]> Cypherpunks.ru repositories - pygost.git/blob - pygost/asn1schemas/cert-selfsigned-example.py
Ability to create certificate examples with various curves
[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_256
23 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetA
24 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetB
25 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetC
26 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_256_paramSetD
27 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512
28 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetA
29 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetB
30 from pygost.asn1schemas.oids import id_tc26_gost3410_2012_512_paramSetC
31 from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_256
32 from pygost.asn1schemas.oids import id_tc26_signwithdigest_gost3410_2012_512
33 from pygost.asn1schemas.prvkey import PrivateKey
34 from pygost.asn1schemas.prvkey import PrivateKeyAlgorithmIdentifier
35 from pygost.asn1schemas.prvkey import PrivateKeyInfo
36 from pygost.asn1schemas.x509 import AlgorithmIdentifier
37 from pygost.asn1schemas.x509 import AttributeType
38 from pygost.asn1schemas.x509 import AttributeTypeAndValue
39 from pygost.asn1schemas.x509 import AttributeValue
40 from pygost.asn1schemas.x509 import BasicConstraints
41 from pygost.asn1schemas.x509 import Certificate
42 from pygost.asn1schemas.x509 import CertificateSerialNumber
43 from pygost.asn1schemas.x509 import Extension
44 from pygost.asn1schemas.x509 import Extensions
45 from pygost.asn1schemas.x509 import GostR34102012PublicKeyParameters
46 from pygost.asn1schemas.x509 import Name
47 from pygost.asn1schemas.x509 import RDNSequence
48 from pygost.asn1schemas.x509 import RelativeDistinguishedName
49 from pygost.asn1schemas.x509 import SubjectKeyIdentifier
50 from pygost.asn1schemas.x509 import SubjectPublicKeyInfo
51 from pygost.asn1schemas.x509 import TBSCertificate
52 from pygost.asn1schemas.x509 import Time
53 from pygost.asn1schemas.x509 import Validity
54 from pygost.asn1schemas.x509 import Version
55 from pygost.gost3410 import CURVES
56 from pygost.gost3410 import prv_unmarshal
57 from pygost.gost3410 import pub_marshal
58 from pygost.gost3410 import public_key
59 from pygost.gost3410 import sign
60 from pygost.gost34112012256 import GOST34112012256
61 from pygost.gost34112012512 import GOST34112012512
62
63 parser = ArgumentParser(description="Self-signed X.509 certificate creator")
64 parser.add_argument(
65     "--ca",
66     action="store_true",
67     help="Enable BasicConstraints.cA",
68 )
69 parser.add_argument(
70     "--cn",
71     required=True,
72     help="Subject's CommonName",
73 )
74 parser.add_argument(
75     "--ai",
76     required=True,
77     help="Signing algorithm: {256[ABCD],512[ABC]}",
78 )
79 args = parser.parse_args()
80 ai = {
81     "256A": {
82         "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetA,
83         "key_algorithm": id_tc26_gost3410_2012_256,
84         "prv_len": 32,
85         "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetA"],
86         "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256,
87         "hasher": GOST34112012256,
88     },
89     "256B": {
90         "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetB,
91         "key_algorithm": id_tc26_gost3410_2012_256,
92         "prv_len": 32,
93         "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetB"],
94         "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256,
95         "hasher": GOST34112012256,
96     },
97     "256C": {
98         "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetC,
99         "key_algorithm": id_tc26_gost3410_2012_256,
100         "prv_len": 32,
101         "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetC"],
102         "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256,
103         "hasher": GOST34112012256,
104     },
105     "256D": {
106         "publicKeyParamSet": id_tc26_gost3410_2012_256_paramSetD,
107         "key_algorithm": id_tc26_gost3410_2012_256,
108         "prv_len": 32,
109         "curve": CURVES["id-tc26-gost-3410-2012-256-paramSetD"],
110         "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_256,
111         "hasher": GOST34112012256,
112     },
113     "512A": {
114         "publicKeyParamSet": id_tc26_gost3410_2012_512_paramSetA,
115         "key_algorithm": id_tc26_gost3410_2012_512,
116         "prv_len": 64,
117         "curve": CURVES["id-tc26-gost-3410-12-512-paramSetA"],
118         "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_512,
119         "hasher": GOST34112012512,
120     },
121     "512B": {
122         "publicKeyParamSet": id_tc26_gost3410_2012_512_paramSetB,
123         "key_algorithm": id_tc26_gost3410_2012_512,
124         "prv_len": 64,
125         "curve": CURVES["id-tc26-gost-3410-12-512-paramSetB"],
126         "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_512,
127         "hasher": GOST34112012512,
128     },
129     "512C": {
130         "publicKeyParamSet": id_tc26_gost3410_2012_512_paramSetC,
131         "key_algorithm": id_tc26_gost3410_2012_512,
132         "prv_len": 64,
133         "curve": CURVES["id-tc26-gost-3410-2012-512-paramSetC"],
134         "sign_algorithm": id_tc26_signwithdigest_gost3410_2012_512,
135         "hasher": GOST34112012512,
136     },
137 }[args.ai]
138
139
140 def pem(obj):
141     return fill(standard_b64encode(obj.encode()).decode("ascii"), 64)
142
143
144 key_params = GostR34102012PublicKeyParameters((
145     ("publicKeyParamSet", ai["publicKeyParamSet"]),
146 ))
147
148 prv_raw = urandom(ai["prv_len"])
149 print("-----BEGIN PRIVATE KEY-----")
150 print(pem(PrivateKeyInfo((
151     ("version", Integer(0)),
152     ("privateKeyAlgorithm", PrivateKeyAlgorithmIdentifier((
153         ("algorithm", ai["key_algorithm"]),
154         ("parameters", Any(key_params)),
155     ))),
156     ("privateKey", PrivateKey(prv_raw)),
157 ))))
158 print("-----END PRIVATE KEY-----")
159
160 prv = prv_unmarshal(prv_raw)
161 curve = ai["curve"]
162 pub_raw = pub_marshal(public_key(curve, prv))
163 subj = Name(("rdnSequence", RDNSequence([
164     RelativeDistinguishedName((
165         AttributeTypeAndValue((
166             ("type", AttributeType(id_at_commonName)),
167             ("value", AttributeValue(PrintableString(args.cn))),
168         )),
169     ))
170 ])))
171 not_before = datetime.utcnow()
172 not_after = not_before + timedelta(days=365)
173 ai_sign = AlgorithmIdentifier((
174     ("algorithm", ai["sign_algorithm"],),
175 ))
176 exts = [
177     Extension((
178         ("extnID", id_ce_subjectKeyIdentifier),
179         ("extnValue", OctetString(
180             SubjectKeyIdentifier(GOST34112012256(pub_raw).digest()[:20]).encode()
181         )),
182     )),
183 ]
184 if args.ca:
185     exts.append(Extension((
186         ("extnID", id_ce_basicConstraints),
187         ("extnValue", OctetString(BasicConstraints((("cA", Boolean(True)),)).encode())),
188     )))
189 tbs = TBSCertificate((
190     ("version", Version("v3")),
191     ("serialNumber", CertificateSerialNumber(12345)),
192     ("signature", ai_sign),
193     ("issuer", subj),
194     ("validity", Validity((
195         ("notBefore", Time(("utcTime", UTCTime(not_before)))),
196         ("notAfter", Time(("utcTime", UTCTime(not_after)))),
197     ))),
198     ("subject", subj),
199     ("subjectPublicKeyInfo", SubjectPublicKeyInfo((
200         ("algorithm", AlgorithmIdentifier((
201             ("algorithm", ai["key_algorithm"]),
202             ("parameters", Any(key_params)),
203         ))),
204         ("subjectPublicKey", BitString(OctetString(pub_raw).encode())),
205     ))),
206     ("extensions", Extensions(exts)),
207 ))
208 cert = Certificate((
209     ("tbsCertificate", tbs),
210     ("signatureAlgorithm", ai_sign),
211     ("signatureValue", BitString(sign(
212         curve,
213         prv,
214         ai["hasher"](tbs.encode()).digest()[::-1],
215     ))),
216 ))
217 print("-----BEGIN CERTIFICATE-----")
218 print(pem(cert))
219 print("-----END CERTIFICATE-----")