def test_sign_operation(self): op = Operation(OperationRev(), 'http://example.com/', [PublicKey.from_signing_key(SigningKey.generate())]) user = User.new_keys() with self.assertRaisesRegex(Operation.VerifyError, "object is not signed"): op.verify() user.sign_object(op) self.assertTrue(op.verify()) self.assertEqual(op.public_key, user._public_key)
class TestSingleOperation(TestCase): def setUp(self): self.private_key = SigningKey.generate(curve=NIST256p) self.public_key = PublicKey.from_signing_key(self.private_key) self.operation = Operation(OperationRev(), 'http://example.com/', [self.public_key]) sign_object(self.public_key, self.private_key, self.operation) def test_fields(self): self.assertEqual(self.operation.previous_operation_rev, OperationRev()) self.assertEqual(self.operation.address, 'http://example.com/') self.assertEqual(self.operation.owners, (self.public_key,)) self.assertEqual(self.operation.public_key, self.public_key) # noinspection PyPropertyAccess def test_immutable(self): with self.assertRaisesRegex(AttributeError, "can't set attribute"): self.operation.previous_operation_rev = OperationRev() with self.assertRaisesRegex(AttributeError, "can't set attribute"): self.operation.uuid = uuid4() with self.assertRaisesRegex(AttributeError, "can't set attribute"): self.operation.address = 'http://changed.com/' with self.assertRaisesRegex(AttributeError, "can't set attribute"): self.operation.owners = [] def test_unsigned_raw(self): unsigned_raw = self.operation.unsigned_raw() self.assertIsInstance(unsigned_raw, bytes) self.assertEqual(unsigned_raw[:36], b'\x00\x00\x00\x01' + b'\x00' * 32) self.assertEqual(len(unsigned_raw), 4 + 32 + 16 + 4 + len('http://example.com/') + 4 + 4 + len(self.public_key.der)) def test_raw(self): raw = self.operation.raw() unsigned_raw = self.operation.unsigned_raw() self.assertIsInstance(raw, bytes) self.assertEqual(raw[:len(unsigned_raw)], self.operation.unsigned_raw()) self.assertEqual(len(raw), len(unsigned_raw) + 4 + len(self.public_key.der) + 4 + len(self.operation.signature)) def test_from_raw(self): new_operation = Operation.from_raw(self.operation.raw()) self.assertIsInstance(new_operation, Operation) for attr in ('previous_operation_rev', 'uuid', 'address', 'signature'): self.assertEqual(getattr(new_operation, attr), getattr(self.operation, attr)) self.assertEqual(new_operation.owners_der, self.operation.owners_der) self.assertEqual(new_operation.public_key.der, self.operation.public_key.der) def test_verify(self): self.assertTrue(self.operation.verify()) def test_mangled_raw(self): raw = self.operation.raw() with self.assertRaisesRegex(RawFormatError, "raw input too short"): Operation.from_raw(raw[:-1]) with self.assertRaisesRegex(RawFormatError, "raw input too long"): Operation.from_raw(raw + b'\x00') with self.assertRaisesRegex(Operation.VerifyError, "wrong signature"): mangled_raw = bytearray(raw) mangled_raw[-1] = 0 Operation.from_raw(mangled_raw).verify() with self.assertRaisesRegex(Operation.VerifyError, "wrong object id"): Operation.from_raw(raw).verify_id(b'wrong hash') # wrong hash length with self.assertRaisesRegex(Operation.VerifyError, "wrong object id"): Operation.from_raw(raw).verify_id(sha256(b'wrong hash').digest()) # different hash def test_owners(self): self.operation = Operation(self.operation.previous_operation_rev, self.operation.address, [self.public_key, self.public_key]) sign_object(self.public_key, self.private_key, self.operation) with self.assertRaisesRegex(Operation.VerifyError, "duplicated owners"): self.operation.verify() self.operation = Operation(self.operation.previous_operation_rev, self.operation.address, []) sign_object(self.public_key, self.private_key, self.operation) self.assertTrue(self.operation.verify())