PKI-证书签发及交叉验证

CA.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#include "stdio.h"
#include <string>

#include "httplib.h"
#include "json.hpp"
#include "../../lab2/miracl/cpp/core.h"
#include "../../lab2/miracl/cpp/randapi.h"
#include "../../lab2/miracl/cpp/rsa_RSA2048.h"
#include "../../lab2/miracl/cpp/big_B512_60.h"
using json = nlohmann::json;
using namespace core;
using namespace RSA2048;
using namespace B512_60;
using namespace std;

rsa_public_key pub;
rsa_private_key priv;
char capkhex[MODBYTES_B512_60 * 4 * 2 + 1];
char caName[256];
char caSelfSignHex[RFS_RSA2048 * 2 + 1];

void big2hex(char *buff, BIG b)
{
char tmp[MODBYTES_B512_60];
BIG_toBytes(tmp, b);
octet oct = {MODBYTES_B512_60, MODBYTES_B512_60, tmp};
OCT_toHex(&oct, buff);
}

void hex2big(BIG b, char *buff)
{
char *src;
src = (char *)malloc(MODBYTES_B512_60 * 2 + 1);
memcpy(src, buff, MODBYTES_B512_60 * 2);
src[MODBYTES_B512_60 * 2] = '\0';

char tmp[MODBYTES_B512_60];
octet oct = {0, MODBYTES_B512_60, tmp};
OCT_fromHex(&oct, src);
BIG_fromBytes(b, tmp);
}

int main(int argc, char const *argv[])
{
if (argc < 3) {
printf("Usage: %s <CA_name> <port>\n", argv[0]);
return 1;
}
strncpy(caName, argv[1], sizeof(caName) - 1);
caName[sizeof(caName) - 1] = '\0';
int port = stoi(argv[2]);

// HTTP
httplib::Server svr;

int i, res;
unsigned long ran;
char raw[100];
octet RAW = {0, sizeof(raw), raw};
csprng RNG;

time((time_t *)&ran);

RAW.len = 100;
RAW.val[0] = ran;
RAW.val[1] = ran >> 8;
RAW.val[2] = ran >> 16;
RAW.val[3] = ran >> 24;
for (i = 4; i < 100; i++)
RAW.val[i] = i;

CREATE_CSPRNG(&RNG, &RAW);

printf("Generating public/private key pair for %s\n", caName);
RSA_KEY_PAIR(&RNG, 65537, &priv, &pub, NULL, NULL);

printf("Saving public/private key pair\n");
string pkPath = string("./") + caName + ".pk";
FILE *fp = fopen(pkPath.c_str(), "w");

for (int i = 0; i < FFLEN_RSA2048; i++)
{
big2hex(capkhex + i * MODBYTES_B512_60 * 2, pub.n[i]);
}
fprintf(fp, "%s", capkhex);
fclose(fp);

// 创建CA自签名证书(用于交叉认证时供其他CA验证)
{
char *caSignData;
int caSignDataLen = strlen(caName) + strlen(capkhex);
caSignData = (char *)malloc(caSignDataLen);
memcpy(caSignData, caName, strlen(caName));
memcpy(caSignData + strlen(caName), capkhex, strlen(capkhex));

octet CA_SIGNDATA = {caSignDataLen, caSignDataLen, caSignData};
char caHashedData[RFS_RSA2048];
octet CA_HASHDATA = {0, sizeof(caHashedData), caHashedData};
char caSign[RFS_RSA2048];
octet CA_SIGN = {0, sizeof(caSign), caSign};

PKCS15(HASH_TYPE_RSA_RSA2048, &CA_SIGNDATA, &CA_HASHDATA);
RSA_DECRYPT(&priv, &CA_HASHDATA, &CA_SIGN);
OCT_toHex(&CA_SIGN, caSelfSignHex);
free(caSignData);
}
printf("CA self-signed certificate created\n");

svr.Get("/", [](const httplib::Request &, httplib::Response &res)
{ res.set_content("Hello World!", "text/plain"); });

// 返回本CA的自签名证书,供其他CA进行交叉认证
svr.Get("/ca-info", [](const httplib::Request &, httplib::Response &res)
{
json result;
result["name"] = caName;
result["publickey"] = capkhex;
result["sign"] = caSelfSignHex;
res.set_content(result.dump(), "application/json");
});

// 证书签发:接受用户自签名证书后验证,并签发CA签名的证书
svr.Post("/certissue", [](const httplib::Request &req, httplib::Response &res)
{
auto jobject = json::parse(req.body);
std::string name = jobject.at("name");
std::string pk = jobject.at("publickey");

std::string sign = jobject.at("sign");

char *signdata;
int signdatalength = name.length() + pk.length();
signdata = (char *)malloc(signdatalength);
char hasheddata[RFS_RSA2048];
char casign[RFS_RSA2048];
char verifydata[RFS_RSA2048];

octet SIGNDATA = {signdatalength, signdatalength, signdata};
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
octet SIGN = {0, sizeof(casign), casign};
octet VERIFY = {0, sizeof(verifydata), verifydata};

memcpy(signdata, name.c_str(), name.length());
memcpy(signdata + name.length(), pk.c_str(), pk.length());
rsa_public_key userPK;
userPK.e = 65537;
for (int i = 0; i < FFLEN_RSA2048; i++)
{
hex2big(userPK.n[i], (char *)pk.c_str() + i * MODBYTES_B512_60 * 2);
}
OCT_fromHex(&SIGN, (char *)sign.c_str());

RSA_ENCRYPT(&userPK, &SIGN, &VERIFY);
PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
PKCS15b(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
json result;
result["result"] = false;
result["msg"] = "error sign";
res.set_content(result.dump(), "application/json");
free(signdata);
return;
}
}

RSA_DECRYPT(&priv, &HASHDATA, &SIGN);
char caSignHex[RFS_RSA2048 * 2];
OCT_toHex(&SIGN, caSignHex);

json result;
json userCert;
userCert["name"] = name;
userCert["publickey"] = pk;
userCert["sign"] = caSignHex;
userCert["issuer"] = caName;
result["result"] = true;
result["cert"] = userCert;
result["caCert"] = capkhex;
res.set_content(result.dump(), "application/json");
free(signdata);
return; });

