1+ #include " cert.h"
2+
3+ #include < cstring>
4+
5+ // X509_new
6+ namespace hcpp
7+ {
8+
9+ // 创建pkey
10+ EVP_PKEY *generate_pkey ()
11+ {
12+ // 创建key
13+ EVP_PKEY_CTX *ctx;
14+ EVP_PKEY *pkey = NULL ;
15+
16+ ctx = EVP_PKEY_CTX_new_id (EVP_PKEY_RSA , NULL );
17+ if (!ctx)
18+ /* Error occurred */
19+ return nullptr ;
20+ if (EVP_PKEY_keygen_init (ctx) <= 0 )
21+ /* Error */
22+ return nullptr ;
23+ if (EVP_PKEY_CTX_set_rsa_keygen_bits (ctx, 2048 ) <= 0 )
24+ /* Error */
25+ return nullptr ;
26+ /* Generate key */
27+ if (EVP_PKEY_keygen (ctx, &pkey) <= 0 )
28+ /* Error */
29+ return nullptr ;
30+
31+ return pkey;
32+ }
33+
34+ X509 *make_x509 ()
35+ {
36+ return X509_new ();
37+ }
38+
39+ EVP_PKEY *make_pkey ()
40+ {
41+ return generate_pkey ();
42+ }
43+
44+ // Version
45+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.1
46+ void set_version (X509 *cert)
47+ {
48+ // X509_set_version
49+ X509_set_version (cert, X509_VERSION_3 );
50+ }
51+
52+ // Serial Number
53+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.2
54+ void set_serialNumber (X509 *cert)
55+ {
56+ unsigned char buff[20 ];
57+ if (RAND_bytes (buff, sizeof (buff)) != 1 )
58+ {
59+ // 随机数生成失败,处理错误
60+ }
61+ buff[0 ] &= 0x7f ; /* Ensure positive serial! */
62+
63+ BIGNUM *serial_bn = BN_bin2bn (buff, sizeof (buff), NULL );
64+ if (serial_bn == NULL )
65+ {
66+ // 转换失败,处理错误
67+ }
68+ auto *serial = ASN1_INTEGER_new ();
69+ BN_to_ASN1_INTEGER (serial_bn, serial);
70+
71+ // X509_set_serialNumber >=3.2.0
72+ X509_set_serialNumber (cert, serial);
73+
74+ ASN1_INTEGER_free (serial);
75+ BN_free (serial_bn);
76+ }
77+
78+ // Issuer
79+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.4
80+ void add_issuer (X509 *cert, std::string_view name2)
81+ {
82+ // auto issuer = X509_NAME_new();
83+ // * country,
84+ // * organization,
85+ // * organizational unit,
86+ // x distinguished name qualifier,
87+ // * state or province name,
88+ // * common name (e.g., "Susan Housley"), and
89+ // x serial number.
90+
91+ // * locality
92+ struct name_entry
93+ {
94+ int nid_;
95+ const char *nid_val_;
96+ int nid_val_len_;
97+ };
98+ name_entry issuer[] = {
99+ {NID_countryName, " CN" , sizeof (" CN" ) - 1 },
100+ {NID_organizationName, " NoBody" , sizeof (" NoBody" ) - 1 },
101+ {NID_organizationalUnitName, " XX" , sizeof (" XX" ) - 1 },
102+ {NID_stateOrProvinceName, " JS" , sizeof (" JS" ) - 1 },
103+ {NID_commonName, " SelfCA" , sizeof (" SelfCA" ) - 1 },
104+ {NID_localityName, " SQ" , sizeof (" SQ" ) - 1 },
105+ };
106+
107+ auto name = X509_NAME_new ();
108+
109+ for (auto &&i : issuer)
110+ {
111+ X509_NAME_add_entry_by_NID (name, i.nid_ , MBSTRING_ASC , (const unsigned char *)i.nid_val_ , i.nid_val_len_ , -1 , 0 );
112+ }
113+ // X509_set_issuer_name
114+ X509_set_issuer_name (cert, name);
115+ X509_NAME_free (name);
116+ }
117+
118+ // Validity
119+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.5
120+ void set_validity (X509 *cert, std::size_t days)
121+ {
122+ // 这两个时间点都是包含的
123+ auto begin_time = ASN1_TIME_new ();
124+ auto end_time = ASN1_TIME_new ();
125+ // now
126+ X509_time_adj_ex (begin_time, 0 , 0 , nullptr );
127+ X509_time_adj_ex (end_time, days, 0 , nullptr );
128+
129+ X509_set1_notBefore (cert, begin_time);
130+ X509_set1_notAfter (cert, end_time);
131+ }
132+
133+ // Subject
134+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.6
135+ void set_subject (X509 *cert)
136+ {
137+ // X509_set_subject_name get X509_NAME hashes or get and set issuer or subject names
138+ X509_set_subject_name (cert, X509_get_issuer_name (cert));
139+ }
140+
141+ // Subject Public Key Info
142+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.7
143+ void set_pubkey (X509 *cert, EVP_PKEY *pkey)
144+ {
145+ X509_set_pubkey (cert, pkey);
146+ }
147+
148+ /* ********扩展**********/
149+ // key usage
150+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.3
151+ void add_ca_key_usage (X509 *cert)
152+ {
153+ auto bb = ASN1_BIT_STRING_new ();
154+ // ASN1_BIT_STRING_set_bit(bb, 6, 1);
155+ // ASN1_BIT_STRING_set_bit(bb, 5, 1);
156+ char8_t bv = KU_KEY_CERT_SIGN | KU_CRL_SIGN ;
157+ ASN1_BIT_STRING_set (bb, (unsigned char *)&bv, sizeof (bv));
158+ X509_add1_ext_i2d (cert, NID_key_usage, bb, 1 , X509_ADD_FLAG_DEFAULT );
159+ ASN1_BIT_STRING_free (bb);
160+ }
161+
162+ void generate_key_id (X509 *cert, unsigned char *md, std::size_t *md_len)
163+ {
164+ // 不要释放
165+ // auto pubkey2 = X509_get0_pubkey(pkey);
166+ // EVP_sha
167+ // https://www.openssl.org/docs/manmaster/man3/X509_pubkey_digest.html
168+ X509_pubkey_digest (cert, EVP_sha1 (), md, (unsigned int *)md_len);
169+
170+ // EVP_PKEY_get_raw_public_key(pkey)
171+ // EVP_PKEY
172+ // or be replaced by (EVP_Q_digest(d, n, md, NULL, NULL, "SHA1", NULL) ? md : NULL)
173+ // SHA1();
174+ }
175+ // Subject Key Identifier
176+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.2
177+ void add_SKI (X509 *cert)
178+ {
179+ unsigned char md[EVP_MAX_MD_SIZE ];
180+ std::size_t md_len = 0 ;
181+ generate_key_id (cert, md, &md_len);
182+
183+ auto oct = ASN1_OCTET_STRING_new ();
184+ ASN1_OCTET_STRING_set (oct, md, md_len);
185+ X509_add1_ext_i2d (cert, NID_subject_key_identifier, oct, 0 , X509V3_ADD_DEFAULT );
186+ ASN1_OCTET_STRING_free (oct);
187+ }
188+
189+ // Authority Key Identifier
190+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.1
191+ void add_AKI (X509 *cert)
192+ {
193+ unsigned char md[EVP_MAX_MD_SIZE ];
194+ std::size_t md_len = 0 ;
195+ generate_key_id (cert, md, &md_len);
196+
197+ auto oct = ASN1_OCTET_STRING_new ();
198+ ASN1_OCTET_STRING_set (oct, md, md_len);
199+
200+ auto akid = AUTHORITY_KEYID_new ();
201+ akid->keyid = oct;
202+ akid->issuer = nullptr ;
203+ akid->serial = nullptr ;
204+ X509_add1_ext_i2d (cert, NID_authority_key_identifier, akid, 0 , X509V3_ADD_DEFAULT );
205+ ASN1_OCTET_STRING_free (oct);
206+ }
207+
208+ // Subject Alternative Name
209+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.6
210+ void add_DNS_SAN (X509 *caCert, std::string_view dns_name)
211+ {
212+ GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null ();
213+
214+ GENERAL_NAME *gen_dns = GENERAL_NAME_new ();
215+ ASN1_IA5STRING *ia5 = ASN1_IA5STRING_new ();
216+ ASN1_STRING_set (ia5, dns_name.data (), dns_name.length ());
217+ GENERAL_NAME_set0_value (gen_dns, GEN_DNS , ia5);
218+ sk_GENERAL_NAME_push (gens, gen_dns);
219+
220+ // in_addr_t ipv4 = inet_addr("10.0.0.1");
221+ // GENERAL_NAME *gen_ip = GENERAL_NAME_new();
222+ // ASN1_OCTET_STRING *octet = ASN1_OCTET_STRING_new();
223+ // ASN1_STRING_set(octet, &ipv4, sizeof(ipv4));
224+ // GENERAL_NAME_set0_value(gen_ip, GEN_IPADD, octet);
225+ // sk_GENERAL_NAME_push(gens, gen_ip);
226+
227+ X509_add1_ext_i2d (caCert, NID_subject_alt_name, gens, 0 , X509V3_ADD_DEFAULT );
228+
229+ sk_GENERAL_NAME_pop_free (gens, GENERAL_NAME_free);
230+ }
231+
232+ // Basic Constraints
233+ // https://www.rfc-editor.org/rfc/rfc5280#section-4.2.1.9
234+ void add_ca_BS (X509 *cert)
235+ {
236+ auto e1 = X509V3_EXT_conf_nid (nullptr , nullptr , NID_basic_constraints, " CA:true" );
237+ X509_EXTENSION_set_critical (e1 , 1 );
238+ X509_add_ext (cert, e1 , -1 );
239+ // XXX为啥不正确
240+ // auto bs = BASIC_CONSTRAINTS_new();
241+ // bs->ca = 1;
242+ // bs->pathlen = nullptr;
243+ // X509_add1_ext_i2d(cert, NID_basic_constraints, bs, 1, X509V3_ADD_DEFAULT);
244+ }
245+
246+ // 签名
247+ void sign (X509 *cert, EVP_PKEY *pkey)
248+ {
249+ X509_sign (cert, pkey, EVP_sha256 ());
250+ }
251+
252+ std::string make_pem_str (X509 *cert)
253+ {
254+ BIO *bio = BIO_new (BIO_s_mem ());
255+ PEM_write_bio_X509 (bio, cert);
256+ auto cert_size = BIO_pending (bio);
257+
258+ auto cert_array = new char [cert_size + 1 ];
259+ BIO_read (bio, cert_array, cert_size);
260+ BIO_free_all (bio);
261+ return cert_array;
262+ }
263+
264+ std::string make_pem_str (EVP_PKEY *pkey)
265+ {
266+ BIO *bio = BIO_new (BIO_s_mem ());
267+ PEM_write_bio_PrivateKey (bio, pkey, NULL , NULL , 0 , NULL , NULL );
268+ auto pkey_size = BIO_pending (bio);
269+ auto pkey_array = new char [pkey_size + 1 ];
270+ BIO_read (bio, pkey_array, pkey_size);
271+ BIO_free_all (bio);
272+ return pkey_array;
273+ }
274+
275+ void test ()
276+ {
277+
278+ auto cert = X509_new ();
279+
280+ auto pkey = generate_pkey ();
281+ // if (pkey == NULL)
282+ // CHECK(false);
283+ // print_key(pkey);
284+
285+ // set_version(cert);
286+ // set_validity(cert);
287+ // set_serialNumber(cert);
288+ // add_issuer(cert);
289+ // set_subject(cert);
290+ // // add_SAN(cert);
291+ // add_ca_BS(cert);
292+ // add_AKI(cert);
293+ // add_SKI(cert);
294+ // add_ca_key_usage(cert);
295+ // set_pubkey(cert, pkey);
296+ // sign(cert, pkey);
297+
298+ // print_cert(cert);
299+
300+ // Save the private key to a file.
301+ // FILE *privateKeyFile = fopen("hcpp.key.pem", "w");
302+ // if (!privateKeyFile)
303+ // {
304+ // // CHECK(false);
305+ // }
306+ // if (!PEM_write_PrivateKey(privateKeyFile, pkey, nullptr, nullptr, 0, nullptr, nullptr))
307+ // {
308+ // fclose(privateKeyFile);
309+ // // CHECK(false);
310+ // }
311+ // fclose(privateKeyFile);
312+
313+ // // Save the CA certificate to a file.
314+ // // auto certfile="cert";
315+
316+ // FILE *caCertFile = fopen("hcpp.crt.pem", "wb");
317+ // if (!caCertFile)
318+ // {
319+ // X509_free(cert);
320+ // // CHECK(false);
321+ // }
322+ // PEM_write_X509(caCertFile, cert);
323+
324+ // fclose(caCertFile);
325+ // X509_free(cert);
326+ }
327+ } // namespace hcpp
0 commit comments