def unseal_signup_data(cls, sealed_signup_data):
        """

        Args:
            sealed_signup_data: Sealed signup data that was returned
                previously in a EnclaveSignupInfo object from a call to
                create_signup_info

        Returns:
            A string The hex encoded PoET public key that was extracted from
            the sealed data
        """

        # Reverse the process we used in creating "sealed" signup info.
        # Specifically, we will do a base 64 decode, which gives us JSON
        # we can convert back to a dictionary we can use to get the
        # data we need
        signup_data = \
            json2dict(base64.b64decode(sealed_signup_data).decode())

        # Since the signing module uses strings for both private (WIF encoded)
        # and public (hex encoded) key canonical formats, we don't have to
        # decode.
        with cls._lock:
            cls._poet_public_key = str(signup_data.get('poet_public_key'))
            cls._poet_private_key = str(signup_data.get('poet_private_key'))
            cls._active_wait_timer = None

            return signup_data.get('poet_public_key')
    def wait_certificate_from_serialized(cls, serialized_certificate,
                                         signature):
        """
        Takes wait certificate that has been serialized to JSON and
        reconstitutes into an EnclaveWaitCertificate object.

        Args:
            serialized_certificate (str): JSON serialized wait certificate
            signature (str): Signature over serialized certificate

        Returns:
            An EnclaveWaitCertificate object
        """
        deserialized_certificate = json2dict(serialized_certificate)

        certificate = \
            EnclaveWaitCertificate(
                duration=float(deserialized_certificate.get('duration')),
                previous_certificate_id=str(
                    deserialized_certificate.get('previous_certificate_id')),
                local_mean=float(deserialized_certificate.get('local_mean')),
                request_time=float(
                    deserialized_certificate.get('request_time')),
                validator_address=str(
                    deserialized_certificate.get('validator_address')),
                nonce=str(deserialized_certificate.get('nonce')),
                block_hash=str(deserialized_certificate.get(
                    'block_hash')),
                signature=signature,
                serialized_certificate=serialized_certificate)

        return certificate
Пример #3
0
    def unseal_signup_data(cls, sealed_signup_data):
        """

        Args:
            sealed_signup_data: Sealed signup data that was returned
                previously in a EnclaveSignupInfo object from a call to
                create_signup_info

        Returns:
            A string The hex encoded PoET public key that was extracted from
            the sealed data
        """

        # Reverse the process we used in creating "sealed" signup info.
        # Specifically, we will do a base 32 decode, which gives us json
        # we can convert back to a dictionary we can use to get the
        # data we need
        signup_data = \
            json2dict(base64.b64decode(sealed_signup_data).decode())

        with cls._lock:
            cls._poet_public_key = \
                signing.decode_pubkey(
                    signup_data.get('poet_public_key'),
                    'hex')
            cls._poet_private_key = \
                signing.decode_privkey(
                    signup_data.get('poet_private_key'),
                    'hex')
            cls._active_wait_timer = None

            return signup_data.get('poet_public_key')
Пример #4
0
    def wait_timer_from_serialized(cls, serialized_timer, signature):
        """
        Takes wait timer that has been serialized to JSON and reconstitutes
        into an EnclaveWaitTimer object.

        Args:
            serialized_timer (str): JSON serialized wait timer
            signature (str): Signature over serialized timer

        Returns:
            An EnclaveWaitTimer object
        """
        deserialized_timer = json2dict(serialized_timer)

        timer = \
            EnclaveWaitTimer(
                validator_address=str(deserialized_timer.get(
                    'validator_address')),
                duration=float(deserialized_timer.get(
                    'duration')),
                previous_certificate_id=str(deserialized_timer.get(
                    'previous_certificate_id')),
                local_mean=float(deserialized_timer.get(
                    'local_mean')),
                signature=signature,
                serialized_timer=serialized_timer)

        timer.request_time = float(deserialized_timer.get('request_time'))

        return timer