// 交叉认证:接收另一个CA的自签名证书,验证后用自己的私钥签发交叉证书
svr.Post("/cross-certify", [](const httplib::Request &req, httplib::Response &res)
{
auto jobject = json::parse(req.body);
std::string otherName = jobject.at("name");
std::string otherPK = jobject.at("publickey");
std::string otherSign = jobject.at("sign");

char *signdata;
int signdatalength = otherName.length() + otherPK.length();
signdata = (char *)malloc(signdatalength);
char hasheddata[RFS_RSA2048];
char mysign[RFS_RSA2048];
char verifydata[RFS_RSA2048];

octet SIGNDATA = {signdatalength, signdatalength, signdata};
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
octet SIGN = {0, sizeof(mysign), mysign};
octet VERIFY = {0, sizeof(verifydata), verifydata};

// 加载待验证数据:otherCA的name + publickey
memcpy(signdata, otherName.c_str(), otherName.length());
memcpy(signdata + otherName.length(), otherPK.c_str(), otherPK.length());

// 加载对方CA的公钥
rsa_public_key otherPub;
otherPub.e = 65537;
for (int i = 0; i < FFLEN_RSA2048; i++)
{
hex2big(otherPub.n[i], (char *)otherPK.c_str() + i * MODBYTES_B512_60 * 2);
}

// 加载对方CA的自签名
OCT_fromHex(&SIGN, (char *)otherSign.c_str());

// 验证对方CA的自签名
RSA_ENCRYPT(&otherPub, &SIGN, &VERIFY);
PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
PKCS15b(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
json result;
result["result"] = false;
result["msg"] = "cannot verify other CA's self-signature";
res.set_content(result.dump(), "application/json");
free(signdata);
return;
}
}

// 用自己的私钥对对方CA的(name+publickey)签名,生成交叉证书
RSA_DECRYPT(&priv, &HASHDATA, &SIGN);
char crossSignHex[RFS_RSA2048 * 2];
OCT_toHex(&SIGN, crossSignHex);

json result;
result["result"] = true;
json crossCert;
crossCert["name"] = otherName;
crossCert["publickey"] = otherPK;
crossCert["sign"] = crossSignHex;
crossCert["issuer"] = caName;
result["crossCert"] = crossCert;
res.set_content(result.dump(), "application/json");
free(signdata);
return; });

