From 08cedcc91f44b8ffd2d8f3a3fbbb15263ccff440 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Tue, 26 Jan 2021 15:05:14 +0300 Subject: [PATCH] Properly add AKID to issued child certificates --- pygost/asn1schemas/cert-selfsigned-example.py | 20 ++++++++++- pygost/asn1schemas/oids.py | 1 + pygost/asn1schemas/x509.py | 33 ++++++++++++------- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/pygost/asn1schemas/cert-selfsigned-example.py b/pygost/asn1schemas/cert-selfsigned-example.py index 94b4b34..1f505aa 100755 --- a/pygost/asn1schemas/cert-selfsigned-example.py +++ b/pygost/asn1schemas/cert-selfsigned-example.py @@ -20,6 +20,7 @@ from pyderasn import PrintableString from pyderasn import UTCTime from pygost.asn1schemas.oids import id_at_commonName +from pygost.asn1schemas.oids import id_ce_authorityKeyIdentifier from pygost.asn1schemas.oids import id_ce_basicConstraints from pygost.asn1schemas.oids import id_ce_subjectAltName from pygost.asn1schemas.oids import id_ce_subjectKeyIdentifier @@ -41,6 +42,7 @@ from pygost.asn1schemas.x509 import AlgorithmIdentifier from pygost.asn1schemas.x509 import AttributeType from pygost.asn1schemas.x509 import AttributeTypeAndValue from pygost.asn1schemas.x509 import AttributeValue +from pygost.asn1schemas.x509 import AuthorityKeyIdentifier from pygost.asn1schemas.x509 import BasicConstraints from pygost.asn1schemas.x509 import Certificate from pygost.asn1schemas.x509 import CertificateSerialNumber @@ -48,6 +50,7 @@ from pygost.asn1schemas.x509 import Extension from pygost.asn1schemas.x509 import Extensions from pygost.asn1schemas.x509 import GeneralName from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters +from pygost.asn1schemas.x509 import KeyIdentifier from pygost.asn1schemas.x509 import Name from pygost.asn1schemas.x509 import RDNSequence from pygost.asn1schemas.x509 import RelativeDistinguishedName @@ -148,6 +151,7 @@ AIs = { ai = AIs[args.ai] ca_prv = None +ca_cert = None ca_subj = None ca_ai = None if args.issue_with is not None: @@ -163,7 +167,8 @@ if args.issue_with is not None: cert_raw = standard_b64decode(lines[idx + 1]) pki = PrivateKeyInfo().decod(prv_raw) ca_prv = prv_unmarshal(bytes(OctetString().decod(bytes(pki["privateKey"])))) - tbs = Certificate().decod(cert_raw)["tbsCertificate"] + ca_cert = Certificate().decod(cert_raw) + tbs = ca_cert["tbsCertificate"] ca_subj = tbs["subject"] curve_oid = GostR34102012PublicKeyParameters().decod(bytes( tbs["subjectPublicKeyInfo"]["algorithm"]["parameters"] @@ -232,6 +237,19 @@ if args.ca: ("extnID", id_ce_basicConstraints), ("extnValue", OctetString(BasicConstraints((("cA", Boolean(True)),)).encode())), ))) +if ca_ai is not None: + caKeyId = [ + bytes(SubjectKeyIdentifier().decod(bytes(ext["extnValue"]))) + for ext in ca_cert["tbsCertificate"]["extensions"] + if ext["extnID"] == id_ce_subjectKeyIdentifier + ][0] + exts.append(Extension(( + ("extnID", id_ce_authorityKeyIdentifier), + ("extnValue", OctetString(AuthorityKeyIdentifier(( + ("keyIdentifier", KeyIdentifier(caKeyId)), + )).encode())), + ))) + tbs = TBSCertificate(( ("version", Version("v3")), ("serialNumber", CertificateSerialNumber(12345)), diff --git a/pygost/asn1schemas/oids.py b/pygost/asn1schemas/oids.py index 54d2b0d..d5b9031 100644 --- a/pygost/asn1schemas/oids.py +++ b/pygost/asn1schemas/oids.py @@ -52,3 +52,4 @@ id_at_commonName = ObjectIdentifier("2.5.4.3") id_ce_basicConstraints = ObjectIdentifier("2.5.29.19") id_ce_subjectKeyIdentifier = ObjectIdentifier("2.5.29.14") id_ce_subjectAltName = ObjectIdentifier("2.5.29.17") +id_ce_authorityKeyIdentifier = ObjectIdentifier("2.5.29.35") diff --git a/pygost/asn1schemas/x509.py b/pygost/asn1schemas/x509.py index 29a0a60..cda11da 100644 --- a/pygost/asn1schemas/x509.py +++ b/pygost/asn1schemas/x509.py @@ -215,23 +215,34 @@ class CertificateList(Sequence): class GeneralName(Choice): schema = ( - # ('otherName', AnotherName(impl=tag_ctxc(0))), - # ('rfc822Name', IA5String(impl=tag_ctxp(1))), - ('dNSName', IA5String(impl=tag_ctxp(2))), - # ('x400Address', ORAddress(impl=tag_ctxp(3))), - # ('x400Address', OctetString(impl=tag_ctxp(3))), - # ('directoryName', Name(expl=tag_ctxc(4))), - # ('ediPartyName', EDIPartyName(impl=tag_ctxc(5))), - # ('uniformResourceIdentifier', IA5String(impl=tag_ctxp(6))), - # ('iPAddress', OctetString(impl=tag_ctxp(7))), - # ('registeredID', ObjectIdentifier(impl=tag_ctxp(8))), + # ("otherName", AnotherName(impl=tag_ctxc(0))), + # ("rfc822Name", IA5String(impl=tag_ctxp(1))), + ("dNSName", IA5String(impl=tag_ctxp(2))), + # ("x400Address", ORAddress(impl=tag_ctxp(3))), + # ("x400Address", OctetString(impl=tag_ctxp(3))), + # ("directoryName", Name(expl=tag_ctxc(4))), + # ("ediPartyName", EDIPartyName(impl=tag_ctxc(5))), + # ("uniformResourceIdentifier", IA5String(impl=tag_ctxp(6))), + # ("iPAddress", OctetString(impl=tag_ctxp(7))), + # ("registeredID", ObjectIdentifier(impl=tag_ctxp(8))), ) class GeneralNames(SequenceOf): schema = GeneralName() - bounds = (1, float('+inf')) + bounds = (1, float("+inf")) class SubjectAltName(GeneralNames): pass + + +class AuthorityKeyIdentifier(Sequence): + schema = ( + ("keyIdentifier", KeyIdentifier(impl=tag_ctxp(0), optional=True)), + # ("authorityCertIssuer", GeneralNames(impl=tag_ctxc(1), optional=True)), + # ( + # "authorityCertSerialNumber", + # CertificateSerialNumber(impl=tag_ctxp(2), optional=True), + # ), + ) -- 2.44.0