Function for getting SPKI hash.

This commit is contained in:
Itamar Turner-Trauring 2022-03-02 10:35:41 -05:00
parent 8ddf21358a
commit 32cbc7b9df
2 changed files with 57 additions and 7 deletions

View File

@ -1,15 +1,12 @@
""" """
Common HTTP infrastructure for the storge server. Common HTTP infrastructure for the storge server.
""" """
from future.utils import PY2
if PY2:
# fmt: off
from future.builtins import filter, map, zip, ascii, chr, hex, input, next, oct, open, pow, round, super, bytes, dict, list, object, range, str, max, min # noqa: F401
# fmt: on
from enum import Enum from enum import Enum
from base64 import b64encode from base64 import b64encode
from hashlib import sha256
from cryptography.x509 import Certificate
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
def swissnum_auth_header(swissnum): # type: (bytes) -> bytes def swissnum_auth_header(swissnum): # type: (bytes) -> bytes
@ -23,3 +20,14 @@ class Secrets(Enum):
LEASE_RENEW = "lease-renew-secret" LEASE_RENEW = "lease-renew-secret"
LEASE_CANCEL = "lease-cancel-secret" LEASE_CANCEL = "lease-cancel-secret"
UPLOAD = "upload-secret" UPLOAD = "upload-secret"
def get_spki_hash(certificate: Certificate) -> bytes:
"""
Get the public key hash, as per RFC 7469: base64 of sha256 of the public
key encoded in DER + Subject Public Key Info format.
"""
public_key_bytes = certificate.public_key().public_bytes(
Encoding.DER, PublicFormat.SubjectPublicKeyInfo
)
return b64encode(sha256(public_key_bytes).digest()).strip()

View File

@ -24,6 +24,7 @@ from klein import Klein
from hyperlink import DecodedURL from hyperlink import DecodedURL
from collections_extended import RangeMap from collections_extended import RangeMap
from twisted.internet.task import Clock from twisted.internet.task import Clock
from cryptography.x509 import load_pem_x509_certificate
from .common import SyncTestCase from .common import SyncTestCase
from ..storage.server import StorageServer from ..storage.server import StorageServer
@ -41,6 +42,47 @@ from ..storage.http_client import (
ImmutableCreateResult, ImmutableCreateResult,
UploadProgress, UploadProgress,
) )
from ..storage.http_common import get_spki_hash
class HTTPFurlTests(SyncTestCase):
"""Tests for HTTP furls."""
def test_spki_hash(self):
"""The output of ``get_spki_hash()`` matches the semantics of RFC 7469.
The expected hash was generated using Appendix A instructions in the
RFC::
openssl x509 -noout -in certificate.pem -pubkey | \
openssl asn1parse -noout -inform pem -out public.key
openssl dgst -sha256 -binary public.key | openssl enc -base64
"""
expected_hash = b"JIj6ezHkdSBlHhrnezAgIC/mrVQHy4KAFyL+8ZNPGPM="
certificate_text = b"""\
-----BEGIN CERTIFICATE-----
MIIDWTCCAkECFCf+I+3oEhTfqt+6ruH4qQ4Wst1DMA0GCSqGSIb3DQEBCwUAMGkx
CzAJBgNVBAYTAlpaMRAwDgYDVQQIDAdOb3doZXJlMRQwEgYDVQQHDAtFeGFtcGxl
dG93bjEcMBoGA1UECgwTRGVmYXVsdCBDb21wYW55IEx0ZDEUMBIGA1UEAwwLZXhh
bXBsZS5jb20wHhcNMjIwMzAyMTUyNTQ3WhcNMjMwMzAyMTUyNTQ3WjBpMQswCQYD
VQQGEwJaWjEQMA4GA1UECAwHTm93aGVyZTEUMBIGA1UEBwwLRXhhbXBsZXRvd24x
HDAaBgNVBAoME0RlZmF1bHQgQ29tcGFueSBMdGQxFDASBgNVBAMMC2V4YW1wbGUu
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv9vqtA8Toy9D6xLG
q41iUafSiAXnuirWxML2ct/LAcGJzATg6JctmJxxZQL7vkmaFFPBF6Y39bOGbbEC
M2iQYn2Qemj5fl3IzKTnYLqzryGM0ZwwnNbPyetSe/sksAIYRLzn49d6l+AHR+Dj
GyvoLzIyGUTn41MTDafMNtPgWx1i+65lFW3GHYpEmugu4bjeUPizNja2LrqwvwFu
YXwmKxbIMdioCoRvDGX9SI3/euFstuR4rbOEUDxniYRF5g6reP8UMF30zJzF5j0k
yDg8Z5b1XpKFNZAeyRYxcs9wJCqVlP6BLPDnvNVpMXodnWLeTK+r6YWvGadGVufk
YNC1PwIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQByrhn78GSS3dJ0pJ6czmhMX5wH
+fauCtt1+Wbn+ctTodTycS+pfULO4gG7wRzhl8KNoOqLmWMjyA2A3mon8kdkD+0C
i8McpoPaGS2wQcqC28Ud6kP9YO81YFyTl4nHVKQ0nmplT+eoLDTCIWMVxHHzxIgs
2ybUluAc+THSjpGxB6kWSAJeg3N+f2OKr+07Yg9LiQ2b8y0eZarpiuuuXCzWeWrQ
PudP0aniyq/gbPhxq0tYF628IBvhDAnr/2kqEmVF2TDr2Sm/Y3PDBuPY6MeIxjnr
ox5zO3LrQmQw11OaIAs2/kviKAoKTFFxeyYcpS5RuKNDZfHQCXlLwt9bySxG
-----END CERTIFICATE-----
"""
certificate = load_pem_x509_certificate(certificate_text)
self.assertEqual(get_spki_hash(certificate), expected_hash)
def _post_process(params): def _post_process(params):