]> Cypherpunks.ru repositories - pygost.git/blob - pygost/asn1schemas/cert-selfsigned-example.py
cert-selfsigned-example optionally can create create CA certificate
[pygost.git] / pygost / asn1schemas / cert-selfsigned-example.py
1 """Create example self-signed X.509 certificate
2 """
3
4 from argparse import ArgumentParser
5 from base64 import standard_b64encode
6 from datetime import datetime
7 from datetime import timedelta
8 from os import urandom
9 from textwrap import fill
10
11 from pyderasn import Any
12 from pyderasn import BitString
13 from pyderasn import Boolean
14 from pyderasn import Integer
15 from pyderasn import OctetString
16 from pyderasn import PrintableString
17 from pyderasn import UTCTime
18
19 from pygost.asn1schemas.oids import id_at_commonName
20 from pygost.asn1schemas.oids import id_ce_basicConstraints
21 from pygost.asn1schemas.oids import id_ce_subjectKeyIdentifier
22 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512
23 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetA
24 from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_512
25 from pygost.asn1schemas.prvkey import PrivateKey
26 from pygost.asn1schemas.prvkey import PrivateKeyAlgorithmIdentifier
27 from pygost.asn1schemas.prvkey import PrivateKeyInfo
28 from pygost.asn1schemas.x509 import AlgorithmIdentifier
29 from pygost.asn1schemas.x509 import AttributeType
30 from pygost.asn1schemas.x509 import AttributeTypeAndValue
31 from pygost.asn1schemas.x509 import AttributeValue
32 from pygost.asn1schemas.x509 import BasicConstraints
33 from pygost.asn1schemas.x509 import Certificate
34 from pygost.asn1schemas.x509 import CertificateSerialNumber
35 from pygost.asn1schemas.x509 import Extension
36 from pygost.asn1schemas.x509 import Extensions
37 from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters
38 from pygost.asn1schemas.x509 import Name
39 from pygost.asn1schemas.x509 import RDNSequence
40 from pygost.asn1schemas.x509 import RelativeDistinguishedName
41 from pygost.asn1schemas.x509 import SubjectKeyIdentifier
42 from pygost.asn1schemas.x509 import SubjectPublicKeyInfo
43 from pygost.asn1schemas.x509 import TBSCertificate
44 from pygost.asn1schemas.x509 import Time
45 from pygost.asn1schemas.x509 import Validity
46 from pygost.asn1schemas.x509 import Version
47 from pygost.gost3410 import CURVES
48 from pygost.gost3410 import prv_unmarshal
49 from pygost.gost3410 import pub_marshal
50 from pygost.gost3410 import public_key
51 from pygost.gost3410 import sign
52 from pygost.gost34112012512 import GOST34112012512
53
54 parser = ArgumentParser(description="Self-signed X.509 certificate creator")
55 parser.add_argument(
56     "--ca",
57     action="store_true",
58     help="Enable BasicConstraints.cA",
59 )
60 parser.add_argument(
61     "--cn",
62     required=True,
63     help="Subject's CommonName",
64 )
65 args = parser.parse_args()
66
67
68 def pem(obj):
69     return fill(standard_b64encode(obj.encode()).decode("ascii"), 64)
70
71
72 key_params = GostR34102012PublicKeyParameters((
73     ("publicKeyParamSet", id_tc26_gost3410_2012_512_paramSetA),
74 ))
75
76 prv_raw = urandom(64)
77 print("-----BEGIN PRIVATE KEY-----")
78 print(pem(PrivateKeyInfo((
79     ("version", Integer(0)),
80     ("privateKeyAlgorithm", PrivateKeyAlgorithmIdentifier((
81         ("algorithm", id_tc26_gost3410_2012_512),
82         ("parameters", Any(key_params)),
83     ))),
84     ("privateKey", PrivateKey(prv_raw)),
85 ))))
86 print("-----END PRIVATE KEY-----")
87
88 prv = prv_unmarshal(prv_raw)
89 curve = CURVES["id-tc26-gost-3410-12-512-paramSetA"]
90 pub_raw = pub_marshal(public_key(curve, prv))
91 subj = Name(("rdnSequence", RDNSequence([
92     RelativeDistinguishedName((
93         AttributeTypeAndValue((
94             ("type", AttributeType(id_at_commonName)),
95             ("value", AttributeValue(PrintableString(args.cn))),
96         )),
97     ))
98 ])))
99 not_before = datetime.utcnow()
100 not_after = not_before + timedelta(days=365)
101 ai_sign = AlgorithmIdentifier((
102     ("algorithm", id_tc26_signwithdigest_gost3410_2012_512),
103 ))
104 exts = [
105     Extension((
106         ("extnID", id_ce_subjectKeyIdentifier),
107         ("extnValue", OctetString(
108             SubjectKeyIdentifier(GOST34112012512(pub_raw).digest()[:20]).encode()
109         )),
110     )),
111 ]
112 if args.ca:
113     exts.append(Extension((
114         ("extnID", id_ce_basicConstraints),
115         ("extnValue", OctetString(BasicConstraints((("cA", Boolean(True)),)).encode())),
116     )))
117 tbs = TBSCertificate((
118     ("version", Version("v3")),
119     ("serialNumber", CertificateSerialNumber(12345)),
120     ("signature", ai_sign),
121     ("issuer", subj),
122     ("validity", Validity((
123         ("notBefore", Time(("utcTime", UTCTime(not_before)))),
124         ("notAfter", Time(("utcTime", UTCTime(not_after)))),
125     ))),
126     ("subject", subj),
127     ("subjectPublicKeyInfo", SubjectPublicKeyInfo((
128         ("algorithm", AlgorithmIdentifier((
129             ("algorithm", id_tc26_gost3410_2012_512),
130             ("parameters", Any(key_params)),
131         ))),
132         ("subjectPublicKey", BitString(OctetString(pub_raw).encode())),
133     ))),
134     ("extensions", Extensions(exts)),
135 ))
136 cert = Certificate((
137     ("tbsCertificate", tbs),
138     ("signatureAlgorithm", ai_sign),
139     ("signatureValue", BitString(sign(
140         curve,
141         prv,
142         GOST34112012512(tbs.encode()).digest()[::-1],
143     ))),
144 ))
145 print("-----BEGIN CERTIFICATE-----")
146 print(pem(cert))
147 print("-----END CERTIFICATE-----")