// 交叉验证服务:验证从其他PKI系统来的用户证书
// 客户端将 (用户证书 + 本CA签发的交叉证书) 提交过来,CA完成信任链验证
svr.Post("/verify-cross", [](const httplib::Request &req, httplib::Response &res)
{
auto jobject = json::parse(req.body);
json userCert = jobject.at("userCert");
json crossCert = jobject.at("crossCert");

// ---- 第一步:用本CA的公钥验证交叉证书 ----
std::string crossName = crossCert.at("name");
std::string crossPK = crossCert.at("publickey");
std::string crossSign = crossCert.at("sign");

char *crossSigndata;
int crossSigndatalen = crossName.length() + crossPK.length();
crossSigndata = (char *)malloc(crossSigndatalen);
char hasheddata[RFS_RSA2048];
char verifydata[RFS_RSA2048];
char signbuf[RFS_RSA2048];

octet SIGNDATA = {crossSigndatalen, crossSigndatalen, crossSigndata};
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
octet VERIFY = {0, sizeof(verifydata), verifydata};
octet SIGN = {0, sizeof(signbuf), signbuf};

memcpy(crossSigndata, crossName.c_str(), crossName.length());
memcpy(crossSigndata + crossName.length(), crossPK.c_str(), crossPK.length());
OCT_fromHex(&SIGN, (char *)crossSign.c_str());

RSA_ENCRYPT(&pub, &SIGN, &VERIFY);
PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
PKCS15b(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
json result;
result["result"] = false;
result["msg"] = "交叉证书验证失败:交叉证书不是本CA签发的";
res.set_content(result.dump(), "application/json");
free(crossSigndata);
return;
}
}
free(crossSigndata);

// ---- 第二步:从已验证的交叉证书中提取对方CA的公钥 ----
rsa_public_key otherCAPub;
otherCAPub.e = 65537;
for (int i = 0; i < FFLEN_RSA2048; i++)
{
hex2big(otherCAPub.n[i], (char *)crossPK.c_str() + i * MODBYTES_B512_60 * 2);
}

// ---- 第三步:用对方CA的公钥验证用户证书 ----
std::string userName = userCert.at("name");
std::string userPK = userCert.at("publickey");
std::string userSign = userCert.at("sign");

char *userSigndata;
int userSigndatalen = userName.length() + userPK.length();
userSigndata = (char *)malloc(userSigndatalen);
char hasheddata2[RFS_RSA2048];
char verifydata2[RFS_RSA2048];
char signbuf2[RFS_RSA2048];

octet SIGNDATA2 = {userSigndatalen, userSigndatalen, userSigndata};
octet HASHDATA2 = {0, sizeof(hasheddata2), hasheddata2};
octet VERIFY2 = {0, sizeof(verifydata2), verifydata2};
octet SIGN2 = {0, sizeof(signbuf2), signbuf2};

memcpy(userSigndata, userName.c_str(), userName.length());
memcpy(userSigndata + userName.length(), userPK.c_str(), userPK.length());
OCT_fromHex(&SIGN2, (char *)userSign.c_str());

RSA_ENCRYPT(&otherCAPub, &SIGN2, &VERIFY2);
PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA2, &HASHDATA2);
if (OCT_comp(&HASHDATA2, &VERIFY2) == 0)
{
PKCS15b(HASH_TYPE_RSA_RSA2048, &SIGNDATA2, &HASHDATA2);
if (OCT_comp(&HASHDATA2, &VERIFY2) == 0)
{
json result;
result["result"] = false;
result["msg"] = "用户证书验证失败:用户证书不是由交叉证书中的CA签发的";
res.set_content(result.dump(), "application/json");
free(userSigndata);
return;
}
}
free(userSigndata);

json result;
result["result"] = true;
result["msg"] = "交叉验证成功:用户证书通过信任链验证";
result["trustChain"] = string(caName) + " -> " + crossName + " -> " + userName;
res.set_content(result.dump(), "application/json");
return; });

printf("%s listening on port %d\n", caName, port);
svr.listen("0.0.0.0", port);
return 0;
}

client.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
#include "stdio.h"
#include <sys/time.h>
#include <cstdlib>

#include "httplib.h"
#include "json.hpp"
#include "../../lab2/miracl/cpp/core.h"
#include "../../lab2/miracl/cpp/randapi.h"
#include "../../lab2/miracl/cpp/rsa_RSA2048.h"
#include "../../lab2/miracl/cpp/big_B512_60.h"
#include "../../lab2/miracl/cpp/eddsa_Ed25519.h"
using json = nlohmann::json;
using namespace core;
using namespace RSA2048;
using namespace B512_60;
using namespace std;

rsa_public_key ca_pub;

rsa_public_key clientPub1;
rsa_private_key clientPri1;
json cert1;

rsa_public_key clientPub2;
rsa_private_key clientPri2;
json cert2;

void big2hex(char *buff, BIG b)
{
char tmp[MODBYTES_B512_60];
BIG_toBytes(tmp, b);
octet oct = {MODBYTES_B512_60, MODBYTES_B512_60, tmp};
OCT_toHex(&oct, buff);
}

void hex2big(BIG b, char *buff)
{
char *src;
src = (char *)malloc(MODBYTES_B512_60 * 2 + 1);
memcpy(src, buff, MODBYTES_B512_60 * 2);
src[MODBYTES_B512_60 * 2] = '\0';

char tmp[MODBYTES_B512_60];
octet oct = {0, MODBYTES_B512_60, tmp};
OCT_fromHex(&oct, src);
BIG_fromBytes(b, tmp);
}

