Skip to content

Commit fc51f51

Browse files
committed
ca
1 parent 8b13a54 commit fc51f51

13 files changed

Lines changed: 550 additions & 66 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ linux下使用clang>16,在debug下编译
2020

2121
windows使用最新编译器
2222

23-
打开终端或`wt`
23+
打开终端或`windows terminal`
2424

2525
```shell
2626
xmake g --proxy_pac=github_mirror.lua

src/certificate/cert.cpp

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
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

src/certificate/cert.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#ifndef SRC_CERTIFICATE_CERT
2+
#define SRC_CERTIFICATE_CERT
3+
4+
#include <openssl/x509.h>
5+
#include <openssl/x509v3.h>
6+
#include <openssl/pem.h>
7+
#include <openssl/rand.h>
8+
9+
#include <string>
10+
11+
namespace hcpp
12+
{
13+
X509 * make_x509();
14+
EVP_PKEY * make_pkey();
15+
void set_version(X509 *cert);
16+
void set_serialNumber(X509 *cert);
17+
void add_issuer(X509 *cert,std::string_view name);
18+
void set_validity(X509 *cert,std::size_t days=365*10);
19+
void set_subject(X509 *cert);
20+
void set_pubkey(X509 *cert, EVP_PKEY *pkey);
21+
void add_ca_key_usage(X509 *cert);
22+
void add_SKI(X509 *cert);
23+
void add_AKI(X509 *cert);
24+
void add_DNS_SAN(X509 *cert, std::string_view dns_name);
25+
void add_ca_BS(X509 *cert);
26+
void sign(X509 *cert, EVP_PKEY *pkey);
27+
28+
std::string make_pem_str(X509 *cert);
29+
std::string make_pem_str(EVP_PKEY *pkey);
30+
} // namespace hcpp
31+
32+
#endif /* SRC_CERTIFICATE_CERT */

src/dns.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,8 @@ namespace hcpp
8787
tcp_socket s(c);
8888
co_await asio::async_connect(s, endpoints);
8989

90-
auto ssl_m = std::make_shared<ssl_sock_mem>(asio::ssl::stream_base::client);
91-
ssl_m->init(std::move(s));
90+
auto ssl_m = std::make_shared<ssl_sock_mem>(provider.host_,"https");
91+
ssl_m->init_client(std::move(s));
9292
co_await ssl_m->async_handshake();
9393
co_await ssl_m->wait();
9494

src/hcpp-cfg.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,16 @@
5555
"sni_host_":"", //假的主机名
5656
"close_sni_":false //默认就是false.优先级高于sni_host_
5757
}
58+
,
59+
{
60+
61+
"host_":"www.baidu.com",
62+
"svc_":"443", //端口或服务名.例如 http https
63+
"url_":"", //暂未使用
64+
"mitm_":true,
65+
"doh_":false,
66+
"sni_host_":"", //假的主机名
67+
"close_sni_":false //默认就是false.优先级高于sni_host_
68+
}
5869
]
5970
}

0 commit comments

Comments
 (0)