diff --git a/TongsuoToolbox_v01.pro b/TongsuoToolbox_v01.pro
index a6e639c..64312dc 100644
--- a/TongsuoToolbox_v01.pro
+++ b/TongsuoToolbox_v01.pro
@@ -13,6 +13,7 @@ SOURCES += \
main.cpp \
mainwindow.cpp \
randnum.cpp \
+ sm2cert.cpp \
sm2encrypt.cpp \
sm2key.cpp \
sm2signverify.cpp \
@@ -24,6 +25,7 @@ HEADERS += \
home.h \
mainwindow.h \
randnum.h \
+ sm2cert.h \
sm2encrypt.h \
sm2key.h \
sm2signverify.h \
@@ -48,6 +50,7 @@ else:unix: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib64/libcrypto.a
FORMS += \
home.ui \
randnum.ui \
+ sm2cert.ui \
sm2encrypt.ui \
sm2key.ui \
sm2signverify.ui \
diff --git a/certs.qrc b/certs.qrc
new file mode 100644
index 0000000..f997abc
--- /dev/null
+++ b/certs.qrc
@@ -0,0 +1,6 @@
+
+
+ certs/subca.pem
+ certs/subca_pkey.pem
+
+
diff --git a/certs/ca.pem b/certs/ca.pem
new file mode 100644
index 0000000..d16953b
--- /dev/null
+++ b/certs/ca.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIB2zCCAYKgAwIBAgIBADAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
+A1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0GA1UEAwwGQ0Eg
+U00yMB4XDTIzMTAyMjA4MTYzNVoXDTI0MTAyMTA4MTYzNVowRTELMAkGA1UEBhMC
+QUIxCzAJBgNVBAgMAkNEMQswCQYDVQQKDAJHSDELMAkGA1UECwwCSUoxDzANBgNV
+BAMMBkNBIFNNMjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABGDEBzKqxehinDE1
+yVmhtBg4RZl3yMdYbSQ1YCS4Oq39UpYnIPBQZJtFVcp/mzYkEatAFH3bULzZN9i2
+tYKVG9OjYzBhMB0GA1UdDgQWBBSGjjM6h6hZvgui1qC/aWzcwA8DxTAfBgNVHSME
+GDAWgBSGjjM6h6hZvgui1qC/aWzcwA8DxTAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBhjAKBggqgRzPVQGDdQNHADBEAiAG1lSJPjiucZM7Ono6Ym4cZRJ6
+FkYkRCbmUsA7KGUurAIgPB75xE9nBCvjOA5mX0w6qTIxyca9ZZQW/fXKiD7rc9w=
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/certs/ca_pkey.pem b/certs/ca_pkey.pem
new file mode 100644
index 0000000..6946edd
--- /dev/null
+++ b/certs/ca_pkey.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgvQZKYXBs2tJ75OiC
+Heno6Hy2hOgF40spgGXQjq9wM22hRANCAARgxAcyqsXoYpwxNclZobQYOEWZd8jH
+WG0kNWAkuDqt/VKWJyDwUGSbRVXKf5s2JBGrQBR921C82TfYtrWClRvT
+-----END PRIVATE KEY-----
\ No newline at end of file
diff --git a/certs/subca.pem b/certs/subca.pem
new file mode 100644
index 0000000..50735f9
--- /dev/null
+++ b/certs/subca.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB4jCCAYigAwIBAgIBADAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
+A1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0GA1UEAwwGQ0Eg
+U00yMB4XDTIzMTAyMjA4MTY1MFoXDTI0MTAyMTA4MTY1MFowSDELMAkGA1UEBhMC
+QUIxCzAJBgNVBAgMAkNEMQswCQYDVQQKDAJHSDELMAkGA1UECwwCSUoxEjAQBgNV
+BAMMCVNVQkNBIFNNMjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABIWmHv6geS35
+44DbP2u7YJwqswfnHEYrWflC9f2KKFDysQREA92amnPCExdQkM/ei7gQp4KjLI6q
+bb6pOuge9qujZjBkMB0GA1UdDgQWBBTrKs5sc0eO1wXiY3pVVctAALwRxjAfBgNV
+HSMEGDAWgBSGjjM6h6hZvgui1qC/aWzcwA8DxTASBgNVHRMBAf8ECDAGAQH/AgEA
+MA4GA1UdDwEB/wQEAwIBhjAKBggqgRzPVQGDdQNIADBFAiBpzPyJFkWFw7x33wod
+1yGoFzj2tspPc58vhnJoxACngwIhAIusYCpxvLmvHkegG1MZwSCr48GthBrfGkR4
+eQIgVj4P
+-----END CERTIFICATE-----
\ No newline at end of file
diff --git a/certs/subca_pkey.pem b/certs/subca_pkey.pem
new file mode 100644
index 0000000..809d283
--- /dev/null
+++ b/certs/subca_pkey.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgthXQl7N8urUeP84X
+1Zc7+0o1QLlfXdOcBc+zLuyYsnWhRANCAASFph7+oHkt+eOA2z9ru2CcKrMH5xxG
+K1n5QvX9iihQ8rEERAPdmppzwhMXUJDP3ou4EKeCoyyOqm2+qTroHvar
+-----END PRIVATE KEY-----
\ No newline at end of file
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 7595237..39f5f6d 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -31,6 +31,8 @@ MainWindow::MainWindow(QWidget *parent)
sm2SignVerify = new Sm2SignVerify();
/* SM4加解密实例化 */
sm4Encry = new Sm4encrypt();
+ /* SM2签发证书实例化 */
+ sm2Cer = new Sm2Cert();
/* 左侧功能导航 */
QList strListWidgetList;
strListWidgetList << "首页"
@@ -39,8 +41,9 @@ MainWindow::MainWindow(QWidget *parent)
<< "SM2加解密"
<< "SM3哈希"
<< "SM2签名验签"
- << "SM4加解密";
- for (int i = 0; i < 7; i++) {
+ << "SM4加解密"
+ << "SM2签发证书";
+ for (int i = 0; i < 8; i++) {
/* listWidget 插入项 */
listWidget->insertItem(i, strListWidgetList[i]);
}
@@ -52,6 +55,7 @@ MainWindow::MainWindow(QWidget *parent)
stackedWidget->addWidget(sm3Hash);
stackedWidget->addWidget(sm2SignVerify);
stackedWidget->addWidget(sm4Encry);
+ stackedWidget->addWidget(sm2Cer);
/* 设置列表的最大宽度 */
listWidget->setMaximumWidth(200);
/* 添加到水平布局 */
diff --git a/mainwindow.h b/mainwindow.h
index 932c0b6..c97dc90 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -3,6 +3,7 @@
#include "home.h"
#include "randnum.h"
+#include "sm2cert.h"
#include "sm2encrypt.h"
#include "sm2key.h"
#include "sm2signverify.h"
@@ -44,5 +45,7 @@ class MainWindow : public QMainWindow
Sm2SignVerify *sm2SignVerify;
/* sm4加解密界面 */
Sm4encrypt *sm4Encry;
+ /* sm2签发证书 */
+ Sm2Cert *sm2Cer;
};
#endif // MAINWINDOW_H
diff --git a/sm2cert.cpp b/sm2cert.cpp
new file mode 100644
index 0000000..2fbaaa2
--- /dev/null
+++ b/sm2cert.cpp
@@ -0,0 +1,169 @@
+#include "sm2cert.h"
+#include "ui_sm2cert.h"
+
+Sm2Cert::Sm2Cert(QWidget *parent)
+ : QWidget(parent)
+ , ui(new Ui::Sm2Cert)
+{
+ ui->setupUi(this);
+}
+
+Sm2Cert::~Sm2Cert()
+{
+ delete ui;
+}
+std::shared_ptr Sm2Cert::genCert(int type,
+ std::shared_ptr midCA,
+ std::shared_ptr midcaPkey,
+ QString CNname,
+ QString days)
+{
+ /* 生成用户密钥 */
+ std::shared_ptr userKey(EVP_PKEY_Q_keygen(NULL, NULL, "SM2"), EVP_PKEY_free);
+ if (userKey.get() == NULL) {
+ /* 错误处理 */
+ getError();
+ exit(0);
+ }
+ /* 输出用户私钥 */
+ std::shared_ptr out(BIO_new(BIO_s_mem()), BIO_free);
+ PEM_write_bio_PrivateKey(out.get(), userKey.get(), NULL, 0, NULL, NULL, NULL);
+ int len = BIO_pending(out.get());
+ char buf[1024] = {};
+ BIO_read(out.get(), buf, len);
+ if (type == 0) {
+ this->ui->textBrowserEncryKey->setText(QString(buf));
+ } else {
+ this->ui->textBrowserSignKey->setText(QString(buf));
+ }
+ /* 生成CSR */
+ std::shared_ptr userReq(X509_REQ_new(), X509_REQ_free);
+ /* CSR相关设置 */
+ X509_REQ_set_pubkey(userReq.get(), userKey.get());
+
+ std::shared_ptr userCAname(X509_NAME_new(), X509_NAME_free);
+ X509_NAME_add_entry_by_txt(userCAname.get(),
+ "CN",
+ MBSTRING_ASC,
+ (unsigned char *) CNname.toStdString().c_str(),
+ -1,
+ -1,
+ 0);
+ X509_REQ_set_subject_name(userReq.get(), userCAname.get());
+
+ X509_REQ_set_version(userReq.get(), X509_VERSION_3);
+ X509_REQ_sign(userReq.get(), userKey.get(), EVP_sm3());
+ X509_REQ_verify(userReq.get(), userKey.get());
+
+ /* 签发证书 */
+ std::shared_ptr userCer(X509_new(), X509_free);
+ /* 证书相关设置 */
+ std::string str;
+ if (type == 0) {
+ str = "Key Encipherment, Data Encipherment";
+ } else {
+ str = "Digital Signature";
+ }
+ std::shared_ptr
+ cert_ex(X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, str.c_str()), X509_EXTENSION_free);
+ X509_add_ext(userCer.get(), cert_ex.get(), -1);
+
+ X509_set_version(userCer.get(), X509_VERSION_3);
+ X509_set_pubkey(userCer.get(), userKey.get());
+
+ std::shared_ptr aserial(ASN1_INTEGER_new(), ASN1_INTEGER_free);
+ ASN1_INTEGER_set(aserial.get(), 0);
+ X509_set_serialNumber(userCer.get(), aserial.get());
+
+ X509_set_subject_name(userCer.get(), userCAname.get());
+
+ const X509_NAME *rootCAname = X509_get_subject_name(midCA.get());
+ X509_set_issuer_name(userCer.get(), rootCAname);
+
+ time_t curTime = time(NULL);
+ std::shared_ptr rootBeforeTime(ASN1_TIME_new(), ASN1_TIME_free);
+ ASN1_TIME_set(rootBeforeTime.get(), curTime);
+ X509_set_notBefore(userCer.get(), rootBeforeTime.get());
+ std::shared_ptr
+ rootAfterTime(ASN1_TIME_adj(NULL, curTime, 0, days.toInt() * 60 * 60 * 24), ASN1_TIME_free);
+ X509_set_notAfter(userCer.get(), rootAfterTime.get());
+ /* 使用中间CA私钥签发 */
+ X509_sign(userCer.get(), midcaPkey.get(), EVP_sm3());
+
+ return userCer;
+}
+
+void Sm2Cert::on_pushButtonGen_clicked()
+{
+ /* 获取用户输入的通用名称 */
+ QString CN = this->ui->lineEditCN->text();
+ if (CN.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入通用名称!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+ /* 获取用户输入的有效期 */
+ QString days = this->ui->lineEditDays->text();
+ if (days.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入有效期!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+ /* 读取中间CA证书 */
+ QFile fsubca(":/certs/subca.pem");
+ if (!fsubca.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("subca.pem打开失败!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+ QTextStream subcaInput(&fsubca);
+ QString subcaQstr = subcaInput.readAll();
+ std::shared_ptr subcaOut(BIO_new(BIO_s_mem()), BIO_free);
+ BIO_write(subcaOut.get(), subcaQstr.toStdString().c_str(), subcaQstr.size());
+ std::shared_ptr subca(PEM_read_bio_X509(subcaOut.get(), NULL, NULL, NULL), X509_free);
+ fsubca.close();
+
+ /* 读取中间CA私钥 */
+ QFile fpkey(":/certs/subca_pkey.pem");
+ if (!fpkey.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("subca_pkey.pem打开失败!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+ QTextStream pkeyInput(&fpkey);
+ QString pkeyQstr = pkeyInput.readAll();
+ std::shared_ptr pkeyOut(BIO_new(BIO_s_mem()), BIO_free);
+ BIO_write(pkeyOut.get(), pkeyQstr.toStdString().c_str(), pkeyQstr.size());
+ std::shared_ptr pkey(PEM_read_bio_PrivateKey(pkeyOut.get(), NULL, NULL, NULL),
+ EVP_PKEY_free);
+ fpkey.close();
+
+ /* 生成用户签名证书 */
+ std::shared_ptr userSignCer = this->genCert(1, subca, pkey, CN, days);
+ /* 生成用户加密证书 */
+ std::shared_ptr userEncryptCer = this->genCert(0, subca, pkey, CN, days);
+ /* 将用户证书以PEM格式输出到输出栏 */
+ std::shared_ptr outSign(BIO_new(BIO_s_mem()), BIO_free);
+ PEM_write_bio_X509(outSign.get(), userSignCer.get());
+ int len = BIO_pending(outSign.get());
+ char buf[2048] = {};
+ BIO_read(outSign.get(), buf, len);
+ this->ui->textBrowserSignOutput->setPlainText(QString(buf));
+ std::shared_ptr outEncrypt(BIO_new(BIO_s_mem()), BIO_free);
+ PEM_write_bio_X509(outEncrypt.get(), userEncryptCer.get());
+ len = BIO_pending(outEncrypt.get());
+ BIO_read(outEncrypt.get(), buf, len);
+ this->ui->textBrowserEncryptOutput->setPlainText(QString(buf));
+}
diff --git a/sm2cert.h b/sm2cert.h
new file mode 100644
index 0000000..1628fd5
--- /dev/null
+++ b/sm2cert.h
@@ -0,0 +1,42 @@
+#ifndef SM2CERT_H
+#define SM2CERT_H
+
+#include "tserror.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace Ui {
+class Sm2Cert;
+}
+
+class Sm2Cert : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit Sm2Cert(QWidget *parent = nullptr);
+ ~Sm2Cert();
+
+private slots:
+ void on_pushButtonGen_clicked();
+
+private:
+ Ui::Sm2Cert *ui;
+ /* type等于1生成签名证书,等于0生成加密证书 */
+ std::shared_ptr genCert(int type,
+ std::shared_ptr midCA,
+ std::shared_ptr midcaPkey,
+ QString CNname,
+ QString days);
+};
+
+#endif // SM2CERT_H
diff --git a/sm2cert.ui b/sm2cert.ui
new file mode 100644
index 0000000..28254fb
--- /dev/null
+++ b/sm2cert.ui
@@ -0,0 +1,158 @@
+
+
+ Sm2Cert
+
+
+
+ 0
+ 0
+ 400
+ 300
+
+
+
+ Form
+
+
+ -
+
+
+ 签名证书&密钥:
+
+
+
+ -
+
+
+ 365
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+
+
+
+ tongsuo
+
+
+ 一般为域名
+
+
+
+ -
+
+
+ -
+
+
+ 生成证书
+
+
+
+ -
+
+
+ 通用名称:
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ 私钥/请求:
+
+
+
+ -
+
+
+ 有效天数:
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+ 自动生成
+
+
+
+ -
+
+
+ 手动生成
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ 加密证书&密钥:
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+