void requestCert(string clientname, rsa_public_key *pub, rsa_private_key *priv, json *cert)
{
// HTTP
httplib::Client client("http://localhost:8880");

int i;
unsigned long ran;
char raw[100];
octet RAW = {0, sizeof(raw), raw};
csprng RNG; // Crypto Strong RNG

time((time_t *)&ran);

RAW.len = 100; // fake random seed source
RAW.val[0] = ran;
RAW.val[1] = ran >> 8;
RAW.val[2] = ran >> 16;
RAW.val[3] = ran >> 24;
for (i = 4; i < 100; i++)
RAW.val[i] = i;

CREATE_CSPRNG(&RNG, &RAW); // initialise strong RNG

printf("Generating public/private key pair\n");
RSA_KEY_PAIR(&RNG, 65537, priv, pub, NULL, NULL);

json reqJson;
std::string name = clientname;
char userPKChars[MODBYTES_B512_60 * 4 * 2];
for (int i = 0; i < FFLEN_RSA2048; i++)
{
big2hex(userPKChars + i * MODBYTES_B512_60 * 2, pub->n[i]);
}
// std::string publickeystr = string(userPKChars, 512);

reqJson["name"] = name;
reqJson["publickey"] = userPKChars;

char *signdata;
int signdatalength = name.length() + sizeof(userPKChars);
signdata = (char *)malloc(signdatalength);
memcpy(signdata, name.c_str(), name.length());
memcpy(signdata + name.length(), userPKChars, sizeof(userPKChars));
// 存储待签名数据
octet SIGNDATA = {signdatalength, signdatalength, signdata};

// 存储待签名数据的hash
char hasheddata[RFS_RSA2048];
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
// 存储签名
char sign[RFS_RSA2048];
octet SIGN = {0, sizeof(sign), sign};

PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
RSA_DECRYPT(priv, &HASHDATA, &SIGN);
char signHex[RFS_RSA2048 * 2];
OCT_toHex(&SIGN, signHex);
reqJson["sign"] = signHex;
cout << reqJson << endl;
auto res = client.Post("/certissue", reqJson.dump(), "application/json");

// cout << "start..." << endl;
// cout << "pk1:" << pub.n[0] << endl;

*cert = json::parse(res->body).at("cert");
cout << cert << endl;
}

void loadPubFromFile()
{

FILE *fp = NULL;
char buff[600];

fp = fopen("CA1.pk", "r");
fscanf(fp, "%s", buff);
fclose(fp);

ca_pub.e = 65537;
for (int i = 0; i < FFLEN_RSA2048; i++)
{
hex2big(ca_pub.n[i], buff + i * MODBYTES_B512_60 * 2);
}
}

void VerifyCert(json *cert)
{
std::string name = cert->at("name");
std::string pk = cert->at("publickey");
std::string sign = cert->at("sign");

char *signdata;
int signdatalength = name.length() + pk.length();
signdata = (char *)malloc(signdatalength);
char hasheddata[RFS_RSA2048];
char verifydata[RFS_RSA2048];
char casign[RFS_RSA2048];

// 存储待签名数据
octet SIGNDATA = {signdatalength, signdatalength, signdata};
// 存储待签名数据的hash
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
// 存储验签用的数据
octet VERIFY = {0, sizeof(verifydata), verifydata};
// 存储签名
octet SIGN = {0, sizeof(casign), casign};
// 先验证用户的签名对不对
// 开始load待签名数据
memcpy(signdata, name.c_str(), name.length());
memcpy(signdata + name.length(), pk.c_str(), pk.length());

// load签名
OCT_fromHex(&SIGN, (char *)sign.c_str());
// 验用户的自签名
RSA_ENCRYPT(&ca_pub, &SIGN, &VERIFY);
PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
PKCS15b(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
cout << "证书错误" << endl;
// res.set_content(result.dump(), "application/json");
exit(-1);
}
}
cout << "证书正确" << endl;
}

void DHSim()
{
// TODO: 这部分,其实应该用ECDH,RSA上好像没有办法构建DH算法。这主要是因为,模数n和公私钥相关(n=p*q),大家n都不一样。
// 这部分懒得重写前面证书了。大家有兴趣的可以去看:https://github.com/miracl/core/blob/master/cpp/testecc.cpp,里面有好几个不同曲线的ECDH算法
// 那么,在TLS里面,其实也有用RSA来做会话密钥生成的。具体过程:https://www.cnblogs.com/my_life/articles/5857614.html
// 下面模拟这个过程
// 再,这里也不想写socket了,所有就直接输出吧。不然代码后面更长了orz

unsigned long ran;
char raw[100];
octet RAW = {0, sizeof(raw), raw};
csprng RNG; // Crypto Strong RNG

time((time_t *)&ran);

RAW.len = 100; // fake random seed source
RAW.val[0] = ran;
RAW.val[1] = ran >> 8;
RAW.val[2] = ran >> 16;
RAW.val[3] = ran >> 24;
for (int i = 4; i < 100; i++)
RAW.val[i] = i;

CREATE_CSPRNG(&RNG, &RAW); // initialise strong RNG

srand((unsigned)time(NULL));
int randNum1 = rand();
cout << "用户1向用户2发送:" << endl;
cout << "\t随机数:" << randNum1 << endl;
cout << "\t证书:" << cert1;

cout << "用户2接受到信息,开始验证证书:\t";
VerifyCert(&cert1);

int randNum2 = rand();
cout << "用户2向用户1发送:" << endl;
cout << "\t随机数:" << randNum2 << endl;
cout << "\t证书:" << cert2;

cout << "用户1接受到信息,开始验证证书:\t";
VerifyCert(&cert2);

cout << "用户1再次产生随即数,并用用户2的公钥加密:" << endl;
int randNum3 = rand();
char m[RFS_RSA2048], e[RFS_RSA2048], c[RFS_RSA2048];
octet M = {0, sizeof(m), m};
octet E = {0, sizeof(e), e};
octet C = {0, sizeof(c), c};
OCT_jint(&M, randNum3, 4);
OAEP_ENCODE(HASH_TYPE_RSA_RSA2048, &M, &RNG, NULL, &E);
RSA_ENCRYPT(&clientPub2, &E, &C);
cout << "\t明文为:";
OCT_output(&M);
cout << endl;
cout << "\t密文为:";
OCT_output(&C);
cout << endl;

cout << "用户2收到密文,开始解密:" << endl;
char ml[RFS_RSA2048];
octet ML = {0, sizeof(ml), ml};
RSA_DECRYPT(&clientPri2, &C, &ML); // ... and then decrypt it
// printf("Decrypted\n");
OAEP_DECODE(HASH_TYPE_RSA_RSA2048, NULL, &ML); // decode it
// printf("Decoded\n");
cout << "\t解密明文:";
OCT_output(&ML);
cout << endl;

if (OCT_comp(&M, &ML) == 0)
{
cout << "随机数不一致,会话密钥协商失败(其实,解密的人可能并不知道解密错误,所以实际上是后面还会有一次加解密的对比)" << endl;
}

char key[AESKEY_Ed25519];
octet KEY = {0, sizeof(key), key};
OCT_jint(&M, randNum1, 4);
OCT_jint(&M, randNum2, 4);
KDF2(MC_SHA2, HASH_TYPE_Ed25519, &KEY, AESKEY_Ed25519, &M, NULL);
cout << "协商出的会话密钥为:";
OCT_output(&KEY);
}

