Skip to content

Commit

Permalink
add support for Certificate.signature to obtain certificate sig bytes
Browse files Browse the repository at this point in the history
  • Loading branch information
reaperhulk committed Oct 1, 2015
1 parent a94f97e commit 48b2836
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 1 deletion.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Changelog
.. note:: This version is not yet released and is under active development.

* Added :class:`~cryptography.hazmat.primitives.kdf.x963kdf.X963KDF`.
* The :class:`~cryptography.x509.Certificate` class now has a
:attr:`~cryptography.x509.Certificate.signature` attribute.

1.0.2 - 2015-09-27
~~~~~~~~~~~~~~~~~~
Expand Down
8 changes: 8 additions & 0 deletions docs/x509/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ X.509 Certificate Object
<Extension(oid=<ObjectIdentifier(oid=2.5.29.32, name=certificatePolicies)>, critical=False, value=<CertificatePolicies([<PolicyInformation(policy_identifier=<ObjectIdentifier(oid=2.16.840.1.101.3.2.1.48.1, name=Unknown OID)>, policy_qualifiers=None)>])>)>
<Extension(oid=<ObjectIdentifier(oid=2.5.29.19, name=basicConstraints)>, critical=True, value=<BasicConstraints(ca=True, path_length=None)>)>

.. attribute:: signature

.. versionadded:: 1.1

:type: bytes

The bytes of the certificate's signature.

.. method:: public_bytes(encoding)

.. versionadded:: 1.0
Expand Down
2 changes: 1 addition & 1 deletion src/_cffi_src/openssl/asn1.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
typedef struct asn1_string_st ASN1_OCTET_STRING;
typedef struct asn1_string_st ASN1_IA5STRING;
typedef ... ASN1_BIT_STRING;
typedef struct asn1_string_st ASN1_BIT_STRING;
typedef ... ASN1_OBJECT;
typedef struct asn1_string_st ASN1_STRING;
typedef struct asn1_string_st ASN1_UTF8STRING;
Expand Down
1 change: 1 addition & 0 deletions src/_cffi_src/openssl/x509.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
typedef struct {
X509_ALGOR *sig_alg;
X509_CINF *cert_info;
ASN1_BIT_STRING *signature;
...;
} X509;
Expand Down
4 changes: 4 additions & 0 deletions src/cryptography/hazmat/backends/openssl/x509.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,10 @@ def signature_hash_algorithm(self):
def extensions(self):
return _CERTIFICATE_EXTENSION_PARSER.parse(self._backend, self._x509)

@property
def signature(self):
return self._backend._asn1_string_to_bytes(self._x509.signature)

def public_bytes(self, encoding):
bio = self._backend._create_mem_bio()
if encoding is serialization.Encoding.PEM:
Expand Down
6 changes: 6 additions & 0 deletions src/cryptography/x509/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ def extensions(self):
Returns an Extensions object.
"""

@abc.abstractproperty
def signature(self):
"""
Returns the signature bytes.
"""

@abc.abstractmethod
def __eq__(self, other):
"""
Expand Down
60 changes: 60 additions & 0 deletions tests/test_x509.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
from cryptography.hazmat.primitives.asymmetric.utils import (
decode_dss_signature
)
from cryptography.x509.oid import (
AuthorityInformationAccessOID, ExtendedKeyUsageOID, ExtensionOID, NameOID
)
Expand Down Expand Up @@ -79,6 +82,25 @@ def test_load_der_cert(self, backend):
assert fingerprint == b"6f49779533d565e8b7c1062503eab41492c38e4d"
assert isinstance(cert.signature_hash_algorithm, hashes.SHA256)

def test_signature(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "post2000utctime.pem"),
x509.load_pem_x509_certificate,
backend
)
assert cert.signature == binascii.unhexlify(
b"8e0f72fcbebe4755abcaf76c8ce0bae17cde4db16291638e1b1ce04a93cdb4c"
b"44a3486070986c5a880c14fdf8497e7d289b2630ccb21d24a3d1aa1b2d87482"
b"07f3a1e16ccdf8daa8a7ea1a33d49774f513edf09270bd8e665b6300a10f003"
b"66a59076905eb63cf10a81a0ca78a6ef3127f6cb2f6fb7f947fce22a30d8004"
b"8c243ba2c1a54c425fe12310e8a737638f4920354d4cce25cbd9dea25e6a2fe"
b"0d8579a5c8d929b9275be221975479f3f75075bcacf09526523b5fd67f7683f"
b"3cda420fabb1e9e6fc26bc0649cf61bb051d6932fac37066bb16f55903dfe78"
b"53dc5e505e2a10fbba4f9e93a0d3b53b7fa34b05d7ba6eef869bfc34b8e514f"
b"d5419f75"
)
assert len(cert.signature) == cert.public_key().key_size // 8

def test_issuer(self, backend):
cert = _load_cert(
os.path.join(
Expand Down Expand Up @@ -2278,6 +2300,20 @@ def test_load_dsa_cert(self, backend):
"822ff5d234e073b901cf5941f58e1f538e71d40d", 16
)

def test_signature(self, backend):
cert = _load_cert(
os.path.join("x509", "custom", "dsa_selfsigned_ca.pem"),
x509.load_pem_x509_certificate,
backend
)
assert cert.signature == binascii.unhexlify(
b"302c021425c4a84a936ab311ee017d3cbd9a3c650bb3ae4a02145d30c64b4326"
b"86bdf925716b4ed059184396bcce"
)
r, s = decode_dss_signature(cert.signature)
assert r == 215618264820276283222494627481362273536404860490
assert s == 532023851299196869156027211159466197586787351758

@pytest.mark.parametrize(
("path", "loader_func"),
[
Expand Down Expand Up @@ -2331,6 +2367,30 @@ def test_load_ecdsa_cert(self, backend):
)
assert isinstance(num.curve, ec.SECP384R1)

def test_signature(self, backend):
cert = _load_cert(
os.path.join("x509", "ecdsa_root.pem"),
x509.load_pem_x509_certificate,
backend
)
assert cert.signature == binascii.unhexlify(
b"3065023100adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085"
b"a763f99e32de66930ff1ccb1098fdd6cabfa6b7fa0023039665bc2648db89e50"
b"dca8d549a2edc7dcd1497f1701b8c8868f4e8c882ba89aa98ac5d100bdf854e2"
b"9ae55b7cb32717"
)
r, s = decode_dss_signature(cert.signature)
assert r == int(
"adbcf26c3f124ad12d39c30a099773f488368c8827bbe6888d5085a763f99e32"
"de66930ff1ccb1098fdd6cabfa6b7fa0",
16
)
assert s == int(
"39665bc2648db89e50dca8d549a2edc7dcd1497f1701b8c8868f4e8c882ba89a"
"a98ac5d100bdf854e29ae55b7cb32717",
16
)

def test_load_ecdsa_no_named_curve(self, backend):
_skip_curve_unsupported(backend, ec.SECP256R1())
cert = _load_cert(
Expand Down

0 comments on commit 48b2836

Please sign in to comment.