def test_check_invalid_digit(self):
        priv_chars = list(KEY1_PRIV_HEX)
        priv_chars[3] = 'i'
        with self.assertRaises(ParseError):
            Secp256k1PrivateKey.from_hex(''.join(priv_chars))

        pub_chars = list(KEY1_PUB_HEX)
        pub_chars[3] = 'i'
        with self.assertRaises(ParseError):
            Secp256k1PublicKey.from_hex(''.join(pub_chars))
 def test_key_signature_validation(self):
     signature, message, pubkey = self.test_key_signing()
     public_key = Secp256k1PublicKey.from_hex(pubkey)
     context = sawtooth_signing.create_context("secp256k1")
     self.assertTrue(context.verify(signature, bytes(message, "utf8"), public_key))
     self.assertFalse(
         context.verify(signature, bytes(message + "foo", "utf8"), public_key)
     )
     other = Secp256k1PublicKey.from_hex(Key().public_key)
     self.assertFalse(context.verify(signature, bytes(message, "utf8"), other))
Exemplo n.º 3
0
 def verify(self, signature, message, public_key=None):
     """Verifies a message was signed by this Key"""
     if public_key is None:
         public_key = self._public_key
     elif isinstance(public_key, str):
         public_key = Secp256k1PublicKey.from_hex(public_key)
     return self._context.verify(signature, message, public_key)
def do_test_verification():
    context = create_context("secp256k1")
    factory = CryptoFactory(context)
    pub_key1 = Secp256k1PublicKey.from_hex(KEY1_PUB_HEX)
    context.verify(signature=MSG1_KEY1_SIG,
                   message=MSG1.encode(),
                   public_key=pub_key1)