int main(int argc, char const *argv[])
{
// attackPassword();
requestCert("client1", &clientPub1, &clientPri1, &cert1);
requestCert("client2", &clientPub2, &clientPri2, &cert2);
loadPubFromFile();

DHSim();

return 0;
}

cross_verify.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include "stdio.h"
#include <string>

#include "httplib.h"
#include "json.hpp"
#include "../../lab2/miracl/cpp/core.h"
#include "../../lab2/miracl/cpp/randapi.h"
#include "../../lab2/miracl/cpp/rsa_RSA2048.h"
#include "../../lab2/miracl/cpp/big_B512_60.h"
#include "../../lab2/miracl/cpp/eddsa_Ed25519.h"
using json = nlohmann::json;
using namespace core;
using namespace RSA2048;
using namespace B512_60;
using namespace std;

// CA1 的公钥(信任锚1)
rsa_public_key ca1Pub;
// CA2 的公钥(信任锚2)
rsa_public_key ca2Pub;

// CA1 为 CA2 签发的交叉证书
json ca2CrossCert;
// CA2 为 CA1 签发的交叉证书
json ca1CrossCert;

void big2hex(char *buff, BIG b)
{
char tmp[MODBYTES_B512_60];
BIG_toBytes(tmp, b);
octet oct = {MODBYTES_B512_60, MODBYTES_B512_60, tmp};
OCT_toHex(&oct, buff);
}

void hex2big(BIG b, char *buff)
{
char *src;
src = (char *)malloc(MODBYTES_B512_60 * 2 + 1);
memcpy(src, buff, MODBYTES_B512_60 * 2);
src[MODBYTES_B512_60 * 2] = '\0';

char tmp[MODBYTES_B512_60];
octet oct = {0, MODBYTES_B512_60, tmp};
OCT_fromHex(&oct, src);
BIG_fromBytes(b, tmp);
}

// 从 hex 字符串加载公钥
void loadPubKey(rsa_public_key *pk, const string &hexPK)
{
pk->e = 65537;
for (int i = 0; i < FFLEN_RSA2048; i++)
{
hex2big(pk->n[i], (char *)hexPK.c_str() + i * MODBYTES_B512_60 * 2);
}
}

// 验证证书签名(通用函数)
bool verifyCert(rsa_public_key *issuerPub, json cert, const string &context)
{
string name = cert.at("name");
string pk = cert.at("publickey");
string sign = cert.at("sign");

char *signdata;
int signdatalength = name.length() + pk.length();
signdata = (char *)malloc(signdatalength);
char hasheddata[RFS_RSA2048];
char verifydata[RFS_RSA2048];
char signbuf[RFS_RSA2048];

octet SIGNDATA = {signdatalength, signdatalength, signdata};
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
octet VERIFY = {0, sizeof(verifydata), verifydata};
octet SIGN = {0, sizeof(signbuf), signbuf};

memcpy(signdata, name.c_str(), name.length());
memcpy(signdata + name.length(), pk.c_str(), pk.length());

OCT_fromHex(&SIGN, (char *)sign.c_str());

RSA_ENCRYPT(issuerPub, &SIGN, &VERIFY);
PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
PKCS15b(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
printf("[%s] 验证失败!\n", context.c_str());
free(signdata);
return false;
}
}
printf("[%s] 验证成功!\n", context.c_str());
free(signdata);
return true;
}

