Ejemplo n.º 1
0
 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))
Ejemplo n.º 2
0
 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)
Ejemplo n.º 3
0
    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])
Ejemplo n.º 4
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))
Ejemplo n.º 5
0
    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 {}
Ejemplo n.º 6
0
    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))
Ejemplo n.º 7
0
    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"))
Ejemplo n.º 8
0
    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='
        }
Ejemplo n.º 9
0
    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
Ejemplo n.º 10
0
 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)
Ejemplo n.º 11
0
    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))
Ejemplo n.º 12
0
    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())
Ejemplo n.º 13
0
    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())
Ejemplo n.º 14
0
 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)
Ejemplo n.º 15
0
    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())
Ejemplo n.º 16
0
    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())
Ejemplo n.º 17
0
    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()))
Ejemplo n.º 18
0
    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())
Ejemplo n.º 19
0
    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
Ejemplo n.º 20
0
 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))
Ejemplo n.º 21
0
    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())
Ejemplo n.º 22
0
 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)