pygost/asn1schemas/cert-selfsigned-example.py | 20 +++++++++++++++++++- pygost/asn1schemas/oids.py | 1 + pygost/asn1schemas/x509.py | 33 ++++++++++++++++++++++----------- diff --git a/pygost/asn1schemas/cert-selfsigned-example.py b/pygost/asn1schemas/cert-selfsigned-example.py index f52421bcf071aca5a1336705d2fba99c3ecd201f16f7bb155aed2528633eed9a..a08163fb7c9318bd8327ab86108dd15c8ab33b6eeec5b144c423e691014f1093 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 @@ } 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 @@ raise ValueError("PEM has no CERTIFICATE") 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 @@ exts.append(Extension(( ("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 b26a87efde08a822b897ad3249fe9520d26770e8b82e33a3f7f1589a72147dc4..ac721502249f59c4413ff2f208639df9dee3f8db8bbb6b26b300fdce8651edb0 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 e12d4b079ea8a7d0f57e166bcda2a04aa4c57e8df2fd72b8738cc17ca45221ac..05f4cc28920b1fbc44798c6b986b64d61d61ab3a1ab31fe25aa93d7ad82eb98c 100644 --- a/pygost/asn1schemas/x509.py +++ b/pygost/asn1schemas/x509.py @@ -215,23 +215,34 @@ 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), + # ), + )