// 获取 CA 的自签名证书
json getCAInfo(int port)
{
httplib::Client cli("localhost", port);
auto res = cli.Get("/ca-info");
if (!res || res->status != 200)
{
printf("无法连接 CA (port %d)\n", port);
exit(1);
}
return json::parse(res->body);
}

// 请求交叉认证:将 otherCA 的自签名证书发送给 issuerCA,
// 由 issuerCA 验证后用自己的私钥签发交叉证书
json requestCrossCertify(int issuerPort, json otherCAInfo)
{
httplib::Client cli("localhost", issuerPort);
json reqBody;
reqBody["name"] = otherCAInfo.at("name");
reqBody["publickey"] = otherCAInfo.at("publickey");
reqBody["sign"] = otherCAInfo.at("sign");

auto res = cli.Post("/cross-certify", reqBody.dump(), "application/json");
if (!res || res->status != 200)
{
printf("交叉认证请求失败 (port %d)\n", issuerPort);
exit(1);
}
json resp = json::parse(res->body);
if (!resp.at("result"))
{
printf("交叉认证被拒绝: %s\n", string(resp.at("msg")).c_str());
exit(1);
}
return resp.at("crossCert");
}


int main(int argc, char const *argv[])
{
printf("========================================\n");
printf(" PKI 交叉认证实验\n");
printf("========================================\n\n");

// ==========================================
// 阶段1:两个 PKI 系统初始化
// ==========================================
printf("【阶段1】两个 PKI 系统初始化\n");
printf("----------------------------------------\n");
printf("假设有两个独立的 PKI 系统:\n");
printf(" PKI-1: CA1 在端口 8880\n");
printf(" PKI-2: CA2 在端口 8881\n");
printf("\n获取各 CA 的自签名证书...\n\n");

json ca1Info = getCAInfo(8880);
printf("CA1 自签名证书:\n 名称: %s\n", string(ca1Info.at("name")).c_str());
printf("CA1 证书内容: %s\n", ca1Info.dump().c_str());

json ca2Info = getCAInfo(8881);
printf("CA2 自签名证书:\n 名称: %s\n", string(ca2Info.at("name")).c_str());
printf("CA2 证书内容: %s\n", ca2Info.dump().c_str());

// 加载两个 CA 的公钥作为信任锚
loadPubKey(&ca1Pub, ca1Info.at("publickey"));
loadPubKey(&ca2Pub, ca2Info.at("publickey"));

// 验证各 CA 的自签名
printf("\n验证各 CA 的自签名证书:\n");
verifyCert(&ca1Pub, ca1Info, "CA1 自签名验证");
verifyCert(&ca2Pub, ca2Info, "CA2 自签名验证");

// ==========================================
// 阶段2:PKI 系统交叉认证
// ==========================================
printf("\n【阶段2】PKI 系统交叉认证\n");
printf("----------------------------------------\n");
printf("CA1 对 CA2 进行交叉认证:CA1 验证 CA2 的自签名,\n");
printf(" 然后用 CA1 的私钥为 CA2 的公钥签发交叉证书...\n");
ca2CrossCert = requestCrossCertify(8880, ca2Info); // CA1 签 CA2
printf(" 交叉证书已生成: CA2 的证书由 %s 签发\n",
string(ca2CrossCert.at("issuer")).c_str());
printf(" 交叉证书内容: %s\n", ca2CrossCert.dump().c_str());

printf("\nCA2 对 CA1 进行交叉认证:CA2 验证 CA1 的自签名,\n");
printf(" 然后用 CA2 的私钥为 CA1 的公钥签发交叉证书...\n");
ca1CrossCert = requestCrossCertify(8881, ca1Info); // CA2 签 CA1
printf(" 交叉证书已生成: CA1 的证书由 %s 签发\n",
string(ca1CrossCert.at("issuer")).c_str());
printf(" 交叉证书内容: %s\n", ca1CrossCert.dump().c_str());

// 验证交叉证书的正确性
printf("\n验证交叉证书:\n");
verifyCert(&ca1Pub, ca2CrossCert, "CA1签发的CA2交叉证书验证"); // CA1的公钥验证CA1签的交叉证书
verifyCert(&ca2Pub, ca1CrossCert, "CA2签发的CA1交叉证书验证"); // CA2的公钥验证CA2签的交叉证书

return 0;
}

client1.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
#include "stdio.h"
#include <string>

#include "httplib.h"
#include "json.hpp"
#include "../../lab2/miracl/cpp/core.h"
#include "../../lab2/miracl/cpp/randapi.h"
#include "../../lab2/miracl/cpp/rsa_RSA2048.h"
#include "../../lab2/miracl/cpp/big_B512_60.h"
#include "../../lab2/miracl/cpp/eddsa_Ed25519.h"
using json = nlohmann::json;
using namespace core;
using namespace RSA2048;
using namespace B512_60;
using namespace std;