Пример #5
0
    def signup_info_from_serialized(cls, serialized_signup_info):
        """
        Takes signup information that has been serialized to JSON and
        reconstitutes into an EnclaveSignupInfo object.

        Args:
            serialized_signup_info: JSON serialized signup info

        Returns:
            An EnclaveSignupInfo object with sealed signup info data
            stripped out as serialized signup info doesn't contain it.
        """
        deserialized_signup_info = json2dict(serialized_signup_info)

        # Note - serialized signup info shouldn't have sealed signup
        # data.
        signup_info = \
            EnclaveSignupInfo(
                poet_public_key=deserialized_signup_info.get(
                    'poet_public_key'),
                proof_data=deserialized_signup_info.get(
                    'proof_data'),
                anti_sybil_id=deserialized_signup_info.get(
                    'anti_sybil_id'),
                serialized_signup_info=serialized_signup_info)

        return signup_info
    def verify_signup_info(cls,
                           signup_info,
                           originator_public_key_hash,
                           most_recent_wait_certificate_id):
        # Verify the attestation verification report signature
        proof_data_dict = json2dict(signup_info.proof_data)
        verification_report = proof_data_dict.get('verification_report')
        if verification_report is None:
            raise ValueError('Verification report is missing from proof data')

        signature = proof_data_dict.get('signature')
        if signature is None:
            raise ValueError('Signature is missing from proof data')

        if not signing.verify(
                verification_report,
                signature,
                cls._report_public_key):
            raise ValueError('Verification report signature is invalid')

        verification_report_dict = json2dict(verification_report)

        # Verify that the verification report contains a PSE manifest status
        # and it is OK
        pse_manifest_status = \
            verification_report_dict.get('pseManifestStatus')
        if pse_manifest_status is None:
            raise \
                ValueError(
                    'Verification report does not contain a PSE manifest '
                    'status')
        if pse_manifest_status != 'OK':
            raise \
                ValueError(
                    'PSE manifest status is {} (i.e., not OK)'.format(
                        pse_manifest_status))

        # Verify that the verification report contains a PSE manifest hash
        # and it is the value we expect
        pse_manifest_hash = \
            verification_report_dict.get('pseManifestHash')
        if pse_manifest_hash is None:
            raise \
                ValueError(
                    'Verification report does not contain a PSE manifest '
                    'hash')

        expected_pse_manifest_hash = \
            base64.b64encode(
                hashlib.sha256(
                    bytes(b'Do you believe in '
                          b'manifest destiny?')).hexdigest()
                .encode()).decode()

        if pse_manifest_hash != expected_pse_manifest_hash:
            raise \
                ValueError(
                    'PSE manifest hash {0} does not match {1}'.format(
                        pse_manifest_hash,
                        expected_pse_manifest_hash))

        # Verify that the verification report contains an enclave quote and
        # that its status is OK
        enclave_quote_status = \
            verification_report_dict.get('isvEnclaveQuoteStatus')
        if enclave_quote_status is None:
            raise \
                ValueError(
                    'Verification report does not contain an enclave quote '
                    'status')
        if enclave_quote_status != 'OK':
            raise \
                ValueError(
                    'Enclave quote status is {} (i.e., not OK)'.format(
                        enclave_quote_status))

        enclave_quote = verification_report_dict.get('isvEnclaveQuoteBody')
        if enclave_quote is None:
            raise \
                ValueError(
                    'Verification report does not contain an enclave quote')

        # Verify that the enclave quote contains a report body with the value
        # we expect (i.e., SHA256(SHA256(OPK)|PPK)
        report_data = '{0}{1}'.format(
            originator_public_key_hash.upper(),
            signup_info.poet_public_key.upper()
        )
        expected_report_body = hashlib.sha256(
            dict2json(report_data).encode()).hexdigest()

        enclave_quote_dict = \
            json2dict(base64.b64decode(enclave_quote).decode())
        report_body = enclave_quote_dict.get('report_body')
        if report_body is None:
            raise ValueError('Enclave quote does not contain a report body')

        if report_body != expected_report_body:
            raise \
                ValueError(
                    'Enclave quote report body {0} does not match {1}'.format(
                        report_body,
                        expected_report_body))

        # Verify that the wait certificate ID in the verification report
        # matches the provided wait certificate ID.  The wait certificate ID
        # is stored in the nonce field.
        nonce = verification_report_dict.get('nonce')
        if nonce is None:
            raise \
                ValueError(
                    'Verification report does not have a nonce')