def is_valid_batch(batch):
    # validate batch signature
    header = BatchHeader()
    header.ParseFromString(batch.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_hex(header.signer_public_key)
    if not context.verify(batch.header_signature,
                          batch.header,
                          public_key):
        LOGGER.debug("batch failed signature validation: %s",
                     batch.header_signature)
        return False

    # validate all transactions in batch
    for txn in batch.transactions:
        if not is_valid_transaction(txn):
            return False

        txn_header = TransactionHeader()
        txn_header.ParseFromString(txn.header)
        if txn_header.batcher_public_key != header.signer_public_key:
            LOGGER.debug("txn batcher public_key does not match signer"
                         "public_key for batch: %s txn: %s",
                         batch.header_signature,
                         txn.header_signature)
            return False

    return True
Exemplo n.º 6
0
def verify_nonce(nonce, checksum, message, hex_public_key):
    ##message is hex encoded
    message = binascii.unhexlify(message)
    public_key = Secp256k1PublicKey.from_hex(hex_public_key)
    unserialized = public_key.secp256k1_public_key.ecdsa_deserialize(message)
    result = public_key.secp256k1_public_key.ecdsa_verify(str(nonce).encode(), unserialized)
    return result
Exemplo n.º 7
0
    def _validate_user(self, restrict=False):
        # validate user incase of update

        self.key_file = self._get_key_file()
        pub_key_file = self._get_pub_key_file()
        if os.path.isfile(pub_key_file):
            try:
                with open(pub_key_file) as fd:
                        self.pub_key_str = fd.read().strip()
            except OSError:
                    raise Exception(
                        'Failed to read public key {key} of user {user}'.format(key=pub_key_file, user=self.user)
                    )
        else:
            raise Exception('Unable to find public kye {key} of user {user}'.format(key=pub_key_file, user=self.user))

        username, tag, priv_key = self._get_user_from_block_chain()
        private_key = Secp256k1PrivateKey.from_hex(priv_key)
        public_key = Secp256k1PublicKey(private_key.secp256k1_private_key.pubkey)

        if self.pub_key_str == public_key.as_hex():
            import pdb;pdb.set_trace()
            if restrict and tag != 'admin':
                raise Exception('Only Admin type users are allowed to perform these operations')
            print('Validation successful')
            return

        raise Exception(
            'Should have correct public keyfile {file} to create user'.format(file=pub_key_file))
Exemplo n.º 8
0
def is_valid_batch(batch):
    # validate batch signature
    header = BatchHeader()
    header.ParseFromString(batch.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_hex(header.signer_public_key)
    if not context.verify(batch.header_signature, batch.header, public_key):
        LOGGER.debug("batch failed signature validation: %s",
                     batch.header_signature)
        return False

    # validate all transactions in batch
    for txn in batch.transactions:
        if not is_valid_transaction(txn):
            return False

        txn_header = TransactionHeader()
        txn_header.ParseFromString(txn.header)
        if txn_header.batcher_public_key != header.signer_public_key:
            LOGGER.debug(
                "txn batcher public_key does not match signer"
                "public_key for batch: %s txn: %s", batch.header_signature,
                txn.header_signature)
            return False

    return True
Exemplo n.º 9
0
 def assertIsPublicKeyBytes(self, key):
     """Sanity checks a public key in bytes"""
     self.assertIsInstance(key, bytes)
     self.assertEqual(len(key), PUBLIC_KEY_LENGTH)
     key = Secp256k1PublicKey.from_hex(str(binascii.hexlify(key), "ascii"))
     self.assertIsPublicKeySecp256k1(key)
     return key
Exemplo n.º 10
0
 def assertIsPublicKeyHex(self, key):
     """Sanity checks a hexidecimal string public key"""
     self.assertIsInstance(key, str)
     self.assertTrue(PUBLIC_KEY_PATTERN.match(key))
     key = Secp256k1PublicKey.from_hex(key)
     self.assertIsPublicKeySecp256k1(key)
     return key
Exemplo n.º 11
0
def verify_signature(message, signature, public_key):
    try:
        context = create_context("secp256k1")
        pubkey = Secp256k1PublicKey.from_hex(public_key)
        result = context.verify(signature,message.encode(),pubkey)
        return result 
    except Exception:
        return False
    def test_hex_key(self):
        priv_key = Secp256k1PrivateKey.from_hex(KEY1_PRIV_HEX)
        self.assertEqual(priv_key.get_algorithm_name(), "secp256k1")
        self.assertEqual(priv_key.as_hex(), KEY1_PRIV_HEX)

        pub_key = Secp256k1PublicKey.from_hex(KEY1_PUB_HEX)
        self.assertEqual(pub_key.get_algorithm_name(), "secp256k1")
        self.assertEqual(pub_key.as_hex(), KEY1_PUB_HEX)
    def test_verification(self):
        context = create_context("secp256k1")
        self.assertEqual(context.get_algorithm_name(), "secp256k1")

        pub_key1 = Secp256k1PublicKey.from_hex(KEY1_PUB_HEX)
        self.assertEqual(pub_key1.get_algorithm_name(), "secp256k1")
        self.assertEqual(pub_key1.as_hex(), KEY1_PUB_HEX)

        result = context.verify(MSG1_KEY1_SIG, MSG1.encode(), pub_key1)
        self.assertEqual(result, True)
    def test_verification_error(self):
        context = create_context("secp256k1")
        self.assertEqual(context.get_algorithm_name(), "secp256k1")

        pub_key1 = Secp256k1PublicKey.from_hex(KEY1_PUB_HEX)
        self.assertEqual(pub_key1.get_algorithm_name(), "secp256k1")
        self.assertEqual(pub_key1.as_hex(), KEY1_PUB_HEX)

        # This signature doesn't match for MSG1/KEY1
        result = context.verify(MSG2_KEY2_SIG, MSG1.encode(), pub_key1)
        self.assertEqual(result, False)
Exemplo n.º 15
0
    def generate_key_pair():
        """
        Generate public and private key pair.

        Returns:
            Generated key pair in bytes.
        """
        private_key_obj = Secp256k1PrivateKey.new_random()
        public_key_obj = Secp256k1PublicKey(
            private_key_obj.secp256k1_private_key.pubkey)

        return private_key_obj.as_bytes(), public_key_obj.as_bytes()
Exemplo n.º 16
0
    def _public_key_bytes_to_object(public_key):
        """
        Public key bytes to object.

        Args:
            public_key (bytes): secp256k1 public key in bytes

        Returns:
            public key object
        """
        return Secp256k1PublicKey(
            secp256k1.PublicKey(public_key, raw=True, ctx=__CTX__))
Exemplo n.º 17
0
    def __init__(self, private_key=None, public_key=None):
        """
        Constructor for ``ECDSA`` key pair. If only private key available then public key will be generate from private.

        Args:
            private_key (bytes): secp256k1 private key
            public_key (bytes, optional): secp256k1 public key
        """
        if private_key and public_key:
            self._private_key = private_key
            self._public_key = public_key

            self._private_key_obj = self._private_key_bytes_to_object(
                private_key=self._private_key)
            self._public_key_obj = self._public_key_bytes_to_object(
                public_key=self._public_key)

        elif private_key:
            self._private_key = private_key

            self._private_key_obj = self._private_key_bytes_to_object(
                private_key=self._private_key)
            self._public_key_obj = Secp256k1PublicKey(
                self._private_key_obj.secp256k1_private_key.pubkey)

            self._public_key = self._public_key_obj.as_bytes()

        elif public_key:
            self._public_key = public_key
            self._public_key_obj = self._public_key_bytes_to_object(
                public_key=self._public_key)

        if private_key:
            self._private_key_hex = self._private_key.hex()
        else:
            self._private_key_hex = None

        self._public_key_hex = self._public_key.hex()

        self._address = generate_address(RemmeFamilyName.PUBLIC_KEY.value,
                                         self._public_key)
        self._key_type = KeyType.ECDSA

        super(ECDSA, self).__init__(
            private_key=private_key if private_key else None,
            public_key=self._public_key,
            private_key_hex=self._private_key_hex,
            public_key_hex=self._public_key_hex,
            key_type=self._key_type,
            address=self._address,
        )
Exemplo n.º 18
0
    def __init__(self, private_key=None, public_key=None):
        """
        Key() -- generates a new key
        Key(private_key:str) -- Uses the private key passed
        """
        self._context = create_context(ELLIPTIC_CURVE_ALGORITHM)

        if private_key is None and public_key is None:
            private_key = Secp256k1PrivateKey.new_random()
        if isinstance(private_key, str):
            private_key = Secp256k1PrivateKey.from_hex(private_key)
        if isinstance(public_key, str):
            public_key = Secp256k1PublicKey.from_hex(public_key)
        if public_key is None and private_key is not None:
            public_key = self._context.get_public_key(private_key)

        self._public_key = public_key
        self._private_key = private_key
Exemplo n.º 19
0
def is_valid_block(block):
    # validate block signature
    header = BlockHeader()
    header.ParseFromString(block.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_hex(header.signer_public_key)
    if not context.verify(block.header_signature, block.header, public_key):
        LOGGER.debug("block failed signature validation: %s",
                     block.header_signature)
        return False

    # validate all batches in block. These are not all batches in the
    # batch_ids stored in the block header, only those sent with the block.
    if not all(map(is_valid_batch, block.batches)):
        return False

    return True
    def verify_wait_certificate(cls, certificate, poet_public_key):
        # Since the signing module uses a hex-encoded string as the canonical
        # format for public keys and we should be handed a public key that was
        # part of signup information created by us, don't bother decoding
        # the public key.
        try:
            poet_public_key = Secp256k1PublicKey.from_hex(poet_public_key)
        except ParseError:
            raise \
                ValueError(
                    'Invalid signup data. Badly formatted poet key(s).')

        if not \
            cls._context.verify(
                certificate.signature,
                certificate.serialize().encode(),
                poet_public_key):
            raise ValueError('Wait certificate signature does not match')
Exemplo n.º 21
0
    def verify_wait_certificate(cls, certificate, poet_public_key):
        # Since the signing module uses a hex-encoded string as the canonical
        # format for public keys and we should be handed a public key that was
        # part of signup information created by us, don't bother decoding
        # the public key.
        try:
            poet_public_key = Secp256k1PublicKey.from_hex(poet_public_key)
        except ParseError:
            raise \
                ValueError(
                    'Invalid signup data. Badly formatted poet key(s).')

        if not \
            cls._context.verify(
                certificate.signature,
                certificate.serialize().encode(),
                poet_public_key):
            raise ValueError('Wait certificate signature does not match')
Exemplo n.º 22
0
    def __init__(self, base_url, keyfile=None):

        self._base_url = base_url
        if keyfile is None:
            self._signer = None
            return

        try:
            with open(keyfile) as fd:
                private_key_str = fd.read().strip()
        except OSError as err:
            raise Exception('Failed to read private key {}: {}'.format(keyfile, str(err)))

        try:
            self.private_key = Secp256k1PrivateKey.from_hex(private_key_str)
            self.public_key = Secp256k1PublicKey(self.private_key.secp256k1_private_key.pubkey)
        except ParseError as e:
            raise Exception('Unable to load private key: {}'.format(str(e)))

        self._signer = CryptoFactory(create_context('secp256k1')).new_signer(self.private_key)
Exemplo n.º 23
0
def is_valid_block(block):
    # validate block signature
    header = BlockHeader()
    header.ParseFromString(block.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_hex(header.signer_public_key)
    if not context.verify(block.header_signature,
                          block.header,
                          public_key):
        LOGGER.debug("block failed signature validation: %s",
                     block.header_signature)
        return False

    # validate all batches in block. These are not all batches in the
    # batch_ids stored in the block header, only those sent with the block.
    if not all(map(is_valid_batch, block.batches)):
        return False

    return True
Exemplo n.º 24
0
def ecdsa_signature_verify(public_key, signature, raw_message):
    secp_public = Secp256k1PublicKey.from_hex(public_key)
    #unhexlify signature

    try:
        signature = binascii.unhexlify(signature)
    except Exception as e:
        logging.error("Signatures are not in valid hex format")
        raise ApiInternalError(e)

    unserialized = secp_public.secp256k1_public_key.ecdsa_deserialize(signature)


    if isinstance(raw_message, int):
        raw_message = str(raw_message)

    if isinstance(raw_message, str):
        raw_message = raw_message.encode()

    return secp_public.secp256k1_public_key.ecdsa_verify(raw_message, unserialized)
Exemplo n.º 25
0
def is_valid_transaction(txn):
    # validate transactions signature
    header = TransactionHeader()
    header.ParseFromString(txn.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_hex(header.signer_public_key)
    if not context.verify(txn.header_signature, txn.header, public_key):
        LOGGER.debug("transaction signature invalid for txn: %s",
                     txn.header_signature)
        return False

    # verify the payload field matches the header
    txn_payload_sha512 = hashlib.sha512(txn.payload).hexdigest()
    if txn_payload_sha512 != header.payload_sha512:
        LOGGER.debug(
            "payload doesn't match payload_sha512 of the header"
            "for txn: %s", txn.header_signature)
        return False

    return True
def is_valid_consensus_message(message_envelope):
    # validate consensus message signature
    header = ConsensusPeerMessageHeader()
    header.ParseFromString(message_envelope.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_bytes(header.signer_public_key)
    if not context.verify(message_envelope.header_signature,
                          message_envelope.header,
                          public_key):
        LOGGER.debug("message signature invalid for message: %s",
                     message_envelope.header_signature)
        return False

    # verify the message field matches the header
    message_sha512 = hashlib.sha512(message_envelope.message).digest()
    if message_sha512 != header.message_sha512:
        LOGGER.debug("message doesn't match message_sha512 of the header for"
                     "message envelope: %s", message_envelope.header_signature)
        return False

    return True
Exemplo n.º 27
0
def is_valid_transaction(txn):
    # validate transactions signature
    header = TransactionHeader()
    header.ParseFromString(txn.header)

    context = create_context('secp256k1')
    public_key = Secp256k1PublicKey.from_hex(header.signer_public_key)
    if not context.verify(txn.header_signature,
                          txn.header,
                          public_key):
        LOGGER.debug("transaction signature invalid for txn: %s",
                     txn.header_signature)
        return False

    # verify the payload field matches the header
    txn_payload_sha512 = hashlib.sha512(txn.payload).hexdigest()
    if txn_payload_sha512 != header.payload_sha512:
        LOGGER.debug("payload doesn't match payload_sha512 of the header"
                     "for txn: %s", txn.header_signature)
        return False

    return True
Exemplo n.º 28
0
def _check_signature(obj, signature, sender_key_str):
    publicKey = Secp256k1PublicKey.from_hex(sender_key_str)
    token_serialized = str(cbor.dumps(obj, sort_keys=True)).encode('utf-8')
    if not create_context('secp256k1').verify(signature, token_serialized,
                                              publicKey):
        raise InvalidTransaction('Invalid signature.')
Exemplo n.º 29
0
 def get_public_hex_secp256k1(public_hex_string):
     """Return and instance of a sawtooth public key"""
     return Secp256k1PublicKey.from_hex(public_hex_string)
Exemplo n.º 30
0
    def handle(self, connection_id, message_content):
        """
        When the validator receives an AuthorizationChallengeSubmit message, it
        will verify the public key against the signature. If the public key is
        verified, the requested roles will be checked against the stored roles
        to see if the public key is included in the policy. If the node’s
        response is accepted, the node’s public key will be stored and the
        requester may start sending messages for the approved roles.

        If the requester wanted a role that is either not available on the
        endpoint, the requester does not have access to one of the roles
        requested, or the previous message was not an
        AuthorizationChallengeRequest, the challenge will be rejected and the
        connection will be closed.
        """
        if self._network.get_connection_status(connection_id) != \
                ConnectionStatus.AUTH_CHALLENGE_REQUEST:
            LOGGER.debug(
                "Connection's previous message was not a"
                " AuthorizationChallengeRequest, Remove connection to"
                "%s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        auth_challenge_submit = AuthorizationChallengeSubmit()
        auth_challenge_submit.ParseFromString(message_content)

        try:
            payload = self._challenge_payload_cache[connection_id]
        except KeyError:
            LOGGER.debug(
                "Connection's challenge payload expired before a"
                "response was received. %s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        context = create_context('secp256k1')
        try:
            public_key = Secp256k1PublicKey.from_hex(
                auth_challenge_submit.public_key)
        except ParseError:
            LOGGER.warning(
                'Authorization Challenge Request cannot be '
                'verified. Invalid public key %s',
                auth_challenge_submit.public_key)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        if not context.verify(auth_challenge_submit.signature, payload,
                              public_key):
            LOGGER.warning(
                "Signature was not able to be verifed. Remove "
                "connection to %s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        roles = self._network.roles
        for role in auth_challenge_submit.roles:
            if role == RoleType.Value("NETWORK") or role == \
                    RoleType.Value("ALL"):
                permitted = False
                if "network" in roles:
                    permitted = self._permission_verifier.check_network_role(
                        auth_challenge_submit.public_key)
                if not permitted:
                    return AuthorizationChallengeSubmitHandler \
                            ._network_violation_result()

        self._network.update_connection_public_key(
            connection_id, auth_challenge_submit.public_key)

        if RoleType.Value("NETWORK") in auth_challenge_submit.roles:
            # Need to send ConnectionRequest to authorize ourself with the
            # connection if they initialized the connection
            try:
                is_outbound_connection = self._network.is_outbound_connection(
                    connection_id)
            except KeyError:
                # Connection has gone away, drop message
                return HandlerResult(HandlerStatus.DROP)

            if not is_outbound_connection:
                self._network.send_connect_request(connection_id)
            else:
                # If this is an outbound connection, authorization is complete
                # for both connections and peering/topology build out can
                # begin.
                self._gossip.connect_success(connection_id)

        auth_challenge_result = AuthorizationChallengeResult(
            roles=[RoleType.Value("NETWORK")])

        LOGGER.debug("Connection: %s is approved", connection_id)
        self._network.update_connection_status(connection_id,
                                               ConnectionStatus.CONNECTED)
        return HandlerResult(
            HandlerStatus.RETURN,
            message_out=auth_challenge_result,
            message_type=validator_pb2.Message.AUTHORIZATION_CHALLENGE_RESULT)
Exemplo n.º 31
0
    def _store_public_key_for_other(self, context, signer_pubkey, transaction_payload):
        """
        Store public key for other account.

        The transaction for account which want to pay for other account public keys storing.

        A first account -> send payload -> A second account -> send transaction with first account's public key,
        but sign and pay for storing on own -> Remme-core.

        So Remme core charges tokens from a second account, but store a first account's public key.
        Public key owner here is a first account.

        Arguments:
            context (sawtooth_sdk.processor.context): context to store updated state (blockchain data).
            signer_pubkey: transaction sender public key.
            transaction_payload (pub_key_pb2.NewPubKeyStoreAndPayPayload): payload for storing public key for other.
        """
        new_public_key_payload = transaction_payload.pub_key_payload

        owner_public_key_as_bytes = transaction_payload.owner_public_key
        owner_public_key_as_hex = owner_public_key_as_bytes.hex()

        owner_secp256k1_public_key = Secp256k1PublicKey.from_hex(owner_public_key_as_hex)

        is_owner_public_key_payload_signature_valid = Secp256k1Context().verify(
            signature=transaction_payload.signature_by_owner.hex(),
            message=new_public_key_payload.SerializeToString(),
            public_key=owner_secp256k1_public_key,
        )
        if not is_owner_public_key_payload_signature_valid:
            raise InvalidTransaction('Public key owner\'s signature is invalid.')

        processor = self._get_public_key_processor(transaction_payload=transaction_payload.pub_key_payload)

        if not processor.verify():
            raise InvalidTransaction('Payed public key has invalid signature.')

        public_key = processor.get_public_key()
        public_key_to_store_address = self.make_address_from_data(public_key)

        public_key_to_store_owner_address = AccountHandler().make_address_from_data(owner_public_key_as_hex)
        payer_for_storing_address = AccountHandler().make_address_from_data(signer_pubkey)

        public_key_information, public_key_to_store_owner_account, payer_for_storing_account = get_multiple_data(context, [
            (public_key_to_store_address, PubKeyStorage),
            (public_key_to_store_owner_address, Account),
            (payer_for_storing_address, Account),
        ])

        if public_key_information:
            raise InvalidTransaction('This public key is already registered.')

        if public_key_to_store_owner_account is None:
            public_key_to_store_owner_account = Account()

        if payer_for_storing_account is None:
            payer_for_storing_account = Account()

        if not self._is_public_key_validity_exceeded(
            valid_from=new_public_key_payload.valid_from,
            valid_to=new_public_key_payload.valid_to,
        ):
            raise InvalidTransaction('The public key validity exceeds the maximum value.')

        public_key_information = PubKeyStorage()
        public_key_information.owner = owner_public_key_as_hex
        public_key_information.payload.CopyFrom(new_public_key_payload)
        public_key_information.is_revoked = False

        state = {
            public_key_to_store_owner_address: public_key_to_store_owner_account,
            payer_for_storing_address: payer_for_storing_account,
            public_key_to_store_address: public_key_information,
        }

        charging_state = self._charge_for_storing(context=context, address_from=payer_for_storing_address)
        if charging_state is not None:
            state.update(charging_state)

        public_key_to_store_owner_account = self._store_public_key_to_account(
            public_key_to_store_address=public_key_to_store_address,
            public_key_to_store_owner_account=public_key_to_store_owner_account,
        )

        state.update({
            public_key_to_store_owner_address: public_key_to_store_owner_account,
        })

        return state
    def create_wait_certificate(cls,
                                sealed_signup_data,
                                wait_timer,
                                block_hash):
        with cls._lock:
            # Extract keys from the 'sealed' signup data
            if sealed_signup_data is None:
                raise ValueError('Sealed Signup Data is None')
            signup_data = \
                json2dict(
                    base64.b64decode(sealed_signup_data.encode()).decode())
            poet_private_key = signup_data['poet_private_key']
            poet_public_key = signup_data['poet_public_key']

            if poet_private_key is None or poet_public_key is None:
                raise \
                    ValueError(
                        'Invalid signup data. No poet key(s).')

            try:
                poet_public_key = Secp256k1PublicKey.from_hex(poet_public_key)
                poet_private_key = Secp256k1PrivateKey.from_hex(
                    poet_private_key)
            except ParseError:
                raise \
                    ValueError(
                        'Invalid signup data. Badly formatted poet key(s).')

            # Several criteria need to be met before we can create a wait
            # certificate:
            # 1. This signup data was used to sign this timer.
            #    i.e. the key sealed / unsealed by the TEE signed this
            #    wait timer.
            # 2. This timer has expired
            # 3. This timer has not timed out
            #
            # In a TEE implementation we would check HW counter agreement.
            # We can't usefully simulate a HW counter though.
            # i.e. wait_timer.counter_value == signup_data.counter.value

            #
            # Note - we make a concession for the genesis block (i.e., a wait
            # timer for which the previous certificate ID is the Null
            # identifier) in that we don't require the timer to have expired
            # and we don't worry about the timer having timed out.

            if wait_timer is None or \
                    not cls._context.verify(
                        wait_timer.signature,
                        wait_timer.serialize().encode(),
                        poet_public_key):
                raise \
                    ValueError(
                        'Validator is not using the current wait timer')

            is_not_genesis_block = \
                (wait_timer.previous_certificate_id != NULL_BLOCK_IDENTIFIER)

            now = time.time()
            expire_time = \
                wait_timer.request_time + \
                wait_timer.duration

            if is_not_genesis_block and now < expire_time:
                raise \
                    ValueError(
                        'Cannot create wait certificate because timer has '
                        'not expired')

            time_out_time = \
                wait_timer.request_time + \
                wait_timer.duration + \
                TIMER_TIMEOUT_PERIOD

            if is_not_genesis_block and time_out_time < now:
                raise \
                    ValueError(
                        'Cannot create wait certificate because timer '
                        'has timed out')

            # Create a random nonce for the certificate.  For our "random"
            # nonce we will take the timer signature, concat that with the
            # current time, JSON-ize it and create a SHA-256 hash over it.
            # Probably not considered random by security professional
            # standards, but it is good enough for the simulator.
            random_string = \
                dict2json({
                    'wait_timer_signature': wait_timer.signature,
                    'now': datetime.datetime.utcnow().isoformat()
                })
            nonce = hashlib.sha256(random_string.encode()).hexdigest()

            # First create a new enclave wait certificate using the data
            # provided and then sign the certificate with the PoET private key
            wait_certificate = \
                EnclaveWaitCertificate.wait_certificate_with_wait_timer(
                    wait_timer=wait_timer,
                    nonce=nonce,
                    block_hash=block_hash)
            wait_certificate.signature = \
                cls._context.sign(
                    wait_certificate.serialize().encode(),
                    poet_private_key)

            # In a TEE implementation we would increment the HW counter here
            # to prevent replay.
            # We can't usefully simulate a HW counter though.

            return wait_certificate
Exemplo n.º 33
0
    def validate_from_dict(self,token):

        _check_format(token,"access token",VALIDATION_FORMAT)

        # state retrival
        device = token['DE']
        result = self._send_request(
            "state?address={}".format(
                self._get_address(device)))

        try:
            encoded_entries = yaml.safe_load(result)["data"]

            data_list =  [
                cbor.loads(base64.b64decode(entry["data"]))
                for entry in encoded_entries
            ]

            state = {x:y[x] for y in data_list for x in y}

        except BaseException:
            return None

        LOGGER.info('checking authorization')
        # check authorization
        capability = token['IC']

        if capability not in state:
            return False

        LOGGER.info('checking delegation chain')
        # delegation chain check
        now = int(time.time())
        resource = token['RE']
        action = token['AC']

        current_token = state[capability]
        parent = current_token['IC']
        while parent != None:
            if parent not in state:
                raise BaseException
            parent_token = state[parent]

            # check time interval
            if now >= int(parent_token['NA']):
                return False
            if now < int(parent_token['NB']):
                return False

            # check access rights
            if resource not in parent_token["AR"]:
                return False
            if action not in parent_token["AR"][resource]:
                return False

            # next
            current_token = parent_token
            parent = current_token['IC']

        LOGGER.info('checking signature')
        # check signature
        signature = token.pop('SI')
        if not create_context('secp256k1').verify(
            signature,
            str(cbor.dumps(token,sort_keys=True)).encode('utf-8'),
            Secp256k1PublicKey.from_hex(state[capability]['SU'])
            ):
            return False

        return True
Exemplo n.º 34
0
def test_verification(benchmark):
    context = create_context("secp256k1")
    factory = CryptoFactory(context)
    pub_key1 = Secp256k1PublicKey.from_hex(KEY1_PUB_HEX)
    result = benchmark(context.verify, MSG1_KEY1_SIG, MSG1.encode(), pub_key1)
    assert result == True
Exemplo n.º 35
0
    def create_wait_certificate(cls,
                                sealed_signup_data,
                                wait_timer,
                                block_hash):
        with cls._lock:
            # Extract keys from the 'sealed' signup data
            if sealed_signup_data is None:
                raise ValueError('Sealed Signup Data is None')
            signup_data = \
                json2dict(
                    base64.b64decode(sealed_signup_data.encode()).decode())
            poet_private_key = signup_data['poet_private_key']
            poet_public_key = signup_data['poet_public_key']

            if poet_private_key is None or poet_public_key is None:
                raise \
                    ValueError(
                        'Invalid signup data. No poet key(s).')

            try:
                poet_public_key = Secp256k1PublicKey.from_hex(poet_public_key)
                poet_private_key = Secp256k1PrivateKey.from_hex(
                    poet_private_key)
            except ParseError:
                raise \
                    ValueError(
                        'Invalid signup data. Badly formatted poet key(s).')

            # Several criteria need to be met before we can create a wait
            # certificate:
            # 1. This signup data was used to sign this timer.
            #    i.e. the key sealed / unsealed by the TEE signed this
            #    wait timer.
            # 2. This timer has expired
            # 3. This timer has not timed out
            #
            # In a TEE implementation we would check HW counter agreement.
            # We can't usefully simulate a HW counter though.
            # i.e. wait_timer.counter_value == signup_data.counter.value

            #
            # Note - we make a concession for the genesis block (i.e., a wait
            # timer for which the previous certificate ID is the Null
            # identifier) in that we don't require the timer to have expired
            # and we don't worry about the timer having timed out.

            if wait_timer is None or \
                    not cls._context.verify(
                        wait_timer.signature,
                        wait_timer.serialize().encode(),
                        poet_public_key):
                raise \
                    ValueError(
                        'Validator is not using the current wait timer')

            is_not_genesis_block = \
                (wait_timer.previous_certificate_id !=
                 NULL_BLOCK_IDENTIFIER)

            now = time.time()
            expire_time = \
                wait_timer.request_time + \
                wait_timer.duration

            if is_not_genesis_block and now < expire_time:
                raise \
                    ValueError(
                        'Cannot create wait certificate because timer has '
                        'not expired')

            time_out_time = \
                wait_timer.request_time + \
                wait_timer.duration + \
                TIMER_TIMEOUT_PERIOD

            if is_not_genesis_block and time_out_time < now:
                raise \
                    ValueError(
                        'Cannot create wait certificate because timer '
                        'has timed out')

            # Create a random nonce for the certificate.  For our "random"
            # nonce we will take the timer signature, concat that with the
            # current time, JSON-ize it and create a SHA-256 hash over it.
            # Probably not considered random by security professional
            # standards, but it is good enough for the simulator.
            random_string = \
                dict2json({
                    'wait_timer_signature': wait_timer.signature,
                    'now': datetime.datetime.utcnow().isoformat()
                })
            nonce = hashlib.sha256(random_string.encode()).hexdigest()

            # First create a new enclave wait certificate using the data
            # provided and then sign the certificate with the PoET private key
            wait_certificate = \
                EnclaveWaitCertificate.wait_certificate_with_wait_timer(
                    wait_timer=wait_timer,
                    nonce=nonce,
                    block_hash=block_hash)
            wait_certificate.signature = \
                cls._context.sign(
                    wait_certificate.serialize().encode(),
                    poet_private_key)

            # In a TEE implementation we would increment the HW counter here
            # to prevent replay.
            # We can't usefully simulate a HW counter though.

            return wait_certificate
Exemplo n.º 36
0
    def handle(self, connection_id, message_content):
        """
        When the validator receives an AuthorizationChallengeSubmit message, it
        will verify the public key against the signature. If the public key is
        verified, the requested roles will be checked against the stored roles
        to see if the public key is included in the policy. If the node’s
        response is accepted, the node’s public key will be stored and the
        requester may start sending messages for the approved roles.

        If the requester wanted a role that is either not available on the
        endpoint, the requester does not have access to one of the roles
        requested, or the previous message was not an
        AuthorizationChallengeRequest, the challenge will be rejected and the
        connection will be closed.
        """
        if self._network.get_connection_status(connection_id) != \
                ConnectionStatus.AUTH_CHALLENGE_REQUEST:
            LOGGER.debug("Connection's previous message was not a"
                         " AuthorizationChallengeRequest, Remove connection to"
                         "%s",
                         connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        auth_challenge_submit = AuthorizationChallengeSubmit()
        auth_challenge_submit.ParseFromString(message_content)

        try:
            payload = self._challenge_payload_cache[connection_id]
        except KeyError:
            LOGGER.warning("Connection's challenge payload expired before a"
                           "response was received. %s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        context = create_context('secp256k1')
        try:
            public_key = Secp256k1PublicKey.from_hex(
                auth_challenge_submit.public_key)
        except ParseError:
            LOGGER.warning('Authorization Challenge Request cannot be '
                           'verified. Invalid public key %s',
                           auth_challenge_submit.public_key)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        if not context.verify(auth_challenge_submit.signature,
                              payload,
                              public_key):
            LOGGER.warning("Signature was not able to be verified. Remove "
                           "connection to %s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        roles = self._network.roles
        for role in auth_challenge_submit.roles:
            if role == RoleType.Value("NETWORK") or role == \
                    RoleType.Value("ALL"):
                permitted = False
                if "network" in roles:
                    permitted = self._permission_verifier.check_network_role(
                        auth_challenge_submit.public_key)
                if not permitted:
                    return AuthorizationChallengeSubmitHandler \
                        ._network_violation_result()

        self._network.update_connection_public_key(
            connection_id,
            auth_challenge_submit.public_key)

        if RoleType.Value("NETWORK") in auth_challenge_submit.roles:
            # Need to send ConnectionRequest to authorize ourself with the
            # connection if they initialized the connection
            try:
                is_outbound_connection = self._network.is_outbound_connection(
                    connection_id)
            except KeyError:
                # Connection has gone away, drop message
                return HandlerResult(HandlerStatus.DROP)

            if not is_outbound_connection:
                self._network.send_connect_request(connection_id)
            else:
                # If this is an outbound connection, authorization is complete
                # for both connections and peering/topology build out can
                # begin.
                self._gossip.connect_success(connection_id)

        auth_challenge_result = AuthorizationChallengeResult(
            roles=[RoleType.Value("NETWORK")])

        LOGGER.debug("Connection: %s is approved", connection_id)
        self._network.update_connection_status(
            connection_id,
            ConnectionStatus.CONNECTED)
        return HandlerResult(
            HandlerStatus.RETURN,
            message_out=auth_challenge_result,
            message_type=validator_pb2.Message.AUTHORIZATION_CHALLENGE_RESULT)