// CA1 的公钥(信任锚1)
rsa_public_key ca1Pub;
// CA2 的公钥(信任锚2)
rsa_public_key ca2Pub;

// 用户A的密钥对和证书
rsa_public_key userAPub;
rsa_private_key userAPri;
json userACert;

void big2hex(char *buff, BIG b)
{
char tmp[MODBYTES_B512_60];
BIG_toBytes(tmp, b);
octet oct = {MODBYTES_B512_60, MODBYTES_B512_60, tmp};
OCT_toHex(&oct, buff);
}

void hex2big(BIG b, char *buff)
{
char *src;
src = (char *)malloc(MODBYTES_B512_60 * 2 + 1);
memcpy(src, buff, MODBYTES_B512_60 * 2);
src[MODBYTES_B512_60 * 2] = '\0';

char tmp[MODBYTES_B512_60];
octet oct = {0, MODBYTES_B512_60, tmp};
OCT_fromHex(&oct, src);
BIG_fromBytes(b, tmp);
}

// 从 hex 字符串加载公钥
void loadPubKey(rsa_public_key *pk, const string &hexPK)
{
pk->e = 65537;
for (int i = 0; i < FFLEN_RSA2048; i++)
{
hex2big(pk->n[i], (char *)hexPK.c_str() + i * MODBYTES_B512_60 * 2);
}
}

// 验证证书签名(通用函数)
bool verifyCert(rsa_public_key *issuerPub, json cert, const string &context)
{
string name = cert.at("name");
string pk = cert.at("publickey");
string sign = cert.at("sign");

char *signdata;
int signdatalength = name.length() + pk.length();
signdata = (char *)malloc(signdatalength);
char hasheddata[RFS_RSA2048];
char verifydata[RFS_RSA2048];
char signbuf[RFS_RSA2048];

octet SIGNDATA = {signdatalength, signdatalength, signdata};
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
octet VERIFY = {0, sizeof(verifydata), verifydata};
octet SIGN = {0, sizeof(signbuf), signbuf};

memcpy(signdata, name.c_str(), name.length());
memcpy(signdata + name.length(), pk.c_str(), pk.length());

OCT_fromHex(&SIGN, (char *)sign.c_str());

RSA_ENCRYPT(issuerPub, &SIGN, &VERIFY);
PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
PKCS15b(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
if (OCT_comp(&HASHDATA, &VERIFY) == 0)
{
printf("[%s] 验证失败!\n", context.c_str());
free(signdata);
return false;
}
}
printf("[%s] 验证成功!\n", context.c_str());
free(signdata);
return true;
}

// 获取 CA 的自签名证书
json getCAInfo(int port)
{
httplib::Client cli("localhost", port);
auto res = cli.Get("/ca-info");
if (!res || res->status != 200)
{
printf("无法连接 CA (port %d)\n", port);
exit(1);
}
return json::parse(res->body);
}

// 请求交叉认证:将 otherCA 的自签名证书发送给 issuerCA,
// 由 issuerCA 验证后用自己的私钥签发交叉证书
json requestCrossCertify(int issuerPort, json otherCAInfo)
{
httplib::Client cli("localhost", issuerPort);
json reqBody;
reqBody["name"] = otherCAInfo.at("name");
reqBody["publickey"] = otherCAInfo.at("publickey");
reqBody["sign"] = otherCAInfo.at("sign");

auto res = cli.Post("/cross-certify", reqBody.dump(), "application/json");
if (!res || res->status != 200)
{
printf("交叉认证请求失败 (port %d)\n", issuerPort);
exit(1);
}
json resp = json::parse(res->body);
if (!resp.at("result"))
{
printf("交叉认证被拒绝: %s\n", string(resp.at("msg")).c_str());
exit(1);
}
return resp.at("crossCert");
}

