def test_sign_ed25519ph_rfc8032(): # sk, pk, msg, exp_sig # taken from RFC 8032 section 7.3. Test Vectors for Ed25519ph sk = unhexlify(b"833fe62409237b9d62ec77587520911e" b"9a759cec1d19755b7da901b96dca3d42") pk = unhexlify(b"ec172b93ad5e563bf4932c70e1245034" b"c35467ef2efd4d64ebf819683467e2bf") msg = b"abc" exp_sig = unhexlify(b"98a70222f0b8121aa9d30f813d683f80" b"9e462b469c7ff87639499bb94e6dae41" b"31f85042463c2a355a2003d062adf5aa" b"a10b8c61e636062aaad11c2a26083406") c_sk = sk + pk edph = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph, msg) sig = c.crypto_sign_ed25519ph_final_create(edph, c_sk) assert sig == exp_sig edph_v = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph_v, msg) assert c.crypto_sign_ed25519ph_final_verify(edph_v, exp_sig, pk) is True c.crypto_sign_ed25519ph_update(edph_v, msg) with pytest.raises(BadSignatureError): c.crypto_sign_ed25519ph_final_verify(edph_v, exp_sig, pk)
def verify_certificate(self, cert: Certificate, usage: CertificateUsage) -> None: """Verify a certificate against a trust store.""" # Check the validity window and usage now = datetime.datetime.now().timestamp() if now < cert.valid_from or now >= cert.valid_from + cert.valid_length: raise Exception("current timestamp is outside certificate validity window") if usage not in cert.usages: raise Exception("not a server certificate") # Find the issuer cert if not cert.HasField("issuer"): raise Exception("no issuer") ca_cert = self.trusted_certs.get(cert.issuer.value) if ca_cert is None: raise Exception("unknown issuer") # Check the issuer's validity window and usage if now < ca_cert.valid_from or now >= ca_cert.valid_from + ca_cert.valid_length: raise Exception("current timestamp is outside CA certificate validity window") if CertificateUsage.CERTIFICATE_SIGNING not in ca_cert.usages: raise Exception("not a CA certificate") # Verify the issuer signature state = crypto_sign_ed25519ph_state() self._certificate_signature_state(state, cert, False) crypto_sign_ed25519ph_final_verify(state, cert.issuer_signature, ca_cert.signing_public_key)
def verify_server_certificate_status(self, cert: Certificate, status: CertificateStatusResponse, status_subject: str) -> None: """Verify a server certificate status against a trust store.""" logging.debug("verifying server certificate status") # Check that the status hash matches if status.certificate.algorithm == HashAlgorithm.SHA256: cert_hash = hash_certificate_sha256(cert) elif status.certificate.algorithm == HashAlgorithm.SHA512: cert_hash = hash_certificate_sha512(cert) else: raise Exception(f"unsupported hash algorithm {status.certificate.algorithm}") if cert_hash.value != status.certificate.value: raise Exception("certificate and status response mismatch") # Check the validity window now = datetime.datetime.now().timestamp() if now < status.valid_from or now >= status.valid_from + status.valid_length: raise Exception("current timestamp is outside status validity window") # Check the status certificate self.verify_status_certificate(status.status_certificate, status_subject) # Verify the status signature state = crypto_sign_ed25519ph_state() self._status_signature_state(state, status) crypto_sign_ed25519ph_final_verify(state, status.status_signature, status.status_certificate.signing_public_key) # Finally, check the actual status if status.status != CertificateStatus.VALID: raise Exception(f"certificate is not valid (status={status.status}")
def test_sign_ed25519ph_rfc8032(): # sk, pk, msg, exp_sig # taken from RFC 8032 section 7.3. Test Vectors for Ed25519ph sk = unhexlify(b'833fe62409237b9d62ec77587520911e' b'9a759cec1d19755b7da901b96dca3d42') pk = unhexlify(b'ec172b93ad5e563bf4932c70e1245034' b'c35467ef2efd4d64ebf819683467e2bf') msg = b'abc' exp_sig = unhexlify(b'98a70222f0b8121aa9d30f813d683f80' b'9e462b469c7ff87639499bb94e6dae41' b'31f85042463c2a355a2003d062adf5aa' b'a10b8c61e636062aaad11c2a26083406') c_sk = sk + pk edph = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph, msg) sig = c.crypto_sign_ed25519ph_final_create(edph, c_sk) assert sig == exp_sig edph_v = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph_v, msg) assert c.crypto_sign_ed25519ph_final_verify(edph_v, exp_sig, pk) is True c.crypto_sign_ed25519ph_update(edph_v, msg) with pytest.raises(BadSignatureError): c.crypto_sign_ed25519ph_final_verify(edph_v, exp_sig, pk)
def test_sign_ed25519ph_libsodium(): # _hsk, _hpk, hmsg, _hsig, _hsigmsg = ed25519_known_answers()[-1] msg = unhexlify(hmsg) seed = unhexlify(b"421151a459faeade3d247115f94aedae" b"42318124095afabe4d1451a559faedee") pk, sk = c.crypto_sign_seed_keypair(seed) exp_sig = unhexlify(b"10c5411e40bd10170fb890d4dfdb6d33" b"8c8cb11d2764a216ee54df10977dcdef" b"d8ff755b1eeb3f16fce80e40e7aafc99" b"083dbff43d5031baf04157b48423960d") edph = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph, msg) sig = c.crypto_sign_ed25519ph_final_create(edph, sk) assert sig == exp_sig edph_incr = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph_incr, b"") c.crypto_sign_ed25519ph_update(edph_incr, msg[0:len(msg) // 2]) c.crypto_sign_ed25519ph_update(edph_incr, msg[len(msg) // 2:]) assert c.crypto_sign_ed25519ph_final_verify(edph_incr, exp_sig, pk) is True with pytest.raises(BadSignatureError): wrng_sig = flip_byte(exp_sig, 0) c.crypto_sign_ed25519ph_final_verify(edph_incr, wrng_sig, pk) with pytest.raises(BadSignatureError): wrng_mesg = flip_byte(msg, 1022) edph_wrng = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph_wrng, wrng_mesg) c.crypto_sign_ed25519ph_final_verify(edph_wrng, exp_sig, pk)
def test_sign_ed25519ph_libsodium(): # _hsk, _hpk, hmsg, _hsig, _hsigmsg = ed25519_known_answers()[-1] msg = unhexlify(hmsg) seed = unhexlify(b'421151a459faeade3d247115f94aedae' b'42318124095afabe4d1451a559faedee') pk, sk = c.crypto_sign_seed_keypair(seed) exp_sig = unhexlify(b'10c5411e40bd10170fb890d4dfdb6d33' b'8c8cb11d2764a216ee54df10977dcdef' b'd8ff755b1eeb3f16fce80e40e7aafc99' b'083dbff43d5031baf04157b48423960d') edph = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph, msg) sig = c.crypto_sign_ed25519ph_final_create(edph, sk) assert sig == exp_sig edph_incr = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph_incr, b'') c.crypto_sign_ed25519ph_update(edph_incr, msg[0:len(msg) // 2]) c.crypto_sign_ed25519ph_update(edph_incr, msg[len(msg) // 2:]) assert c.crypto_sign_ed25519ph_final_verify(edph_incr, exp_sig, pk) is True with pytest.raises(BadSignatureError): wrng_sig = flip_byte(exp_sig, 0) c.crypto_sign_ed25519ph_final_verify(edph_incr, wrng_sig, pk) with pytest.raises(BadSignatureError): wrng_mesg = flip_byte(msg, 1022) edph_wrng = c.crypto_sign_ed25519ph_state() c.crypto_sign_ed25519ph_update(edph_wrng, wrng_mesg) c.crypto_sign_ed25519ph_final_verify(edph_wrng, exp_sig, pk)