def test_create_multisignature_contract(self): """ var priv_key1 = new byte[] { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, }; var priv_key2 = new byte[] { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, }; var kp1 = new KeyPair(priv_key1); var kp2 = new KeyPair(priv_key2); var c = Contract.CreateMultiSigContract(1, new ECPoint[] {kp1.PublicKey, kp2.PublicKey}); Console.WriteLine(c.Script.ToHexString()); Console.WriteLine(c.ScriptHash.ToArray().ToHexString()); """ expected_script = binascii.unhexlify( b'110c2102550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e240c21026ff03b949241ce1dadd43519e6960e0a85b41a69a05c328103aa2bce1594ca1612419ed0dc3a' ) expected_script_hash = types.UInt160( binascii.unhexlify(b'a72d98260b3dd7d7dd4f733490b9c16b5c352644')) keypair1 = cryptography.KeyPair(private_key=b'\x01' * 32) keypair2 = cryptography.KeyPair(private_key=b'\x02' * 32) contract = contracts.Contract.create_multisig_contract( 1, [keypair1.public_key, keypair2.public_key]) self.assertEqual(expected_script, contract.script) self.assertEqual(str(expected_script_hash), str(contract.script_hash))
def test_create_multisignature_contract(self): """ var priv_key1 = new byte[] { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, }; var priv_key2 = new byte[] { 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, }; var kp1 = new KeyPair(priv_key1); var kp2 = new KeyPair(priv_key2); var c = Contract.CreateMultiSigContract(1, new ECPoint[] {kp1.PublicKey, kp2.PublicKey}); """ expected_script = binascii.unhexlify( b'110c2102550f471003f3df97c3df506ac797f6721fb1a1fb7b8f6f83d224498a65c88e240c21026ff03b949241ce1dadd43519e6960e0a85b41a69a05c328103aa2bce1594ca16120b41138defaf' ) expected_script_hash = types.UInt160( binascii.unhexlify(b'205bc1a9d199eecb30ab0c1ff027456ce7998e1f')) keypair1 = cryptography.KeyPair(private_key=b'\x01' * 32) keypair2 = cryptography.KeyPair(private_key=b'\x02' * 32) contract = contracts.Contract.create_multisig_contract( 1, [keypair1.public_key, keypair2.public_key]) self.assertEqual(expected_script, contract.script) self.assertEqual(expected_script_hash, contract.script_hash)
def test_assign_and_get_role(self): engine = test_engine(has_snapshot=True, has_container=True) # set signers list to our committee to pass check_committee() validation engine.script_container.signers = [ payloads.Signer( types.UInt160.from_string( "54166e586e86b9d653bf96f61e6568df7a8ecb50"), payloads.WitnessScope.GLOBAL) ] public_key1 = cryptography.KeyPair(b'\x01' * 32).public_key public_key2 = cryptography.KeyPair(b'\x02' * 32).public_key public_key3 = cryptography.KeyPair(b'\x03' * 32).public_key c = contracts.DesignationContract() c.designate_as_role(engine, contracts.DesignateRole.STATE_VALIDATOR, [public_key1, public_key2]) c.designate_as_role(engine, contracts.DesignateRole.ORACLE, [public_key3]) index = engine.snapshot.persisting_block.index + 1 state_nodes = c.get_designated_by_role( engine.snapshot, contracts.DesignateRole.STATE_VALIDATOR, index) self.assertEqual(2, len(state_nodes)) self.assertIn(public_key1, state_nodes) self.assertIn(public_key2, state_nodes) oracle_nodes = c.get_designated_by_role(engine.snapshot, contracts.DesignateRole.ORACLE, index) self.assertEqual(1, len(oracle_nodes)) self.assertEqual(public_key3, oracle_nodes[0])
def test_multisig_verify_helper_verification(self): engine = test_engine() message = vm.ByteStringStackItem(b'hello') kp1 = cryptography.KeyPair(private_key=b'\x01' * 32) kp2 = cryptography.KeyPair(private_key=b'\x02' * 32) sig1 = cryptography.sign(message.to_array(), kp1.private_key) sig2 = cryptography.sign(message.to_array(), kp2.private_key) # quick pre-check the verify_signature function actually passes self.assertTrue( cryptography.verify_signature(message.to_array(), sig1, kp1.public_key.encode_point(False), cryptography.ECCCurve.SECP256R1)) self.assertTrue( cryptography.verify_signature(message.to_array(), sig2, kp2.public_key.encode_point(False), cryptography.ECCCurve.SECP256R1)) # first do a check on regular data (meaning; check sig1 with pub_key1, sig2 with pub_key2) public_keys = [ kp1.public_key.encode_point(False), kp2.public_key.encode_point(False) ] signatures = [sig1, sig2] self.assertTrue( _check_multisig(engine, message, public_keys, signatures, cryptography.ECCCurve.SECP256R1)) # same as previous, but supplying the keys out of order public_keys = [ kp2.public_key.encode_point(False), kp1.public_key.encode_point(False) ] signatures = [sig1, sig2] self.assertFalse( _check_multisig(engine, message, public_keys, signatures, cryptography.ECCCurve.SECP256R1)) # now validate it will try all available public keys for a given signature (for 1-of-2, 3-of-5 like contracts) public_keys = [ kp2.public_key.encode_point(False), kp1.public_key.encode_point(False) ] signatures = [sig1] self.assertTrue( _check_multisig(engine, message, public_keys, signatures, cryptography.ECCCurve.SECP256R1)) # test handling an exception caused by an invalid public key public_keys = [b''] signatures = [sig1] self.assertFalse( _check_multisig(engine, message, public_keys, signatures, cryptography.ECCCurve.SECP256R1))
def __init__(self, password: str, private_key: Optional[bytes] = None, watch_only: bool = False, address: Optional[str] = None, label: Optional[str] = None, lock: bool = False, contract: Optional[contracts.Contract] = None, extra: Optional[Dict[str, Any]] = None): """ Instantiate an account. This constructor should only be directly called when it's desired to create a new account using just a password and a randomly generated private key, otherwise use the alternative constructors """ public_key: Optional[cryptography.ECPoint] = None encrypted_key: Optional[bytes] = None contract_script: Optional[bytes] = None if watch_only: if address is None: raise ValueError( "Creating a watch only account requires an address") else: self.validate_address(address) else: key_pair: cryptography.KeyPair if private_key is None: key_pair = cryptography.KeyPair.generate() private_key = key_pair.private_key else: key_pair = cryptography.KeyPair(private_key) encrypted_key = self.private_key_to_nep2(private_key, password) contract_script = contracts.Contract.create_signature_redeemscript( key_pair.public_key) script_hash = to_script_hash(contract_script) address = address if address else self.script_hash_to_address( script_hash) public_key = key_pair.public_key self.label: Optional[str] = label self.address: str = address self.public_key = public_key self.encrypted_key = encrypted_key self.lock = lock if not isinstance(contract, AccountContract): if contract is not None: contract = AccountContract.from_contract(contract) elif contract_script is not None: default_parameters_list = [ contracts.ContractParameterDefinition( name='signature', type=contracts.ContractParameterType.SIGNATURE) ] contract = AccountContract(contract_script, default_parameters_list) self.contract: Optional[AccountContract] = contract self.extra = extra if extra else {}
def test_is_valid(self): # create a contract cm = contracts.ContractManifest("test_contract") method1 = contracts.ContractMethodDescriptor( name="main_entry", offset=0, parameters=[], return_type=contracts.ContractParameterType.INTEGER, safe=True) cm.abi.methods = [method1] # A contract hash is normally created from a combination of transaction sender (UInt160), NEF checksum and manifest.name # For this test we'll keep it simple and pretend that hash is all zeros dummy_contract_hash = types.UInt160.zero() # a "default" contract has no groups data, which is the same as always allow self.assertTrue(cm.is_valid(dummy_contract_hash)) # now try to add a malicious group member (meaning; the member did not actually sign the ABI) private_key = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' keypair = cryptography.KeyPair(private_key) bad_signature = bytes(64) cm.groups = [ contracts.ContractGroup(keypair.public_key, bad_signature) ] # this time validation should fail self.assertFalse(cm.is_valid(dummy_contract_hash)) # Finally test with a group member that did sign the ABI good_signature = cryptography.sign(dummy_contract_hash.to_array(), keypair.private_key) cm.groups = [ contracts.ContractGroup(keypair.public_key, good_signature) ] self.assertTrue(cm.is_valid(dummy_contract_hash))
def test_is_allowed_based_on_group(self): # We test the group permissions where all methods are allowed to be called # if the 'groups' member is valid. private_key = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' keypair = cryptography.KeyPair(private_key) dummy_contract_hash = types.UInt160.from_string("01" * 20) contract_state = contracts.ContractState(1, contracts.NEF(), contracts.ContractManifest(), 0, dummy_contract_hash) signature = cryptography.sign(contract_state.hash.to_array(), keypair.private_key) contract_state.manifest.groups = [ contracts.ContractGroup(keypair.public_key, signature) ] cpd = contracts.ContractPermissionDescriptor(group=keypair.public_key) cp = contracts.ContractPermission( contract=cpd, methods=contracts.WildcardContainer.create_wildcard()) self.assertTrue(cp.is_allowed(contract_state, "dummy_method")) # now modify the manifest to have a different `groups` attribute such that validation fails public_key = cryptography.ECPoint.deserialize_from_bytes( b'\x00') # ECPoint.Infinity contract_state.manifest.groups = [ contracts.ContractGroup(public_key, signature) ] self.assertFalse(cp.is_allowed(contract_state, "dummy_method"))
def setUpClass(cls) -> None: private_key = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' cls.keypair = cryptography.KeyPair(private_key) # capture from C# cls.expected_json = { 'pubkey': '033d523f36a732974c0f7dbdfafb5206ecd087211366a274190f05b86d357f4bad', 'signature': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' }
def private_key_to_nep2( private_key: bytes, passphrase: str, scrypt_parameters: Optional[wallet.ScryptParameters] = None ) -> bytes: """ Encrypt a private key into a nep2 key. Args: private_key: the key that will be encrypt. passphrase: the password to encrypt the nep2 key. scrypt_parameters: a ScryptParameters object that will be passed to the key derivation function. Returns: the encrypted nep2 key. """ if scrypt_parameters is None: scrypt_parameters = wallet.ScryptParameters() key_pair = cryptography.KeyPair(private_key=private_key) script_hash = to_script_hash( contracts.Contract.create_signature_redeemscript( key_pair.public_key)) address = Account.script_hash_to_address(script_hash) # NEP2 checksum: hash the address twice and get the first 4 bytes first_hash = hashlib.sha256(address.encode("utf-8")).digest() second_hash = hashlib.sha256(first_hash).digest() checksum = second_hash[:4] pwd_normalized = bytes(unicodedata.normalize("NFC", passphrase), "utf-8") derived = hashlib.scrypt(password=pwd_normalized, salt=checksum, n=scrypt_parameters.n, r=scrypt_parameters.r, p=scrypt_parameters.p, dklen=64) derived1 = derived[:32] derived2 = derived[32:] xor_ed = Account._xor_bytes(bytes(private_key), derived1) cipher = AES.new(derived2, AES.MODE_ECB) encrypted = cipher.encrypt(xor_ed) nep2 = bytearray() nep2.extend(NEP_HEADER) nep2.extend(NEP_FLAG) nep2.extend(checksum) nep2.extend(encrypted) # Finally, encode with Base58Check encoded_nep2 = base58.b58encode_check(bytes(nep2)) return encoded_nep2
def test_contract_create_standard_account(self): keypair = cryptography.KeyPair(b'\x01' * 32) engine = test_engine() engine.push(vm.ByteStringStackItem(keypair.public_key.to_array())) engine.invoke_syscall_by_name("System.Contract.CreateStandardAccount") engine.execute() self.assertEqual(1, len(engine.result_stack)) signature_redeem_script = contracts.Contract.create_signature_redeemscript( keypair.public_key) result_item = types.UInt160(engine.result_stack.pop().to_array()) self.assertEqual(to_script_hash(signature_redeem_script), result_item)
def test_is_multsig_contract_invalid_pubkey_count(self): # this is another test where we check for a mismatch between processed public keys and the claimed present # amount but this time for a signature count between push0 <= cnt <= PUSH16 # we re-use the standard create_multisignature_account call keypair = cryptography.KeyPair(private_key=b'\x01' * 32) contract = contracts.Contract.create_multisig_contract(1, [keypair.public_key]) # and modify the claimed public key length from 1 to 255 data = bytearray(contract.script) data[-6] = int(vm.OpCode.PUSH16) - 1 self.assertFalse(contracts.Contract.is_multisig_contract(data)) # and finally we try it again but this time the public key length is in an invalid range data[-6] = int(vm.OpCode.PUSH16) + 1 self.assertFalse(contracts.Contract.is_multisig_contract(data))
def test_contract_is_standard_ok(self): keypair = cryptography.KeyPair(b'\x01' * 32) sig_contract = contracts.Contract.create_signature_contract( keypair.public_key) engine = test_engine(has_snapshot=True) contract = storage.ContractState( sig_contract.script, contracts.ContractManifest(sig_contract.script_hash)) engine.snapshot.contracts.put(contract) engine.push(vm.ByteStringStackItem(contract.script_hash().to_array())) engine.invoke_syscall_by_name("System.Contract.IsStandard") engine.execute() self.assertEqual(True, engine.result_stack.pop().to_boolean())
def test_verify_secp256r1(self): """ var privkey = new byte[] { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; var message = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; var signature = new byte[] { 56,70,104,22,234,182,23,161,111,25,71,188,12,5,54,28,99,189,8,47,4,82,62,150,57,216,25,130,217,25,123,118,89,149,217,130,12,109,34,125,176,189,142,119,154,140,116,16,32,209,214,87,178,248,214,39,248,29,214,10,205,153,146,111}; var kp = new KeyPair(privkey); Console.WriteLine(Crypto.VerifySignature(message, signature, kp.PublicKey.EncodePoint(false), ECCurve.Secp256r1)); """ message = b'\x01' * 32 priv_key = b'\x02' + b'\x00' * 30 + b'\x01' sig = cryptography.sign(message, priv_key) # from ecdsa import VerifyingKey, SigningKey, curves as ecdsa_curves # import hashlib # sk = SigningKey.from_string(priv_key, curve=ecdsa_curves.NIST256p, hashfunc=hashlib.sha256) # sig = sk.sign(message, hashfunc=hashlib.sha256) kp = cryptography.KeyPair(priv_key) sb = vm.ScriptBuilder() sb.emit_push(sig) sb.emit_push(kp.public_key.encode_point(False)) sb.emit_push(message) sb.emit_syscall( syscall_name_to_int("Neo.Crypto.VerifyWithECDsaSecp256r1")) engine = test_engine() script = vm.Script(sb.to_array()) engine.load_script(script) # first test with an invalid interop item. They must be IVerifiable engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) self.assertEqual(vm.BooleanStackItem(True), engine.result_stack.pop())
def test_create_signature_contract(self): """ var priv_key1 = new byte[] { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, }; var kp1 = new KeyPair(priv_key1); var c = Contract.CreateSignatureContract(kp1.PublicKey); Console.WriteLine(c.Script.ToHexString()); """ expected = binascii.unhexlify(b'0c21026ff03b949241ce1dadd43519e6960e0a85b41a69a05c328103aa2bce1594ca164156e7b327') keypair = cryptography.KeyPair(private_key=b'\x01' * 32) contract = contracts.Contract.create_signature_contract(keypair.public_key) self.assertEqual(expected, contract.script)
def test_checkwitness_with_public_key(self): kp = cryptography.KeyPair(b'\x01' * 32) redeemscript = contracts.Contract.create_signature_redeemscript( kp.public_key) intermediate_data = hashlib.sha256(redeemscript).digest() data = hashlib.new('ripemd160', intermediate_data).digest() hash_ = types.UInt160(data=data) engine = test_engine(has_snapshot=True, has_container=False, default_script=True) engine.script_container = TestIVerifiable() engine.script_container.script_hashes = [hash_] engine.push(vm.ByteStringStackItem(kp.public_key.to_array())) engine.invoke_syscall_by_name("System.Runtime.CheckWitness") self.assertEqual(1, len(engine.current_context.evaluation_stack)) item = engine.pop() self.assertTrue(item.to_boolean())
def test_check_multisig_with_ECDSA_Secp256r1(self): engine = test_engine() message = vm.ByteStringStackItem(b'hello') kp1 = cryptography.KeyPair(private_key=b'\x01' * 32) sig1 = cryptography.sign(message.to_array(), kp1.private_key) sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("Neo.Crypto.CheckMultisigWithECDsaSecp256r1")) script = vm.Script(sb.to_array()) engine.load_script(script) # setup the stack for the syscall signatures = vm.ArrayStackItem(engine.reference_counter) signatures.append(vm.ByteStringStackItem(sig1)) public_keys = vm.ArrayStackItem(engine.reference_counter) public_keys.append( vm.ByteStringStackItem(kp1.public_key.encode_point(False))) engine.push(signatures) engine.push(public_keys) engine.push(message) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) self.assertEqual(vm.BooleanStackItem(True), engine.result_stack.pop()) # do the same but change the message such that the signature and key are wrong engine = test_engine() engine.load_script(script) engine.push(signatures) engine.push(public_keys) engine.push(vm.ByteStringStackItem(b'badmessage')) engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) self.assertEqual(vm.BooleanStackItem(False), engine.result_stack.pop())
def test_is_valid(self): # create a default contract cm = contracts.ContractManifest() # a default contract uses a UInt160.zero as contract hash self.assertTrue(cm.is_valid(types.UInt160.zero())) self.assertFalse(cm.is_valid(types.UInt160.from_string("11" * 20))) # now try to add a malicious group member (meaning; the member did not actually sign the ABI) private_key = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' keypair = cryptography.KeyPair(private_key) bad_signature = bytes(64) cm.groups = [ contracts.ContractGroup(keypair.public_key, bad_signature) ] # this time validation should fail self.assertFalse(cm.is_valid(types.UInt160.zero())) # Finally test with a group member that did sign the ABI good_signature = cryptography.sign(cm.abi.contract_hash.to_array(), keypair.private_key) cm.groups = [ contracts.ContractGroup(keypair.public_key, good_signature) ] self.assertTrue(cm.is_valid(types.UInt160.zero()))
def test_checkwitness_custom_groups(self): """ We need to setup 2 contracts 1) caller_contract: uses a System.Contract.Call to call callee_contract. This will set the calling script hash on the ExecutionContext of the callee_contract 2) callee_contract: uses a System.Runtime.CheckWitness """ engine = test_engine(has_snapshot=True, default_script=False) tx = test_tx() engine.script_container = tx sb = vm.ScriptBuilder() sb.emit_push(tx.sender.to_array()) sb.emit_syscall(syscall_name_to_int("System.Runtime.CheckWitness")) callee_contract_script = sb.to_array() callee_manifest = contracts.ContractManifest( contract_hash=to_script_hash(callee_contract_script)) callee_manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY) ] callee_contract = storage.ContractState(callee_contract_script, callee_manifest) sb = vm.ScriptBuilder() sb.emit(vm.OpCode.NEWARRAY0) # args (empty array) sb.emit_push('test_func') # target method name sb.emit_push(callee_contract.script_hash().to_array()) # contract hash sb.emit_syscall(syscall_name_to_int("System.Contract.Call")) caller_script = sb.to_array() caller_manifest = contracts.ContractManifest( contract_hash=to_script_hash(caller_script)) keypair = cryptography.KeyPair(private_key=b'\x01' * 32) signature = cryptography.sign(caller_script, keypair.private_key) caller_manifest.groups = [ contracts.ContractGroup(public_key=keypair.public_key, signature=signature) ] caller_contract = storage.ContractState(caller_script, caller_manifest) engine.snapshot.contracts.put(caller_contract) engine.snapshot.contracts.put(callee_contract) engine.load_script(vm.Script(caller_script)) tx.signers[0].scope = payloads.WitnessScope.CUSTOM_GROUPS tx.signers[0].allowed_groups = [keypair.public_key] engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertTrue(item.to_boolean()) # now try again but make sure it fails if the public key is not listed in the allowed groups engine = test_engine(has_snapshot=True, default_script=False) tx = test_tx() engine.script_container = tx engine.snapshot.contracts.put(caller_contract) engine.snapshot.contracts.put(callee_contract) engine.load_script(vm.Script(caller_script)) tx.signers[0].scope = payloads.WitnessScope.CUSTOM_GROUPS keypair = cryptography.KeyPair(private_key=b'\x02' * 32) tx.signers[0].allowed_groups = [keypair.public_key] engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertFalse(item.to_boolean())
def private_key_from_nep2( nep2_key: str, passphrase: str, scrypt_parameters: Optional[wallet.ScryptParameters] = None ) -> bytes: """ Decrypt a nep2 key into a private key. Args: nep2_key: the key that will be decrypt. passphrase: the password to decrypt the nep2 key. scrypt_parameters: a ScryptParameters object that will be passed to the key derivation function. Raises: ValueError: if the length of the nep2_key is not valid. ValueError: if it's not possible to decode the nep2_key. ValueError: if the passphrase is incorrect or the version of the account is not valid. Returns: the private key. """ if scrypt_parameters is None: scrypt_parameters = wallet.ScryptParameters() if len(nep2_key) != 58: raise ValueError( f"Please provide a nep2_key with a length of 58 bytes (LEN: {len(nep2_key)})" ) address_hash_size = 4 address_hash_offset = len(NEP_FLAG) + len(NEP_HEADER) try: decoded_key = base58.b58decode_check(nep2_key) except Exception: raise ValueError("Base58decode failure of nep2 key") address_checksum = decoded_key[ address_hash_offset:address_hash_offset + address_hash_size] encrypted = decoded_key[-32:] pwd_normalized = bytes(unicodedata.normalize("NFC", passphrase), "utf-8") derived = hashlib.scrypt(password=pwd_normalized, salt=address_checksum, n=scrypt_parameters.n, r=scrypt_parameters.r, p=scrypt_parameters.p, dklen=64) derived1 = derived[:32] derived2 = derived[32:] cipher = AES.new(derived2, AES.MODE_ECB) decrypted = cipher.decrypt(encrypted) private_key = Account._xor_bytes(decrypted, derived1) # Now check that the address hashes match. If they don't, the password was wrong. key_pair = cryptography.KeyPair(private_key=private_key) script_hash = to_script_hash( contracts.Contract.create_signature_redeemscript( key_pair.public_key)) address = Account.script_hash_to_address(script_hash) first_hash = hashlib.sha256(address.encode("utf-8")).digest() second_hash = hashlib.sha256(first_hash).digest() checksum = second_hash[:4] if checksum != address_checksum: raise ValueError( f"Wrong passphrase or key was encrypted with an address version that is not " f"{settings.network.account_version}") return private_key
def test_is_multsig_contract_ok(self): keypair = cryptography.KeyPair(private_key=b'\x01' * 32) contract = contracts.Contract.create_multisig_contract( 1, [keypair.public_key]) self.assertTrue( contracts.Contract.is_multisig_contract(contract.script))
def test_checkwitness_custom_groups(self): """ We need to setup 2 contracts 1) caller_contract: uses a System.Contract.Call to call callee_contract. This will set the calling script hash on the ExecutionContext of the callee_contract 2) callee_contract: uses a System.Runtime.CheckWitness """ engine = test_engine(has_snapshot=True, default_script=False) tx = test_tx() engine.script_container = tx ''' Create the callee contract, which does a checkwitness on its caller. Checkwitness shall only pass if the caller == "caller_contract" as defined by CustomGroup ''' sb = vm.ScriptBuilder() sb.emit_syscall( syscall_name_to_int("System.Runtime.GetCallingScriptHash") ) # get script hash of "caller_contract" sb.emit_syscall(syscall_name_to_int("System.Runtime.CheckWitness")) callee_contract_script = sb.to_array() callee_nef = contracts.NEF(script=callee_contract_script) callee_contract_name = "callee_contract" callee_manifest = contracts.ContractManifest(callee_contract_name) callee_manifest.abi.methods = [ contracts.ContractMethodDescriptor( "test_func", 0, [], contracts.ContractParameterType.ANY, True) ] callee_contract_hash = contract_hash(tx.sender, callee_nef.checksum, callee_contract_name) callee_contract = contracts.ContractState(1, callee_nef, callee_manifest, 0, callee_contract_hash) sb = vm.ScriptBuilder() sb.emit_dynamic_call(callee_contract.hash, "test_func") caller_script = sb.to_array() caller_nef = contracts.NEF(script=caller_script) caller_contract_name = "caller_contract" caller_manifest = contracts.ContractManifest(caller_contract_name) keypair = cryptography.KeyPair(private_key=b'\x01' * 32) signature = cryptography.sign(caller_script, keypair.private_key) caller_manifest.groups = [ contracts.ContractGroup(public_key=keypair.public_key, signature=signature) ] caller_contract_hash = contract_hash(tx.sender, caller_nef.checksum, caller_contract_name) caller_contract = contracts.ContractState(2, caller_nef, caller_manifest, 0, caller_contract_hash) engine.snapshot.contracts.put(caller_contract) engine.snapshot.contracts.put(callee_contract) engine.load_script(vm.Script(caller_script)) tx.signers[0].scope = payloads.WitnessScope.CUSTOM_GROUPS tx.signers[0].allowed_groups = [keypair.public_key] engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertTrue(item.to_boolean()) # now try again but make sure it fails if the public key is not listed in the allowed groups engine = test_engine(has_snapshot=True, default_script=False) tx = test_tx() engine.script_container = tx engine.snapshot.contracts.put(caller_contract) engine.snapshot.contracts.put(callee_contract) engine.load_script(vm.Script(caller_script)) tx.signers[0].scope = payloads.WitnessScope.CUSTOM_GROUPS keypair = cryptography.KeyPair(private_key=b'\x02' * 32) tx.signers[0].allowed_groups = [keypair.public_key] engine.execute() self.assertEqual(vm.VMState.HALT, engine.state) self.assertEqual(1, len(engine.result_stack)) item = engine.result_stack.pop() self.assertFalse(item.to_boolean())
def setUpClass(cls) -> None: private_key = b'\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01' cls.keypair = cryptography.KeyPair(private_key)