// 为用户请求证书:生成密钥对 -> 自签名 -> CA签发
json requestUserCert(int caPort, const string &userName,
rsa_public_key *pub, rsa_private_key *priv)
{
// 生成用户密钥对
unsigned long ran;
char raw[100];
octet RAW = {0, sizeof(raw), raw};
csprng RNG;

time((time_t *)&ran);
RAW.len = 100;
RAW.val[0] = ran;
RAW.val[1] = ran >> 8;
RAW.val[2] = ran >> 16;
RAW.val[3] = ran >> 24;
for (int i = 4; i < 100; i++)
RAW.val[i] = i;

CREATE_CSPRNG(&RNG, &RAW);
RSA_KEY_PAIR(&RNG, 65537, priv, pub, NULL, NULL);

// 构造公钥 hex
char userPKChars[MODBYTES_B512_60 * 4 * 2 + 1];
for (int i = 0; i < FFLEN_RSA2048; i++)
{
big2hex(userPKChars + i * MODBYTES_B512_60 * 2, pub->n[i]);
}

// 自签名
json reqJson;
reqJson["name"] = userName;
reqJson["publickey"] = userPKChars;

char *signdata;
int signdatalength = userName.length() + strlen(userPKChars);
signdata = (char *)malloc(signdatalength);
memcpy(signdata, userName.c_str(), userName.length());
memcpy(signdata + userName.length(), userPKChars, strlen(userPKChars));

octet SIGNDATA = {signdatalength, signdatalength, signdata};
char hasheddata[RFS_RSA2048];
octet HASHDATA = {0, sizeof(hasheddata), hasheddata};
char sign[RFS_RSA2048];
octet SIGN = {0, sizeof(sign), sign};

PKCS15(HASH_TYPE_RSA_RSA2048, &SIGNDATA, &HASHDATA);
RSA_DECRYPT(priv, &HASHDATA, &SIGN);
char signHex[RFS_RSA2048 * 2];
OCT_toHex(&SIGN, signHex);
reqJson["sign"] = signHex;
free(signdata);

printf("证书申请: %s\n", reqJson.dump().c_str());

// 向 CA 请求签发
httplib::Client cli("localhost", caPort);
auto res = cli.Post("/certissue", reqJson.dump(), "application/json");
if (!res || res->status != 200)
{
printf("证书请求失败 (port %d)\n", caPort);
exit(1);
}
json resp = json::parse(res->body);
if (!resp.at("result"))
{
printf("证书签发被拒绝\n");
exit(1);
}
json cert = resp.at("cert");
printf("证书内容: %s\n", cert.dump().c_str());
return cert;
}

// 调用CA的交叉验证服务:将用户证书和交叉证书提交给CA进行验证
bool requestVerifyCross(int caPort, json userCert, json crossCert)
{
httplib::Client cli("localhost", caPort);
json reqBody;
reqBody["userCert"] = userCert;
reqBody["crossCert"] = crossCert;

auto res = cli.Post("/verify-cross", reqBody.dump(), "application/json");
if (!res || res->status != 200)
{
printf("交叉验证请求失败 (port %d)\n", caPort);
return false;
}
json resp = json::parse(res->body);
if (resp.at("result"))
{
printf("CA返回: %s\n", string(resp.at("msg")).c_str());
printf("信任链: %s\n", string(resp.at("trustChain")).c_str());
return true;
}
else
{
printf("CA返回: %s\n", string(resp.at("msg")).c_str());
return false;
}
}

int main(int argc, char const *argv[])
{
printf("========================================\n");
printf(" 客户端X验证用户A\n");
printf("========================================\n\n");

// ==========================================
// 阶段1:获取并验证 CA 自签名
// ==========================================
printf("【1】CA 自签名\n");
printf("----------------------------------------\n");
printf("CA1:8880 CA2:8881\n\n");

json ca1Info = getCAInfo(8880);
json ca2Info = getCAInfo(8881);

loadPubKey(&ca1Pub, ca1Info.at("publickey"));
loadPubKey(&ca2Pub, ca2Info.at("publickey"));

verifyCert(&ca1Pub, ca1Info, "CA1 自签名验证");
verifyCert(&ca2Pub, ca2Info, "CA2 自签名验证");

// ==========================================
// 阶段2:用户A证书的生成
// ==========================================
printf("\n【2】申请用户A证书\n");
printf("----------------------------------------\n");
printf("向 CA1 申请...\n\n");

userACert = requestUserCert(8880, "UserA", &userAPub, &userAPri);
printf("用户A证书:\n");
printf(" 名称: %s\n", string(userACert.at("name")).c_str());
printf(" 签发者: %s\n", string(userACert.at("issuer")).c_str());

// ==========================================
// 阶段3:获取交叉证书并验证
// ==========================================
printf("\n【3】获取交叉证书\n");
printf("----------------------------------------\n");

json ca1CrossCert = requestCrossCertify(8881, ca1Info); // CA2 签 CA1
printf("交叉证书: CA1 由 %s 签发\n", string(ca1CrossCert.at("issuer")).c_str());
printf("交叉证书内容: %s\n", ca1CrossCert.dump().c_str());
verifyCert(&ca2Pub, ca1CrossCert, "CA2签发的CA1交叉证书验证");

// ==========================================
// 阶段4:用户X对用户A证书的交叉验证
// ==========================================
printf("\n【4】交叉验证\n");
printf("----------------------------------------\n");
bool crossVerifyOK = requestVerifyCross(8881, userACert, ca1CrossCert);

printf("\n========================================\n");
if (crossVerifyOK)
{
printf(" 交叉认证验证成功!\n");
printf(" 用户X通过CA2的验证服务,\n");
printf(" 成功验证了属于PKI-1系统的用户A的证书。\n");
}
else
{
printf(" 交叉认证验证失败!\n");
}
printf("========================================\n\n");

printf("信任链:CA2 -> CA1 -> UserA\n");
return 0;
}

PKI-证书签发及交叉验证
https://eleco.top/2026/05/21/PKI-证书签发及交叉验证/
作者
Eleco
发布于
2026年5月21日
许可协议