Пример #7
0
    def verify_signup_info(cls, signup_info, originator_public_key_hash,
                           most_recent_wait_certificate_id):
        # Verify the attestation verification report signature
        proof_data_dict = json2dict(signup_info.proof_data)
        verification_report = proof_data_dict.get('verification_report')
        if verification_report is None:
            raise ValueError('Verification report is missing from proof data')

        signature = proof_data_dict.get('signature')
        if signature is None:
            raise ValueError('Signature is missing from proof data')

        try:
            cls._report_public_key.verify(base64.b64decode(signature.encode()),
                                          verification_report.encode(),
                                          padding.PKCS1v15(), hashes.SHA256())
        except InvalidSignature:
            raise ValueError('Verification report signature is invalid')

        verification_report_dict = json2dict(verification_report)

        # Verify that the verification report contains an ID field
        if 'id' not in verification_report_dict:
            raise ValueError('Verification report does not contain an ID')

        # Verify that the verification report contains an EPID pseudonym and
        # that it matches the anti-Sybil ID
        epid_pseudonym = verification_report_dict.get('epidPseudonym')
        if epid_pseudonym is None:
            raise \
                ValueError(
                    'Verification report does not contain an EPID pseudonym')

        if epid_pseudonym != signup_info.anti_sybil_id:
            raise \
                ValueError(
                    'The anti-Sybil ID in the verification report [{0}] does '
                    'not match the one contained in the signup information '
                    '[{1}]'.format(
                        epid_pseudonym,
                        signup_info.anti_sybil_id))

        # Verify that the verification report contains a PSE manifest status
        # and it is OK
        pse_manifest_status = \
            verification_report_dict.get('pseManifestStatus')
        if pse_manifest_status is None:
            raise \
                ValueError(
                    'Verification report does not contain a PSE manifest '
                    'status')
        if pse_manifest_status.upper() != 'OK':
            raise \
                ValueError(
                    'PSE manifest status is {} (i.e., not OK)'.format(
                        pse_manifest_status))

        # Verify that the verification report contains a PSE manifest hash
        pse_manifest_hash = \
            verification_report_dict.get('pseManifestHash')
        if pse_manifest_hash is None:
            raise \
                ValueError(
                    'Verification report does not contain a PSE manifest '
                    'hash')

        # Verify that the proof data contains evidence payload
        evidence_payload = proof_data_dict.get('evidence_payload')
        if evidence_payload is None:
            raise ValueError('Evidence payload is missing from proof data')

        # Verify that the evidence payload contains a PSE manifest and then
        # use it to make sure that the PSE manifest hash is what we expect
        pse_manifest = evidence_payload.get('pse_manifest')
        if pse_manifest is None:
            raise ValueError('Evidence payload does not include PSE manifest')

        expected_pse_manifest_hash = \
            base64.b64encode(
                hashlib.sha256(
                    pse_manifest.encode()).hexdigest().encode()).decode()

        if pse_manifest_hash.upper() != expected_pse_manifest_hash.upper():
            raise \
                ValueError(
                    'PSE manifest hash {0} does not match {1}'.format(
                        pse_manifest_hash,
                        expected_pse_manifest_hash))

        # Verify that the verification report contains an enclave quote status
        # and the status is OK
        enclave_quote_status = \
            verification_report_dict.get('isvEnclaveQuoteStatus')
        if enclave_quote_status is None:
            raise \
                ValueError(
                    'Verification report does not contain an enclave quote '
                    'status')
        if enclave_quote_status.upper() != 'OK':
            raise \
                ValueError(
                    'Enclave quote status is {} (i.e., not OK)'.format(
                        enclave_quote_status))

        # Verify that the verification report contains an enclave quote
        enclave_quote = verification_report_dict.get('isvEnclaveQuoteBody')
        if enclave_quote is None:
            raise \
                ValueError(
                    'Verification report does not contain an enclave quote')

        # Verify that the enclave quote contains a report body with the value
        # we expect (i.e., SHA256(SHA256(OPK)|PPK)
        report_data = '{0}{1}'.format(originator_public_key_hash.upper(),
                                      signup_info.poet_public_key.upper())
        expected_report_body = hashlib.sha256(
            dict2json(report_data).encode()).hexdigest()

        enclave_quote_dict = \
            json2dict(base64.b64decode(enclave_quote).decode())
        report_body = enclave_quote_dict.get('report_body')
        if report_body is None:
            raise ValueError('Enclave quote does not contain a report body')

        if report_body.upper() != expected_report_body.upper():
            raise \
                ValueError(
                    'Enclave quote report body {0} does not match {1}'.format(
                        report_body,
                        expected_report_body))

        # Verify that the wait certificate ID in the verification report
        # matches the provided wait certificate ID.  The wait certificate ID
        # is stored in the nonce field.
        nonce = verification_report_dict.get('nonce')
        if nonce is None:
            raise \
                ValueError(
                    'Verification report does not have a nonce')