diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dd8b00c..a5305e7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -26,8 +26,17 @@ jobs:
run: |
clang-format-15 --Werror --dry-run *.cpp *.h
- build-on-linux:
- runs-on: ubuntu-latest
+ unix:
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [
+ macos-12,
+ macos-13,
+ ubuntu-20.04,
+ ubuntu-22.04,
+ ]
+ runs-on: ${{ matrix.os }}
steps:
- name: checkout tongsuo
uses: actions/checkout@v3
@@ -37,15 +46,15 @@ jobs:
- name: build Tongsuo
working-directory: ./Tongsuo
run: |
- ./config --banner=Configured --prefix=${RUNNER_TEMP}/tongsuo enable-ntls
+ ./config --banner=Configured --prefix=${RUNNER_TEMP}/tongsuo --libdir=${RUNNER_TEMP}/tongsuo/lib enable-ntls
make -s -j4
make install
- uses: actions/checkout@v3
- name: install QT
- uses: jurplel/install-qt-action@v3
+ uses: jurplel/install-qt-action@v4
with:
- version: 6.2.4
+ version: 6.4.3
- name: build tsapp
run: |
@@ -53,8 +62,14 @@ jobs:
make -s -j4
make install
- build-on-windows:
- runs-on: windows-latest
+ windows:
+ strategy:
+ fail-fast: false
+ matrix:
+ os:
+ - windows-2019
+ - windows-2022
+ runs-on: ${{ matrix.os }}
steps:
- uses: ilammy/msvc-dev-cmd@v1
with:
@@ -82,9 +97,9 @@ jobs:
- uses: actions/checkout@v3
- name: install QT
- uses: jurplel/install-qt-action@v3
+ uses: jurplel/install-qt-action@v4
with:
- version: 6.2.4
+ version: 6.4.3
- name: build tsapp
shell: cmd
diff --git a/TongsuoToolbox_v01.pro b/TongsuoToolbox_v01.pro
index 689694a..3d3f234 100644
--- a/TongsuoToolbox_v01.pro
+++ b/TongsuoToolbox_v01.pro
@@ -15,6 +15,7 @@ SOURCES += \
main.cpp \
mainwindow.cpp \
randnum.cpp \
+ sm2.cpp \
sm2cert.cpp \
sm2encrypt.cpp \
sm2key.cpp \
@@ -28,6 +29,7 @@ HEADERS += \
home.h \
mainwindow.h \
randnum.h \
+ sm2.h \
sm2cert.h \
sm2encrypt.h \
sm2key.h \
@@ -42,17 +44,17 @@ target.path = $$(PREFIX)
!isEmpty(target.path): INSTALLS += target
win32: LIBS += -ladvapi32 -lcrypt32 -lgdi32 -luser32 -lws2_32 -L$$(TONGSUO_HOME)/lib -llibcrypto
-else:unix: LIBS += -L$$(TONGSUO_HOME)/lib64 -lcrypto
+else:unix: LIBS += -L$$(TONGSUO_HOME)/lib -lcrypto
win32: LIBS += -ladvapi32 -lcrypt32 -lgdi32 -luser32 -lws2_32 -L$$(TONGSUO_HOME)/lib -llibssl
-else:unix: LIBS += -L$$(TONGSUO_HOME)/lib64 -lssl
+else:unix: LIBS += -L$$(TONGSUO_HOME)/lib -lssl
INCLUDEPATH += $$(TONGSUO_HOME)/include
DEPENDPATH += $$(TONGSUO_HOME)/include
win32-g++: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib/libcrypto.lib.a
else:win32:!win32-g++: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib/libcrypto.lib
-else:unix: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib64/libcrypto.a
+else:unix: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib/libcrypto.a
FORMS += \
home.ui \
diff --git a/certs.qrc b/certs.qrc
index f997abc..9b68185 100644
--- a/certs.qrc
+++ b/certs.qrc
@@ -1,6 +1,6 @@
certs/subca.pem
- certs/subca_pkey.pem
+ certs/subca.key
diff --git a/certs/ca.key b/certs/ca.key
new file mode 100644
index 0000000..69e7e59
--- /dev/null
+++ b/certs/ca.key
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgTSHZtff0A3YHhojG
+HKIu0odvPip6+39lsguxDH3m+TmhRANCAARC7ZCfZAaqCbMEh1K3pEj2S6/ty2yN
+C6x0zIbyxq+mib7qTssQcLrsPMe1EGb2FZQpGk4L9mOzBNlijoi1ocb5
+-----END PRIVATE KEY-----
diff --git a/certs/ca.pem b/certs/ca.pem
index d16953b..bc6f8cc 100644
--- a/certs/ca.pem
+++ b/certs/ca.pem
@@ -1,12 +1,13 @@
-----BEGIN CERTIFICATE-----
-MIIB2zCCAYKgAwIBAgIBADAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
+MIIB3jCCAYSgAwIBAgIBAjAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
A1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0GA1UEAwwGQ0Eg
-U00yMB4XDTIzMTAyMjA4MTYzNVoXDTI0MTAyMTA4MTYzNVowRTELMAkGA1UEBhMC
-QUIxCzAJBgNVBAgMAkNEMQswCQYDVQQKDAJHSDELMAkGA1UECwwCSUoxDzANBgNV
-BAMMBkNBIFNNMjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABGDEBzKqxehinDE1
-yVmhtBg4RZl3yMdYbSQ1YCS4Oq39UpYnIPBQZJtFVcp/mzYkEatAFH3bULzZN9i2
-tYKVG9OjYzBhMB0GA1UdDgQWBBSGjjM6h6hZvgui1qC/aWzcwA8DxTAfBgNVHSME
-GDAWgBSGjjM6h6hZvgui1qC/aWzcwA8DxTAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
-DwEB/wQEAwIBhjAKBggqgRzPVQGDdQNHADBEAiAG1lSJPjiucZM7Ono6Ym4cZRJ6
-FkYkRCbmUsA7KGUurAIgPB75xE9nBCvjOA5mX0w6qTIxyca9ZZQW/fXKiD7rc9w=
------END CERTIFICATE-----
\ No newline at end of file
+U00yMCAXDTI0MDcwNzA0Mjc0NVoYDzIxMjQwNjEzMDQyNzQ1WjBFMQswCQYDVQQG
+EwJBQjELMAkGA1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0G
+A1UEAwwGQ0EgU00yMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEQu2Qn2QGqgmz
+BIdSt6RI9kuv7ctsjQusdMyG8savpom+6k7LEHC67DzHtRBm9hWUKRpOC/ZjswTZ
+Yo6ItaHG+aNjMGEwHQYDVR0OBBYEFGPkDCglafjEeeT2wufS/PqKqSP+MB8GA1Ud
+IwQYMBaAFGPkDCglafjEeeT2wufS/PqKqSP+MA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgGGMAoGCCqBHM9VAYN1A0gAMEUCIQDOKNIcpCOnL/qFC9nYHSY0
+fHWiGgZLLVFkamCN0meRNgIgUfW1xK+7rZddJSHqJKIeHJp28PlKBXY8oIuGhhEz
+EqQ=
+-----END CERTIFICATE-----
diff --git a/certs/ca_pkey.pem b/certs/ca_pkey.pem
deleted file mode 100644
index 6946edd..0000000
--- a/certs/ca_pkey.pem
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgvQZKYXBs2tJ75OiC
-Heno6Hy2hOgF40spgGXQjq9wM22hRANCAARgxAcyqsXoYpwxNclZobQYOEWZd8jH
-WG0kNWAkuDqt/VKWJyDwUGSbRVXKf5s2JBGrQBR921C82TfYtrWClRvT
------END PRIVATE KEY-----
\ No newline at end of file
diff --git a/certs/subca.key b/certs/subca.key
new file mode 100644
index 0000000..b625382
--- /dev/null
+++ b/certs/subca.key
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgC2yI3oPT4cnM8fGf
+J/emyP9/Qr87/x1RO5sNMnm5ioqhRANCAAR73c9xN7bdOrqUQhe/77qxwerRbzZe
+wZ65DXOMgIztuCiCEQLh0CfjPLV98LxHbUhTc1EJWhDGofTqh8VFQNYj
+-----END PRIVATE KEY-----
diff --git a/certs/subca.pem b/certs/subca.pem
index 50735f9..24144c7 100644
--- a/certs/subca.pem
+++ b/certs/subca.pem
@@ -1,13 +1,13 @@
-----BEGIN CERTIFICATE-----
-MIIB4jCCAYigAwIBAgIBADAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
+MIIB4zCCAYqgAwIBAgIBAjAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
A1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0GA1UEAwwGQ0Eg
-U00yMB4XDTIzMTAyMjA4MTY1MFoXDTI0MTAyMTA4MTY1MFowSDELMAkGA1UEBhMC
-QUIxCzAJBgNVBAgMAkNEMQswCQYDVQQKDAJHSDELMAkGA1UECwwCSUoxEjAQBgNV
-BAMMCVNVQkNBIFNNMjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABIWmHv6geS35
-44DbP2u7YJwqswfnHEYrWflC9f2KKFDysQREA92amnPCExdQkM/ei7gQp4KjLI6q
-bb6pOuge9qujZjBkMB0GA1UdDgQWBBTrKs5sc0eO1wXiY3pVVctAALwRxjAfBgNV
-HSMEGDAWgBSGjjM6h6hZvgui1qC/aWzcwA8DxTASBgNVHRMBAf8ECDAGAQH/AgEA
-MA4GA1UdDwEB/wQEAwIBhjAKBggqgRzPVQGDdQNIADBFAiBpzPyJFkWFw7x33wod
-1yGoFzj2tspPc58vhnJoxACngwIhAIusYCpxvLmvHkegG1MZwSCr48GthBrfGkR4
-eQIgVj4P
------END CERTIFICATE-----
\ No newline at end of file
+U00yMCAXDTI0MDcwNzA0Mjc0NloYDzIxMjQwNjEzMDQyNzQ2WjBIMQswCQYDVQQG
+EwJBQjELMAkGA1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjESMBAG
+A1UEAwwJU1VCQ0EgU00yMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEe93PcTe2
+3Tq6lEIXv++6scHq0W82XsGeuQ1zjICM7bgoghEC4dAn4zy1ffC8R21IU3NRCVoQ
+xqH06ofFRUDWI6NmMGQwHQYDVR0OBBYEFCi8tdpCMx+yoWdWdO3IZ6xxDhljMB8G
+A1UdIwQYMBaAFGPkDCglafjEeeT2wufS/PqKqSP+MBIGA1UdEwEB/wQIMAYBAf8C
+AQAwDgYDVR0PAQH/BAQDAgGGMAoGCCqBHM9VAYN1A0cAMEQCIH6UJaA1ppUtSbHn
+3JRGdRHpVKgGaxRkqIVIrfgLnG8IAiBrcRv26xSHRe1eFT9BoJkIiFNTb/gbPdjS
+0kQ4AdEHkQ==
+-----END CERTIFICATE-----
diff --git a/certs/subca_pkey.pem b/certs/subca_pkey.pem
deleted file mode 100644
index 809d283..0000000
--- a/certs/subca_pkey.pem
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgthXQl7N8urUeP84X
-1Zc7+0o1QLlfXdOcBc+zLuyYsnWhRANCAASFph7+oHkt+eOA2z9ru2CcKrMH5xxG
-K1n5QvX9iihQ8rEERAPdmppzwhMXUJDP3ou4EKeCoyyOqm2+qTroHvar
------END PRIVATE KEY-----
\ No newline at end of file
diff --git a/home.ui b/home.ui
index 0c777d8..951f86b 100644
--- a/home.ui
+++ b/home.ui
@@ -8,8 +8,8 @@
0
0
- 400
- 300
+ 800
+ 600
diff --git a/images/HomeBackground.png b/images/HomeBackground.png
index 3fe6e53..516b483 100644
Binary files a/images/HomeBackground.png and b/images/HomeBackground.png differ
diff --git a/main.cpp b/main.cpp
index 115a22b..26c0c73 100644
--- a/main.cpp
+++ b/main.cpp
@@ -1,8 +1,16 @@
#include "mainwindow.h"
+#include
#include
+BIO *bio_err = NULL;
+
int main(int argc, char *argv[])
{
+ if (!OPENSSL_init_ssl(OPENSSL_INIT_NO_LOAD_CONFIG, NULL))
+ return 1;
+
+ bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
QApplication a(argc, argv);
MainWindow w;
w.show();
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 66e7298..e11af70 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -4,9 +4,9 @@ MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
/* 主界面设置 */
- this->setGeometry(480, 200, 800, 480);
+ this->setGeometry(100, 100, 1200, 800);
this->setWindowIcon(QIcon(":/images/TongSuoIcon.png"));
- this->setWindowTitle(QString("TongSuo"));
+ this->setWindowTitle(QString("铜锁密码工具箱"));
/* widget 小部件实例化 */
widget = new QWidget(this);
/* 设置居中 */
@@ -40,11 +40,11 @@ MainWindow::MainWindow(QWidget *parent)
strListWidgetList << "首页"
<< "随机数生成"
<< "SM2密钥生成"
- << "SM2加解密"
- << "SM3哈希"
<< "SM2签名验签"
+ << "SM2加解密"
+ << "SM3杂凑"
<< "SM4加解密"
- << "SM2签发证书"
+ << "双证书签发"
<< "TLCP客户端";
for (int i = 0; i < 9; i++) {
/* listWidget 插入项 */
@@ -54,9 +54,9 @@ MainWindow::MainWindow(QWidget *parent)
stackedWidget->addWidget(tsHome);
stackedWidget->addWidget(rdNum);
stackedWidget->addWidget(sm2Key);
+ stackedWidget->addWidget(sm2SignVerify);
stackedWidget->addWidget(sm2Encry);
stackedWidget->addWidget(sm3Hash);
- stackedWidget->addWidget(sm2SignVerify);
stackedWidget->addWidget(sm4Encry);
stackedWidget->addWidget(sm2Cer);
stackedWidget->addWidget(tlcpClient);
diff --git a/randnum.cpp b/randnum.cpp
index 64bc7d6..2fe70c0 100644
--- a/randnum.cpp
+++ b/randnum.cpp
@@ -6,9 +6,9 @@ RandNum::RandNum(QWidget *parent)
, ui(new Ui::RandNum)
{
ui->setupUi(this);
- /* 限制只能输入整数且范围为[1,256]*/
+ /* 限制只能输入整数且范围为[1,128 * 1024]*/
QIntValidator *aIntValidator = new QIntValidator;
- aIntValidator->setRange(1, 256);
+ aIntValidator->setRange(1, 131072);
ui->lineEditInput->setValidator(aIntValidator);
}
@@ -19,22 +19,32 @@ RandNum::~RandNum()
void RandNum::on_pushButtonGen_clicked()
{
- /* 获取用户输入 */
QString inputByte = this->ui->lineEditInput->text();
int randNumByte = inputByte.toInt();
- std::unique_ptr buf(new unsigned char[randNumByte]);
- /* 获取随机数输出栏 */
- QTextBrowser *outputNum = this->ui->textBrowserOutput;
- /* 调用随机数生成函数 */
- int ret = RAND_bytes(buf.get(), randNumByte);
+ size_t len = randNumByte * 2 + 1;
+ std::vector buf;
+ std::vector str;
+
+ buf.reserve(randNumByte);
+
+ int ret = RAND_bytes((unsigned char *) buf.data(), randNumByte);
+
if (ret == 0) {
- /* 生成失败弹窗 */
- getError();
- return;
+ printTSError();
} else {
- /* 生成成功将结果写到输出框 */
- std::shared_ptr outBuf(OPENSSL_buf2hexstr(buf.get(), randNumByte),
- [](char *outbuf) { OPENSSL_free(outbuf); });
- outputNum->setText(QString(outBuf.get()));
+ str.reserve(len);
+
+ if (OPENSSL_buf2hexstr_ex(str.data(),
+ len,
+ NULL,
+ (unsigned char *) buf.data(),
+ randNumByte,
+ '\0')
+ != 1)
+ return;
+
+ this->ui->textBrowserOutput->setText(QString::fromStdString(std::string(str.data(), len)));
}
+
+ return;
}
diff --git a/randnum.h b/randnum.h
index e7a68b8..fde77d8 100644
--- a/randnum.h
+++ b/randnum.h
@@ -3,6 +3,7 @@
#include "tserror.h"
#include
+#include
#include
#include
#include
diff --git a/randnum.ui b/randnum.ui
index 578d4da..88e51ce 100644
--- a/randnum.ui
+++ b/randnum.ui
@@ -6,123 +6,103 @@
0
0
- 463
- 312
+ 740
+ 531
Form
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
-
-
-
+
-
+
+
+ 生成随机数
+
+
+
+ -
+
-
+
0
0
-
-
- 12
-
+
+
+ 10
+ 10
+
+
+
+ 128
+
+
+
+ -
+
+
+ 字节
-
-
+
- Qt::Vertical
+ Qt::Horizontal
- 20
- 40
+ 40
+ 20
- -
-
+
-
+
- Qt::Vertical
+ Qt::Horizontal
- 20
- 40
+ 40
+ 20
- -
-
-
- 生成的十六进制随机数:
-
-
-
- -
-
-
- 输入您希望获取的随机数的字节数(1~256):
-
-
-
- -
-
-
-
- 12
-
+
-
+
+
+ Qt::Vertical
-
- 生成
+
+
+ 20
+ 40
+
-
+
- -
-
-
-
- 12
-
+
-
+
+
+
+ 0
+ 0
+
-
- 1
+
+ hex格式
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
diff --git a/sm2.cpp b/sm2.cpp
new file mode 100644
index 0000000..17418ef
--- /dev/null
+++ b/sm2.cpp
@@ -0,0 +1,197 @@
+#include
+#include
+
+EVP_PKEY *sm2_key_new_from_raw_pub(const std::string &pub)
+{
+ std::string hex;
+ std::vector buf;
+ OSSL_PARAM_BLD *keybld = NULL;
+ OSSL_PARAM *keyparams = NULL;
+ EVP_PKEY_CTX *keyctx = NULL;
+ EVP_PKEY *pkey = NULL;
+
+ hex = std::string("04") + pub;
+
+ keybld = OSSL_PARAM_BLD_new();
+ if (keybld == NULL)
+ goto end;
+
+ buf.reserve(hex.length() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, hex.c_str(), '\0') != 1)
+ goto end;
+
+ if (!OSSL_PARAM_BLD_push_utf8_string(keybld, OSSL_PKEY_PARAM_GROUP_NAME, "SM2", 3))
+ goto end;
+
+ if (!OSSL_PARAM_BLD_push_octet_string(keybld,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ buf.data(),
+ buf.capacity()))
+ goto end;
+
+ keyparams = OSSL_PARAM_BLD_to_param(keybld);
+ keyctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL);
+
+ if (keyctx == NULL || keyparams == NULL)
+ goto end;
+
+ if (EVP_PKEY_fromdata_init(keyctx) <= 0
+ || EVP_PKEY_fromdata(keyctx, &pkey, EVP_PKEY_PUBLIC_KEY, keyparams) <= 0)
+ goto end;
+end:
+ EVP_PKEY_CTX_free(keyctx);
+ OSSL_PARAM_free(keyparams);
+ OSSL_PARAM_BLD_free(keybld);
+ return pkey;
+}
+
+EVP_PKEY *sm2_key_new_from_raw_pub_and_priv(const std::string &pub, const std::string &priv)
+{
+ std::string hex;
+ std::vector buf;
+ OSSL_PARAM_BLD *keybld = NULL;
+ OSSL_PARAM *keyparams = NULL;
+ EVP_PKEY_CTX *keyctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ BIGNUM *bn = NULL;
+
+ keybld = OSSL_PARAM_BLD_new();
+ if (keybld == NULL)
+ goto end;
+
+ if (!OSSL_PARAM_BLD_push_utf8_string(keybld, OSSL_PKEY_PARAM_GROUP_NAME, "SM2", 3))
+ goto end;
+
+ buf.clear();
+ buf.reserve(priv.length() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, priv.c_str(), '\0') != 1)
+ goto end;
+
+ bn = BN_new();
+ if (bn == NULL)
+ goto end;
+
+ if (BN_bin2bn(buf.data(), buf.capacity(), bn) == NULL
+ || !OSSL_PARAM_BLD_push_BN(keybld, OSSL_PKEY_PARAM_PRIV_KEY, bn))
+ goto end;
+
+ hex = std::string("04") + pub;
+
+ buf.clear();
+ buf.reserve(hex.length() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, hex.c_str(), '\0') != 1)
+ goto end;
+
+ if (!OSSL_PARAM_BLD_push_octet_string(keybld,
+ OSSL_PKEY_PARAM_PUB_KEY,
+ buf.data(),
+ buf.capacity()))
+ goto end;
+
+ keyparams = OSSL_PARAM_BLD_to_param(keybld);
+ keyctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL);
+
+ if (keyctx == NULL || keyparams == NULL)
+ goto end;
+
+ if (EVP_PKEY_fromdata_init(keyctx) <= 0
+ || EVP_PKEY_fromdata(keyctx, &pkey, EVP_PKEY_KEYPAIR, keyparams) <= 0)
+ goto end;
+end:
+ BN_free(bn);
+ EVP_PKEY_CTX_free(keyctx);
+ OSSL_PARAM_free(keyparams);
+ OSSL_PARAM_BLD_free(keybld);
+ return pkey;
+}
+
+int sm2_key_get_priv_pem(const EVP_PKEY *pkey, std::string &pem)
+{
+ int ret = 0;
+ BIO *out = NULL;
+ long len;
+ char *buf = NULL;
+
+ out = BIO_new(BIO_s_mem());
+ if (out == NULL)
+ goto end;
+
+ if (!PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, NULL))
+ goto end;
+
+ len = BIO_get_mem_data(out, &buf);
+
+ pem = std::string(buf, len);
+
+ ret = 1;
+end:
+ BIO_free(out);
+ return ret;
+}
+
+int sm2_key_get_pub_pem(const EVP_PKEY *pkey, std::string &pem)
+{
+ int ret = 0;
+ BIO *out = NULL;
+ long len;
+ char *buf = NULL;
+
+ out = BIO_new(BIO_s_mem());
+ if (out == NULL)
+ goto end;
+
+ if (!PEM_write_bio_PUBKEY(out, pkey))
+ goto end;
+
+ len = BIO_get_mem_data(out, &buf);
+
+ pem = std::string(buf, len);
+
+ ret = 1;
+end:
+ BIO_free(out);
+ return ret;
+}
+
+int sm2_key_get_pub_hex(const EVP_PKEY *pkey, std::string &hex)
+{
+ BIGNUM *qx = NULL, *qy = NULL;
+ char *pubx = NULL, *puby = NULL;
+
+ if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &qx)
+ || !EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &qy))
+ return 0;
+
+ pubx = BN_bn2hex(qx);
+ puby = BN_bn2hex(qy);
+
+ hex = std::string(pubx) + std::string(puby);
+
+ BN_clear_free(qx);
+ BN_clear_free(qy);
+ OPENSSL_free(pubx);
+ OPENSSL_free(puby);
+
+ return 1;
+}
+
+int sm2_key_get_priv_hex(const EVP_PKEY *pkey, std::string &hex)
+{
+ BIGNUM *priv = NULL;
+ char *buf = NULL;
+
+ if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv))
+ return 0;
+
+ buf = BN_bn2hex(priv);
+
+ hex = std::string(buf);
+
+ OPENSSL_free(buf);
+ BN_clear_free(priv);
+
+ return 1;
+}
diff --git a/sm2.h b/sm2.h
new file mode 100644
index 0000000..ad532a6
--- /dev/null
+++ b/sm2.h
@@ -0,0 +1,20 @@
+#ifndef SM2_H
+#define SM2_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+int sm2_key_get_pub_pem(const EVP_PKEY *pkey, std::string &pem);
+int sm2_key_get_priv_pem(const EVP_PKEY *pkey, std::string &pem);
+int sm2_key_get_pub_hex(const EVP_PKEY *pkey, std::string &hex);
+int sm2_key_get_priv_hex(const EVP_PKEY *pkey, std::string &hex);
+EVP_PKEY *sm2_key_new_from_raw_pub(const std::string &pub);
+EVP_PKEY *sm2_key_new_from_raw_pub_and_priv(const std::string &pub, const std::string &priv);
+
+#endif // SM2_H
diff --git a/sm2cert.cpp b/sm2cert.cpp
index 2fbaaa2..92f2ae3 100644
--- a/sm2cert.cpp
+++ b/sm2cert.cpp
@@ -1,5 +1,6 @@
#include "sm2cert.h"
#include "ui_sm2cert.h"
+#include
Sm2Cert::Sm2Cert(QWidget *parent)
: QWidget(parent)
@@ -12,101 +13,280 @@ Sm2Cert::~Sm2Cert()
{
delete ui;
}
-std::shared_ptr Sm2Cert::genCert(int type,
- std::shared_ptr midCA,
- std::shared_ptr midcaPkey,
- QString CNname,
- QString days)
+
+static char *opt_getprog(void)
{
- /* 生成用户密钥 */
- 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);
- /* 证书相关设置 */
+ return (char *) "";
+}
+
+/*
+ * name is expected to be in the format /type0=value0/type1=value1/type2=...
+ * where + can be used instead of / to form multi-valued RDNs if canmulti
+ * and characters may be escaped by \
+ */
+static X509_NAME *parse_name(const char *cp, int chtype, int canmulti, const char *desc)
+{
+ int nextismulti = 0;
+ char *work;
+ X509_NAME *n;
+
+ if (*cp++ != '/') {
+ BIO_printf(bio_err,
+ "%s: %s name is expected to be in the format "
+ "/type0=value0/type1=value1/type2=... where characters may "
+ "be escaped by \\. This name is not in that format: '%s'\n",
+ opt_getprog(),
+ desc,
+ --cp);
+ return NULL;
+ }
+
+ n = X509_NAME_new();
+ if (n == NULL) {
+ BIO_printf(bio_err, "%s: Out of memory\n", opt_getprog());
+ return NULL;
+ }
+ work = OPENSSL_strdup(cp);
+ if (work == NULL) {
+ BIO_printf(bio_err, "%s: Error copying %s name input\n", opt_getprog(), desc);
+ goto err;
+ }
+
+ while (*cp != '\0') {
+ char *bp = work;
+ char *typestr = bp;
+ unsigned char *valstr;
+ int nid;
+ int ismulti = nextismulti;
+ nextismulti = 0;
+
+ /* Collect the type */
+ while (*cp != '\0' && *cp != '=')
+ *bp++ = *cp++;
+ *bp++ = '\0';
+ if (*cp == '\0') {
+ BIO_printf(bio_err,
+ "%s: Missing '=' after RDN type string '%s' in %s name string\n",
+ opt_getprog(),
+ typestr,
+ desc);
+ goto err;
+ }
+ ++cp;
+
+ /* Collect the value. */
+ valstr = (unsigned char *) bp;
+ for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) {
+ /* unescaped '+' symbol string signals further member of multiRDN */
+ if (canmulti && *cp == '+') {
+ nextismulti = 1;
+ break;
+ }
+ if (*cp == '\\' && *++cp == '\0') {
+ BIO_printf(bio_err,
+ "%s: Escape character at end of %s name string\n",
+ opt_getprog(),
+ desc);
+ goto err;
+ }
+ }
+ *bp++ = '\0';
+
+ /* If not at EOS (must be + or /), move forward. */
+ if (*cp != '\0')
+ ++cp;
+
+ /* Parse */
+ nid = OBJ_txt2nid(typestr);
+ if (nid == NID_undef) {
+ BIO_printf(bio_err,
+ "%s: Skipping unknown %s name attribute \"%s\"\n",
+ opt_getprog(),
+ desc,
+ typestr);
+ if (ismulti)
+ BIO_printf(bio_err,
+ "Hint: a '+' in a value string needs be escaped using '\\' else a new "
+ "member of a multi-valued RDN is expected\n");
+ continue;
+ }
+ if (*valstr == '\0') {
+ BIO_printf(bio_err,
+ "%s: No value provided for %s name attribute \"%s\", skipped\n",
+ opt_getprog(),
+ desc,
+ typestr);
+ continue;
+ }
+ if (!X509_NAME_add_entry_by_NID(
+ n, nid, chtype, valstr, strlen((char *) valstr), -1, ismulti ? -1 : 0)) {
+ ERR_print_errors(bio_err);
+ BIO_printf(bio_err,
+ "%s: Error adding %s name attribute \"/%s=%s\"\n",
+ opt_getprog(),
+ desc,
+ typestr,
+ valstr);
+ goto err;
+ }
+ }
+
+ OPENSSL_free(work);
+ return n;
+
+err:
+ X509_NAME_free(n);
+ OPENSSL_free(work);
+ return NULL;
+}
+
+static X509 *genCert(int type,
+ X509 *midCA,
+ EVP_PKEY *midcaPkey,
+ QString subj,
+ QString days,
+ char **key,
+ size_t *keylen)
+{
+ X509_NAME *name = NULL;
+ X509 *userCer = NULL;
std::string str;
+ long len;
+ BIO *out = NULL;
+ X509_EXTENSION *cert_ex = NULL;
+ X509_REQ *userReq = NULL;
+ ASN1_INTEGER *aserial = NULL;
+ const X509_NAME *rootCAname;
+ time_t curTime;
+ ASN1_TIME *rootBeforeTime = NULL;
+ ASN1_TIME *rootAfterTime = NULL;
+ EVP_PKEY *userKey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
+
+ if (userKey == NULL) {
+ printTSError();
+ return NULL;
+ }
+
+ out = BIO_new(BIO_s_mem());
+ if (out == NULL)
+ goto end;
+
+ if (!PEM_write_bio_PrivateKey(out, userKey, NULL, NULL, 0, NULL, NULL)) {
+ printTSError();
+ goto end;
+ }
+
+ len = BIO_get_mem_data(out, NULL);
+ if (len <= 0)
+ goto end;
+
+ *key = (char *) malloc(len);
+ if (*key == NULL)
+ goto end;
+
+ if (BIO_read(out, *key, len) != len)
+ goto end;
+
+ *keylen = len;
+
+ userReq = X509_REQ_new();
+ if (userReq == NULL)
+ goto end;
+
+ X509_REQ_set_pubkey(userReq, userKey);
+
+ if (!subj.isEmpty()) {
+ name = parse_name(subj.toStdString().c_str(), MBSTRING_ASC, 1, "subject");
+
+ if (!name) {
+ return NULL;
+ }
+
+ X509_REQ_set_subject_name(userReq, name);
+ }
+
+ if (!X509_REQ_set_version(userReq, X509_VERSION_3)
+ || !X509_REQ_sign(userReq, userKey, EVP_sm3()) || !X509_REQ_verify(userReq, userKey))
+ goto end;
+
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());
+ userCer = X509_new();
+ if (userCer == NULL)
+ goto end;
+
+ cert_ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, str.c_str());
+ if (cert_ex == NULL)
+ goto end;
+
+ if (!X509_add_ext(userCer, cert_ex, -1) || !X509_set_version(userCer, X509_VERSION_3)
+ || !X509_set_pubkey(userCer, userKey))
+ goto end;
- std::shared_ptr aserial(ASN1_INTEGER_new(), ASN1_INTEGER_free);
- ASN1_INTEGER_set(aserial.get(), 0);
- X509_set_serialNumber(userCer.get(), aserial.get());
+ aserial = ASN1_INTEGER_new();
- X509_set_subject_name(userCer.get(), userCAname.get());
+ if (!ASN1_INTEGER_set(aserial, 0))
+ goto end;
- const X509_NAME *rootCAname = X509_get_subject_name(midCA.get());
- X509_set_issuer_name(userCer.get(), rootCAname);
+ if (!X509_set_serialNumber(userCer, aserial) || !X509_set_subject_name(userCer, name))
+ goto end;
- 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());
+ rootCAname = X509_get_subject_name(midCA);
+ if (!X509_set_issuer_name(userCer, rootCAname))
+ goto end;
+
+ curTime = time(NULL);
+ rootBeforeTime = ASN1_TIME_new();
+ rootAfterTime = ASN1_TIME_adj(NULL, curTime, 0, days.toInt() * 60 * 60 * 24);
+
+ if (!ASN1_TIME_set(rootBeforeTime, curTime) || !X509_set_notBefore(userCer, rootBeforeTime)
+ || !X509_set_notAfter(userCer, rootAfterTime))
+ goto end;
+
+ if (!X509_sign(userCer, midcaPkey, EVP_sm3()))
+ goto end;
+
+end:
+ ASN1_TIME_free(rootAfterTime);
+ ASN1_TIME_free(rootBeforeTime);
+ ASN1_INTEGER_free(aserial);
+ X509_EXTENSION_free(cert_ex);
+ X509_REQ_free(userReq);
+ BIO_free(out);
+ EVP_PKEY_free(userKey);
return userCer;
}
void Sm2Cert::on_pushButtonGen_clicked()
{
- /* 获取用户输入的通用名称 */
- QString CN = this->ui->lineEditCN->text();
- if (CN.isEmpty()) {
+ QString subj = this->ui->lineEditSubj->text();
+ QString days = this->ui->lineEditDays->text();
+ QFile fsubca(":/certs/subca.pem");
+ QFile fpkey(":/certs/subca.key");
+ X509 *userSignCer = NULL, *userEncryptCer = NULL;
+ char *signKey = NULL, *encKey = NULL;
+ size_t signKeyLen, encKeyLen;
+ QString subcaQstr, pkeyQstr;
+ X509 *subca = NULL;
+ EVP_PKEY *pkey = NULL;
+ long len;
+ char *buf = NULL;
+ BIO *out = NULL;
+
+ if (subj.isEmpty()) {
QMessageBox::warning(NULL,
"warning",
- QString("请输入通用名称!"),
+ QString("请输入主体名称!"),
QMessageBox::Close,
QMessageBox::Close);
return;
}
- /* 获取用户输入的有效期 */
- QString days = this->ui->lineEditDays->text();
+
if (days.isEmpty()) {
QMessageBox::warning(NULL,
"warning",
@@ -115,8 +295,7 @@ void Sm2Cert::on_pushButtonGen_clicked()
QMessageBox::Close);
return;
}
- /* 读取中间CA证书 */
- QFile fsubca(":/certs/subca.pem");
+
if (!fsubca.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::warning(NULL,
"warning",
@@ -125,45 +304,96 @@ void Sm2Cert::on_pushButtonGen_clicked()
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打开失败!"),
+ QString("subca.key打开失败!"),
QMessageBox::Close,
QMessageBox::Close);
return;
}
+ QTextStream subcaInput(&fsubca);
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);
+
+ subcaQstr = subcaInput.readAll();
+ pkeyQstr = pkeyInput.readAll();
+
+ out = BIO_new(BIO_s_mem());
+ if (out == NULL)
+ goto end;
+
+ if (BIO_write(out, subcaQstr.toStdString().c_str(), subcaQstr.size()) != subcaQstr.size())
+ goto end;
+
+ subca = PEM_read_bio_X509(out, NULL, NULL, NULL);
+ if (subca == NULL) {
+ this->ui->textBrowserSignKey->setText(subcaQstr);
+ printTSError();
+ goto end;
+ }
+
+ fsubca.close();
+ BIO_reset(out);
+
+ if (BIO_write(out, pkeyQstr.toStdString().c_str(), pkeyQstr.size()) != pkeyQstr.size())
+ goto end;
+
+ pkey = PEM_read_bio_PrivateKey(out, NULL, NULL, NULL);
+ if (pkey == NULL) {
+ printTSError();
+ goto end;
+ }
+
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));
+ userSignCer = genCert(1, subca, pkey, subj, days, &signKey, &signKeyLen);
+ if (userSignCer == NULL) {
+ printTSError();
+ goto end;
+ }
+
+ userEncryptCer = genCert(0, subca, pkey, subj, days, &encKey, &encKeyLen);
+ if (userEncryptCer == NULL) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->textBrowserSignKey->setText(QString::fromStdString(std::string(signKey, signKeyLen)));
+ this->ui->textBrowserEncryKey->setText(QString::fromStdString(std::string(encKey, encKeyLen)));
+
+ BIO_reset(out);
+
+ if (!PEM_write_bio_X509(out, userSignCer)) {
+ printTSError();
+ goto end;
+ }
+
+ len = BIO_get_mem_data(out, &buf);
+ if (len <= 0)
+ goto end;
+
+ this->ui->textBrowserSignOutput->setPlainText(QString::fromStdString(std::string(buf, len)));
+
+ BIO_reset(out);
+
+ if (!PEM_write_bio_X509(out, userEncryptCer)) {
+ printTSError();
+ goto end;
+ }
+
+ len = BIO_get_mem_data(out, &buf);
+ if (len <= 0)
+ goto end;
+
+ this->ui->textBrowserEncryptOutput->setPlainText(QString::fromStdString(std::string(buf, len)));
+
+end:
+ EVP_PKEY_free(pkey);
+ X509_free(subca);
+ BIO_free(out);
+ free(signKey);
+ free(encKey);
+ X509_free(userSignCer);
+ X509_free(userEncryptCer);
}
diff --git a/sm2cert.h b/sm2cert.h
index 1628fd5..7391376 100644
--- a/sm2cert.h
+++ b/sm2cert.h
@@ -31,12 +31,6 @@ private slots:
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
index b943e6f..45f537d 100644
--- a/sm2cert.ui
+++ b/sm2cert.ui
@@ -7,73 +7,58 @@
0
0
400
- 300
+ 314
Form
- -
-
+
-
+
- 12
+ 10
-
- 签名证书&密钥:
-
- -
-
+
-
+
- 12
+ 10
-
- 365
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
- 12
-
-
-
-
-
-
- tongsuo
-
-
- 一般为域名
+
-
+
+
+ 0
-
+ -
+
+
+
+ 12
+
+
+
+
+
+
+ /C=AB/ST=CD/L=EF/O=GH/OU=IJ/CN=test
+
+
+ 一般为域名
+
+
+
+
- -
-
+
-
+
10
@@ -81,32 +66,29 @@
- -
-
+
-
+
12
- 生成证书
+ 加密证书&私钥:
- -
-
+
-
+
- 12
+ 10
-
- 通用名称:
-
- -
-
+
-
+
Qt::Vertical
@@ -118,111 +100,80 @@
- -
-
+
-
+
12
- 私钥/请求:
+ 有效天数:
- -
-
+
-
+
12
- 有效天数:
+ 签名证书&私钥:
- -
-
-
- 0
+
-
+
+
+ Qt::Vertical
-
-
-
-
-
- 12
-
-
-
- 自动生成
-
-
-
- -
-
-
-
- 12
-
-
-
- 手动生成
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
-
- 10
-
+
+
+ 20
+ 40
+
-
+
- -
-
+
-
+
12
- 加密证书&密钥:
+ 365
+
+
+
- -
-
+
-
+
- 10
+ 12
+
+ 主体名称:
+
- -
-
+
-
+
- 10
+ 12
+
+ 生成证书
+
diff --git a/sm2encrypt.cpp b/sm2encrypt.cpp
index 3881bfd..2caa4cb 100644
--- a/sm2encrypt.cpp
+++ b/sm2encrypt.cpp
@@ -1,4 +1,5 @@
#include "sm2encrypt.h"
+#include "sm2.h"
#include "ui_sm2encrypt.h"
Sm2Encrypt::Sm2Encrypt(QWidget *parent)
@@ -15,94 +16,166 @@ Sm2Encrypt::~Sm2Encrypt()
void Sm2Encrypt::on_pushButtonEncrypt_clicked()
{
- /* 选定椭圆曲线组 */
- std::shared_ptr group(EC_GROUP_new_by_curve_name(NID_sm2), EC_GROUP_free);
- /* 密钥上下文生成 */
- std::shared_ptr eckey(EC_KEY_new(), EC_KEY_free);
- /* 设定密钥的曲线组 */
- EC_KEY_set_group(eckey.get(), group.get());
- /* 获取用户输入的公钥 */
- QString pubQstrInput = this->ui->lineEditPub->text();
- /* 将16进制字符串公钥转为EC_POINT,并设置到EC_KEY */
- const EC_POINT *pubPoint
- = EC_POINT_hex2point(group.get(), pubQstrInput.toStdString().c_str(), NULL, NULL);
- EC_KEY_set_public_key(eckey.get(), pubPoint);
- /* 将EC_KEY设置到EVP_PKEY */
- std::shared_ptr pKey(EVP_PKEY_new(), EVP_PKEY_free);
- EVP_PKEY_set1_EC_KEY(pKey.get(), eckey.get());
- /* 生成加密上下文 */
- std::shared_ptr pkCtx(EVP_PKEY_CTX_new(pKey.get(), NULL), EVP_PKEY_CTX_free);
- /* 加密初始化 */
- if (EVP_PKEY_encrypt_init(pkCtx.get()) <= 0) {
- getError();
+ QString input = this->ui->textEditPlain->toPlainText();
+ QString pubQstrInput = this->ui->plainTextEditPub->toPlainText();
+ EVP_PKEY_CTX *encctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ size_t outlen;
+ std::vector buf;
+ std::vector str;
+
+ if (pubQstrInput.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入公钥!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
return;
}
- /* 获取输入明文 */
- QString plainTextQstr = this->ui->plainTextEditInput->toPlainText();
- /* 获取加密密文长度 */
- size_t cipherTextLen = 0;
- int res = EVP_PKEY_encrypt(pkCtx.get(),
- NULL,
- &cipherTextLen,
- (const unsigned char *) plainTextQstr.toStdString().c_str(),
- plainTextQstr.size());
- if (res != 1) {
- getError();
+
+ if (input.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入明文!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
return;
}
- /* 加密生成密文 */
- std::shared_ptr cipherText(new unsigned char[cipherTextLen]);
- res = EVP_PKEY_encrypt(pkCtx.get(),
- cipherText.get(),
- &cipherTextLen,
- (const unsigned char *) plainTextQstr.toStdString().c_str(),
- plainTextQstr.size());
- if (res != 1) {
- getError();
- return;
+
+ pkey = sm2_key_new_from_raw_pub(pubQstrInput.toStdString());
+ if (pkey == NULL) {
+ printTSError();
+ goto end;
+ }
+
+ encctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+ if (encctx == NULL)
+ goto end;
+
+ if (EVP_PKEY_encrypt_init(encctx) <= 0
+ || EVP_PKEY_encrypt(encctx,
+ NULL,
+ &outlen,
+ (const unsigned char *) input.toStdString().c_str(),
+ input.toStdString().length())
+ <= 0)
+ goto end;
+
+ buf.clear();
+ buf.reserve(outlen);
+
+ if (EVP_PKEY_encrypt(encctx,
+ buf.data(),
+ &outlen,
+ (const unsigned char *) input.toStdString().c_str(),
+ input.toStdString().length())
+ <= 0)
+ goto end;
+
+ str.reserve(outlen * 2 + 1);
+ if (OPENSSL_buf2hexstr_ex(str.data(), str.capacity(), NULL, buf.data(), outlen, '\0') != 1) {
+ printTSError();
+ goto end;
}
- /* 以16进制字符串的形式显示在输出框 */
- std::shared_ptr outBuf(OPENSSL_buf2hexstr(cipherText.get(), cipherTextLen),
- [](char *outbuf) { OPENSSL_free(outbuf); });
- this->ui->plainTextEditOutput->setPlainText(QString(outBuf.get()));
+
+ this->ui->textEditCipher->setText(QString::fromStdString(std::string(str.data(), outlen * 2)));
+
+end:
+ EVP_PKEY_free(pkey);
}
void Sm2Encrypt::on_pushButtonDecrypt_clicked()
{
- /* 选定椭圆曲线组 */
- std::shared_ptr group(EC_GROUP_new_by_curve_name(NID_sm2), EC_GROUP_free);
- /* 密钥上下文生成 */
- std::shared_ptr ecKey(EC_KEY_new(), EC_KEY_free);
- /* 设定密钥的曲线组 */
- EC_KEY_set_group(ecKey.get(), group.get());
- /* 获取用户输入的私钥 */
- QString priQstrInput = this->ui->lineEditPri->text();
- /* 将16进制字符串私钥转为BIGNUM,并设置到EC_KEY */
- BIGNUM *priBn = BN_new();
- BN_hex2bn(&priBn, priQstrInput.toStdString().c_str());
- EC_KEY_set_private_key(ecKey.get(), priBn);
- BN_free(priBn);
- /* 将EC_KEY设置到EVP_PKEY */
- std::shared_ptr pKey(EVP_PKEY_new(), EVP_PKEY_free);
- EVP_PKEY_set1_EC_KEY(pKey.get(), ecKey.get());
- /* 生成解密上下文 */
- std::shared_ptr pkCtx(EVP_PKEY_CTX_new(pKey.get(), NULL), EVP_PKEY_CTX_free);
- /* 解密初始化 */
- if (EVP_PKEY_decrypt_init(pkCtx.get()) <= 0) {
- getError();
+ QString input = this->ui->textEditCipher->toPlainText();
+ QString pubQstrInput = this->ui->plainTextEditPub->toPlainText();
+ QString privQstrInput = this->ui->plainTextEditPriv->toPlainText();
+ EVP_PKEY_CTX *encctx = NULL;
+ EVP_PKEY *pkey = NULL;
+ size_t outlen;
+ std::vector buf;
+ std::vector str;
+
+ if (pubQstrInput.isEmpty() || privQstrInput.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入公钥和私钥!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+
+ if (input.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入密文!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
return;
}
- /* 获取输入密文 */
- QString cipherTextQstr = this->ui->plainTextEditInput->toPlainText();
- long inBufLen = 0;
- const unsigned char *inBuf = OPENSSL_hexstr2buf(cipherTextQstr.toStdString().c_str(), &inBufLen);
- /* 获取解密明文长度 */
- size_t plainTextLen = 0;
- EVP_PKEY_decrypt(pkCtx.get(), NULL, &plainTextLen, inBuf, inBufLen);
- /* 解密 生成明文 */
- std::shared_ptr plainText(new unsigned char[plainTextLen]);
- EVP_PKEY_decrypt(pkCtx.get(), plainText.get(), &plainTextLen, inBuf, inBufLen);
- /* 将明文内容显示到输出框 */
- std::string outStr((const char *) plainText.get(), plainTextLen);
- this->ui->plainTextEditOutput->setPlainText(QString::fromStdString(outStr));
+
+ pkey = sm2_key_new_from_raw_pub_and_priv(pubQstrInput.toStdString(),
+ privQstrInput.toStdString());
+ if (pkey == NULL) {
+ printTSError();
+ goto end;
+ }
+
+ encctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
+ if (encctx == NULL)
+ goto end;
+
+ buf.clear();
+ buf.reserve(input.length() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, input.toStdString().c_str(), '\0')
+ != 1) {
+ printTSError();
+ goto end;
+ }
+
+ if (EVP_PKEY_decrypt_init(encctx) <= 0
+ || EVP_PKEY_decrypt(encctx, NULL, &outlen, buf.data(), buf.capacity()) <= 0)
+ goto end;
+
+ str.clear();
+ str.reserve(outlen);
+
+ if (EVP_PKEY_decrypt(encctx, (unsigned char *) str.data(), &outlen, buf.data(), buf.capacity())
+ <= 0)
+ goto end;
+
+ this->ui->textEditPlain->setText(QString::fromStdString(std::string(str.data(), outlen)));
+
+end:
+ EVP_PKEY_free(pkey);
+}
+
+void Sm2Encrypt::on_pushButtonGen_clicked()
+{
+ EVP_PKEY *pkey = NULL;
+ std::string hex;
+
+ pkey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
+ if (pkey == NULL) {
+ printTSError();
+ goto end;
+ }
+
+ if (!sm2_key_get_pub_hex(pkey, hex)) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->plainTextEditPub->setPlainText(QString::fromStdString(hex));
+
+ if (!sm2_key_get_priv_hex(pkey, hex)) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->plainTextEditPriv->setPlainText(QString::fromStdString(hex));
+
+end:
+ EVP_PKEY_free(pkey);
+ return;
}
diff --git a/sm2encrypt.h b/sm2encrypt.h
index c36957b..b0da76a 100644
--- a/sm2encrypt.h
+++ b/sm2encrypt.h
@@ -3,9 +3,11 @@
#include "tserror.h"
#include
+#include
#include
#include
#include
+#include
#include
#include
#include
@@ -28,6 +30,8 @@ private slots:
void on_pushButtonDecrypt_clicked();
+ void on_pushButtonGen_clicked();
+
private:
Ui::Sm2Encrypt *ui;
};
diff --git a/sm2encrypt.ui b/sm2encrypt.ui
index 17dd21a..aa26ae4 100644
--- a/sm2encrypt.ui
+++ b/sm2encrypt.ui
@@ -6,8 +6,8 @@
0
0
- 400
- 300
+ 436
+ 412
@@ -15,148 +15,82 @@
-
-
-
-
-
-
-
- 12
-
-
-
- 公钥
+
+
-
+
+
+ hex格式
-
-
-
- 12
-
-
私钥
- -
-
-
-
- 12
-
-
+
-
+
+
+ -
+
- 04C370A09551DCC0321F0927A44B1A4D6ED5C39C06B336AA8FDE3389AAE830CC518C54BE3D1EAAAF45E8A34F41BCEA429EAD6B3271189B967CD248FF566F9F5161
+ 密文
- -
-
-
-
- 12
-
-
+
-
+
- 54519B9E1FD670D429B4D8EDE7A9A0322C5A6D3C3E9446903EFA5FE2C6B49EC2
+ 明文
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Qt::Vertical
+
-
+
+
+ hex格式
-
-
- 20
- 40
-
-
-
+
-
-
- -
-
-
-
-
-
-
- 12
-
-
+
-
+
- 加密
+ 公钥
-
-
-
-
- 12
-
+
+
+ hex格式
+
+
+ -
+
- 解密
+ 公钥加密
- -
-
-
-
- 12
-
-
-
- QPlainTextEdit::WidgetWidth
+
-
+
+
+ 私钥解密
- -
-
-
-
- 12
-
-
-
- hello Tongsuo
+
-
+
+
+ 生成密钥对
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
diff --git a/sm2key.cpp b/sm2key.cpp
index 885fafc..20c8c61 100644
--- a/sm2key.cpp
+++ b/sm2key.cpp
@@ -1,4 +1,5 @@
#include "sm2key.h"
+#include "sm2.h"
#include "ui_sm2key.h"
Sm2Key::Sm2Key(QWidget *parent)
@@ -15,33 +16,44 @@ Sm2Key::~Sm2Key()
void Sm2Key::on_pushButtonGen_clicked()
{
- /* 选定椭圆曲线组 */
- std::shared_ptr group(EC_GROUP_new_by_curve_name(NID_sm2), EC_GROUP_free);
- if (!group) {
- getError();
- return;
+ EVP_PKEY *pkey = NULL;
+ std::string pem, hex;
+
+ pkey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
+ if (pkey == NULL) {
+ printTSError();
+ goto end;
}
- /* 密钥上下文生成 */
- std::shared_ptr key(EC_KEY_new(), EC_KEY_free);
- /* 设定密钥的曲线组 */
- EC_KEY_set_group(key.get(), group.get());
- /* 生成EC_KEY */
- int res = EC_KEY_generate_key(key.get());
- if (res != 1) {
- getError();
- return;
+
+ if (!sm2_key_get_priv_pem(pkey, pem)) {
+ printTSError();
+ goto end;
}
- /* 取公钥并转换为十六进制字符串 */
- const EC_POINT *pubPoint = EC_KEY_get0_public_key(key.get());
- std::shared_ptr pubHexStr(EC_POINT_point2hex(group.get(),
- pubPoint,
- POINT_CONVERSION_UNCOMPRESSED,
- NULL),
- [](char *pub) { OPENSSL_free(pub); });
- /* 取私钥并转换为十六进制字符串 */
- const BIGNUM *priBn = EC_KEY_get0_private_key(key.get());
- std::shared_ptr priHexStr(BN_bn2hex(priBn), [](char *pri) { OPENSSL_free(pri); });
- /* 在浏览框中显示公钥和私钥 */
- this->ui->textBrowserPrikey->setText(QString(priHexStr.get()));
- this->ui->textBrowserPubkey->setText(QString(pubHexStr.get()));
+
+ this->ui->textBrowserPrivPem->setText(QString::fromStdString(pem));
+
+ if (!sm2_key_get_pub_pem(pkey, pem)) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->textBrowserPubPem->setText(QString::fromStdString(pem));
+
+ if (!sm2_key_get_pub_hex(pkey, hex)) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->textBrowserPubkey->setText(QString::fromStdString(hex));
+
+ if (!sm2_key_get_priv_hex(pkey, hex)) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->textBrowserPrivkey->setText(QString::fromStdString(hex));
+
+end:
+ EVP_PKEY_free(pkey);
+ return;
}
diff --git a/sm2key.h b/sm2key.h
index c7d4509..35ec84e 100644
--- a/sm2key.h
+++ b/sm2key.h
@@ -1,11 +1,14 @@
#ifndef SM2KEY_H
#define SM2KEY_H
-#include "openssl/ec.h"
#include "tserror.h"
#include
+#include
+#include
#include
#include
+#include
+#include
#include
#include
#include
diff --git a/sm2key.ui b/sm2key.ui
index 468a21a..968d6e0 100644
--- a/sm2key.ui
+++ b/sm2key.ui
@@ -6,8 +6,8 @@
0
0
- 414
- 312
+ 573
+ 503
@@ -15,203 +15,56 @@
-
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
+
+
-
+
- -
-
-
-
- 微软雅黑
- 14
-
-
-
- 生成
-
-
+
-
+
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
+
-
-
-
- 16
-
-
- 私钥:
+ SM2私钥(PEM)
- -
-
-
- true
-
-
-
- 0
- 0
-
-
-
-
- 0
- 4
-
-
-
-
- 200
- 200
-
-
-
-
- 12
-
+
-
+
+
+ SM2私钥
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
+
-
-
-
- 16
-
-
- 公钥:
+ SM2公钥(x||y)
- -
-
-
-
- 0
- 0
-
+
-
+
+
+ 生成密钥对
-
-
- 12
-
+
+
+ -
+
+
+ -
+
+
+ SM2公钥(PEM)
+ -
+
+
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
diff --git a/sm2signverify.cpp b/sm2signverify.cpp
index 03f31ea..e637a7d 100644
--- a/sm2signverify.cpp
+++ b/sm2signverify.cpp
@@ -1,4 +1,5 @@
#include "sm2signverify.h"
+#include "sm2.h"
#include "ui_sm2signverify.h"
Sm2SignVerify::Sm2SignVerify(QWidget *parent)
@@ -15,155 +16,176 @@ Sm2SignVerify::~Sm2SignVerify()
void Sm2SignVerify::on_pushButtonGenKey_clicked()
{
- /* 选定椭圆曲线组 */
- std::shared_ptr group(EC_GROUP_new_by_curve_name(NID_sm2), EC_GROUP_free);
- if (!group) {
- getError();
- return;
+ EVP_PKEY *pkey = NULL;
+ std::string hex;
+
+ pkey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
+ if (pkey == NULL) {
+ printTSError();
+ goto end;
}
- /* 密钥上下文生成 */
- std::shared_ptr key(EC_KEY_new(), EC_KEY_free);
- /* 设定密钥的曲线组 */
- EC_KEY_set_group(key.get(), group.get());
- /* 生成EC_KEY */
- int res = EC_KEY_generate_key(key.get());
- if (res != 1) {
- getError();
- return;
+
+ if (!sm2_key_get_pub_hex(pkey, hex)) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->plainTextEditPubKey->setPlainText(QString::fromStdString(hex));
+
+ if (!sm2_key_get_priv_hex(pkey, hex)) {
+ printTSError();
+ goto end;
}
- /* 取公钥并转换为十六进制字符串 */
- const EC_POINT *pubPoint = EC_KEY_get0_public_key(key.get());
- std::shared_ptr pubHexStr(EC_POINT_point2hex(group.get(),
- pubPoint,
- POINT_CONVERSION_UNCOMPRESSED,
- NULL),
- [](char *pub) { OPENSSL_free(pub); });
- /* 取私钥并转换为十六进制字符串 */
- const BIGNUM *priBn = EC_KEY_get0_private_key(key.get());
- std::shared_ptr priHexStr(BN_bn2hex(priBn), [](char *pri) { OPENSSL_free(pri); });
- /* 在浏览框中显示公钥和私钥 */
- this->ui->lineEditPriKey->setText(QString(priHexStr.get()));
- this->ui->plainTextEditPubKey->setPlainText(QString(pubHexStr.get()));
+
+ this->ui->lineEditPriKey->setText(QString::fromStdString(hex));
+
+end:
+ EVP_PKEY_free(pkey);
+ return;
}
void Sm2SignVerify::on_pushButtonSign_clicked()
{
/* 获取私钥 */
+ QString pubQstr = this->ui->plainTextEditPubKey->toPlainText();
QString priQstr = this->ui->lineEditPriKey->text();
+ QString inputQstr = this->ui->textEditData->toPlainText();
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ size_t siglen = 0;
+ std::vector sig;
+ std::vector str;
+
if (priQstr.isEmpty()) {
QMessageBox::warning(NULL,
"warning",
- QString("请输入或者生成私钥!"),
+ QString("请输入或生成私钥!"),
QMessageBox::Close,
QMessageBox::Close);
return;
}
- /* 获取待签名数据 */
- QString inputQstr = this->ui->lineEditInput->text();
+
if (inputQstr.isEmpty()) {
QMessageBox::warning(NULL,
"warning",
- QString("请输入待签数据!"),
+ QString("请输入待签名数据!"),
QMessageBox::Close,
QMessageBox::Close);
return;
}
- /* 选定椭圆曲线组 */
- std::shared_ptr group(EC_GROUP_new_by_curve_name(NID_sm2), EC_GROUP_free);
- /* EC密钥生成 */
- std::shared_ptr ecKey(EC_KEY_new(), EC_KEY_free);
- /* 设定密钥的曲线组 */
- EC_KEY_set_group(ecKey.get(), group.get());
- /* 将16进制字符串私钥转为BIGNUM,并设置到EC_KEY */
- BIGNUM *priBn = BN_new();
- BN_hex2bn(&priBn, priQstr.toStdString().c_str());
- EC_KEY_set_private_key(ecKey.get(), priBn);
- BN_free(priBn);
- /* 将16进制字符串公钥转为ECPOINT,并设置到EC_KEY */
- QString pubQstrInput = this->ui->plainTextEditPubKey->toPlainText();
- const EC_POINT *pubPoint
- = EC_POINT_hex2point(group.get(), pubQstrInput.toStdString().c_str(), NULL, NULL);
- EC_KEY_set_public_key(ecKey.get(), pubPoint);
- /* 将EC_KEY设置到EVP_PKEY */
- std::shared_ptr pKey(EVP_PKEY_new(), EVP_PKEY_free);
- EVP_PKEY_set1_EC_KEY(pKey.get(), ecKey.get());
- /* 签名上下文及初始化 */
- size_t siglen = 0;
- std::shared_ptr mctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
- if (!EVP_DigestSignInit(mctx.get(), NULL, EVP_sm3(), NULL, pKey.get())
- || !EVP_DigestSign(mctx.get(),
+ pkey = sm2_key_new_from_raw_pub_and_priv(pubQstr.toStdString(), priQstr.toStdString());
+ if (pkey == NULL) {
+ printTSError();
+ return;
+ }
+
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL)
+ goto end;
+
+ if (!EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, pkey)
+ || !EVP_DigestSign(mctx,
NULL,
&siglen,
(unsigned char *) inputQstr.toStdString().c_str(),
inputQstr.size())) {
- getError();
- return;
+ printTSError();
+ goto end;
}
- /* 签名 */
- std::shared_ptr sig((unsigned char *) OPENSSL_malloc(siglen),
- [](unsigned char *buf) { OPENSSL_free(buf); });
- int ret = EVP_DigestSign(mctx.get(),
- sig.get(),
- &siglen,
- (unsigned char *) inputQstr.toStdString().c_str(),
- inputQstr.size());
- if (ret != 1) {
- getError();
- return;
+
+ sig.reserve(siglen);
+
+ if (EVP_DigestSign(mctx,
+ sig.data(),
+ &siglen,
+ (unsigned char *) inputQstr.toStdString().c_str(),
+ inputQstr.size())
+ != 1) {
+ printTSError();
+ goto end;
}
- /* 显示十六进制字符串到输出框 */
- std::shared_ptr out(OPENSSL_buf2hexstr(sig.get(), siglen),
- [](char *buf) { OPENSSL_free(buf); });
- this->ui->plainTextEditOutput->setPlainText(QString(out.get()));
+
+ str.reserve(siglen * 2 + 1);
+
+ if (OPENSSL_buf2hexstr_ex(str.data(), str.capacity(), NULL, sig.data(), siglen, '\0') != 1) {
+ printTSError();
+ goto end;
+ }
+
+ this->ui->plainTextEditSign->setPlainText(
+ QString::fromStdString(std::string(str.data(), str.capacity())));
+end:
+ EVP_MD_CTX_free(mctx);
+ EVP_PKEY_free(pkey);
+ return;
}
void Sm2SignVerify::on_pushButtonVerify_clicked()
{
- /* 获取原文 */
- QString inputQstr = this->ui->lineEditInput->text();
- /* 获取签名 */
- QString signQstr = this->ui->plainTextEditOutput->toPlainText();
- long siglen = signQstr.size();
- const unsigned char *sig = OPENSSL_hexstr2buf(signQstr.toStdString().c_str(), &siglen);
- /* 选定椭圆曲线组 */
- std::shared_ptr group(EC_GROUP_new_by_curve_name(NID_sm2), EC_GROUP_free);
- /* 密钥上下文生成 */
- std::shared_ptr eckey(EC_KEY_new(), EC_KEY_free);
- /* 设定密钥的曲线组 */
- EC_KEY_set_group(eckey.get(), group.get());
- /* 获取用户输入的公钥 */
QString pubQstrInput = this->ui->plainTextEditPubKey->toPlainText();
- /* 将16进制字符串公钥转为EC_POINT,并设置到EC_KEY */
- const EC_POINT *pubPoint
- = EC_POINT_hex2point(group.get(), pubQstrInput.toStdString().c_str(), NULL, NULL);
- EC_KEY_set_public_key(eckey.get(), pubPoint);
- /* 将EC_KEY设置到EVP_PKEY */
- std::shared_ptr pKey(EVP_PKEY_new(), EVP_PKEY_free);
- EVP_PKEY_set1_EC_KEY(pKey.get(), eckey.get());
- /* 验签上下文及初始化 */
- std::shared_ptr mctx(EVP_MD_CTX_new(), EVP_MD_CTX_free);
- if (!EVP_DigestVerifyInit(mctx.get(), NULL, EVP_sm3(), NULL, pKey.get())) {
- getError();
+ QString inputQstr = this->ui->textEditData->toPlainText();
+ QString signQstr = this->ui->plainTextEditSign->toPlainText();
+ std::vector sig;
+ EVP_PKEY *pkey = NULL;
+ EVP_MD_CTX *mctx = NULL;
+ int ret;
+
+ if (pubQstrInput.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入公钥!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
return;
}
- /* 验签 */
- int ret = EVP_DigestVerify(mctx.get(),
- sig,
- siglen,
- (unsigned char *) inputQstr.toStdString().c_str(),
- inputQstr.size());
- if (ret == 1) {
- /* 验签成功 */
+
+ if (signQstr.isEmpty()) {
QMessageBox::warning(NULL,
"warning",
- QString("验签成功!"),
+ QString("请输入签名!"),
QMessageBox::Close,
QMessageBox::Close);
+ return;
+ }
+
+ sig.reserve(signQstr.size() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(sig.data(), sig.capacity(), NULL, signQstr.toStdString().c_str(), '\0')
+ != 1) {
+ printTSError();
+ goto end;
+ }
+
+ pkey = sm2_key_new_from_raw_pub(pubQstrInput.toStdString());
+ if (pkey == NULL) {
+ printTSError();
+ goto end;
+ }
+
+ mctx = EVP_MD_CTX_new();
+ if (mctx == NULL)
+ goto end;
+
+ if (!EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey)) {
+ printTSError();
+ goto end;
+ }
+ /* 验签 */
+ ret = EVP_DigestVerify(mctx,
+ sig.data(),
+ sig.capacity(),
+ (unsigned char *) inputQstr.toStdString().c_str(),
+ inputQstr.size());
+ if (ret == 1) {
+ QMessageBox::information(NULL,
+ "success",
+ QString("验签成功!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
} else if (ret == 0) {
- /* 验签失败 */
QMessageBox::warning(NULL,
- "warning",
+ "failed",
QString("验签失败!"),
QMessageBox::Close,
QMessageBox::Close);
@@ -171,4 +193,8 @@ void Sm2SignVerify::on_pushButtonVerify_clicked()
getError();
return;
}
+end:
+ EVP_MD_CTX_free(mctx);
+ EVP_PKEY_free(pkey);
+ return;
}
diff --git a/sm2signverify.ui b/sm2signverify.ui
index 0f711f8..1f812e4 100644
--- a/sm2signverify.ui
+++ b/sm2signverify.ui
@@ -7,148 +7,134 @@
0
0
390
- 302
+ 318
Form
-
- -
-
-
-
- 12
-
-
-
- 公钥:
-
-
-
- -
-
-
-
- 12
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
-
- 12
-
-
-
- 验证签名
-
-
-
- -
-
-
-
- 12
-
-
-
- 私钥:
-
-
-
- -
-
-
-
- 12
-
-
-
- 生成签名
-
-
-
- -
-
-
-
- 12
-
-
-
- 签名:
-
-
-
- -
-
-
-
- 12
-
-
-
- hello Tongsuo
-
-
-
- -
-
-
-
- 12
-
-
-
-
- -
-
-
-
- 12
-
-
-
- 待签/待验数据:
-
-
-
- -
-
-
-
- 12
-
-
-
-
- -
-
-
-
- 12
-
-
-
- 生成密钥对
-
-
+
+
-
+
+
-
+
+
+
+ 12
+
+
+
+ 待签名/验签数据:
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 生成密钥对
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 私钥:
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ hex格式
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 公钥:
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ hex格式
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 签名:
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 生成签名
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 验证签名
+
+
+
+ -
+
+
+ -
+
+
+ hex格式
+
+
+
+
diff --git a/sm3hash.cpp b/sm3hash.cpp
index 9f9255e..cef2f7b 100644
--- a/sm3hash.cpp
+++ b/sm3hash.cpp
@@ -15,18 +15,32 @@ Sm3Hash::~Sm3Hash()
void Sm3Hash::on_pushButtonGen_clicked()
{
- /* 获取用户输入 */
QString input = this->ui->plainTextEditInput->toPlainText();
- /* 进行哈希生成摘要 */
unsigned char md[32] = {};
+ unsigned char hex[65];
size_t mdlen = 0;
+
+ if (input.isEmpty()) {
+ if (input.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入数据!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+ }
+
if (!EVP_Q_digest(NULL, "SM3", NULL, input.toStdString().c_str(), input.size(), md, &mdlen)) {
- /* 错误处理 */
- getError();
+ printTSError();
return;
}
- /* 转为16进制字符串并输出 */
- std::shared_ptr output(OPENSSL_buf2hexstr(md, mdlen),
- [](char *buf) { OPENSSL_free(buf); });
- this->ui->textBrowserOutput->setText(QString(output.get()));
+
+ if (OPENSSL_buf2hexstr_ex((char *) hex, sizeof(hex), NULL, md, mdlen, '\0') != 1) {
+ printTSError();
+ return;
+ }
+
+ this->ui->textBrowserOutput->setText(
+ QString::fromStdString(std::string((char *) hex, sizeof(hex))));
}
diff --git a/sm3hash.ui b/sm3hash.ui
index a308cd1..2c538bc 100644
--- a/sm3hash.ui
+++ b/sm3hash.ui
@@ -14,19 +14,6 @@
Form
- -
-
-
- Qt::Vertical
-
-
-
- 40
- 160
-
-
-
-
-
-
@@ -37,7 +24,7 @@
- 哈希内容:
+ 输入内容:
@@ -48,6 +35,9 @@
12
+
+ hex格式
+
-
@@ -70,7 +60,7 @@
- 哈希结果:
+ 杂凑结果:
@@ -88,19 +78,6 @@
- -
-
-
- Qt::Vertical
-
-
-
- 40
- 200
-
-
-
-
diff --git a/sm4encrypt.cpp b/sm4encrypt.cpp
index 71eb9e8..52da545 100644
--- a/sm4encrypt.cpp
+++ b/sm4encrypt.cpp
@@ -1,5 +1,6 @@
#include "sm4encrypt.h"
#include "ui_sm4encrypt.h"
+#include
Sm4encrypt::Sm4encrypt(QWidget *parent)
: QWidget(parent)
@@ -13,129 +14,235 @@ Sm4encrypt::~Sm4encrypt()
delete ui;
}
-void Sm4encrypt::on_pushButtonGen_clicked()
+static int do_sm4_crypt(const char *algo,
+ int enc,
+ const unsigned char *key,
+ const unsigned char *iv,
+ const unsigned char *input,
+ size_t inlen,
+ unsigned char *output,
+ size_t *outlen)
{
- /* 获取密钥 */
+ int ret = 0;
+ EVP_CIPHER_CTX *ctx = NULL;
+ EVP_CIPHER *cipher = NULL;
+ int len, lenf;
+
+ ctx = EVP_CIPHER_CTX_new();
+ if (ctx == NULL)
+ goto end;
+
+ cipher = EVP_CIPHER_fetch(NULL, algo, NULL);
+ if (cipher == NULL)
+ goto end;
+
+ if (!EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc))
+ goto end;
+
+ if (!EVP_CipherUpdate(ctx, output, &len, input, inlen))
+ goto end;
+
+ if (!EVP_CipherFinal_ex(ctx, output + len, &lenf))
+ goto end;
+
+ *outlen = len + lenf;
+ ret = 1;
+end:
+ EVP_CIPHER_CTX_free(ctx);
+ return ret;
+}
+
+void Sm4encrypt::on_pushButtonEncrypt_clicked()
+{
+ QString algo = this->ui->comboBoxMode->currentText();
QString keyQstr = this->ui->lineEditKey->text();
- long keyLen = keyQstr.size();
- std::shared_ptr key(OPENSSL_hexstr2buf(keyQstr.toStdString().c_str(), &keyLen),
- [](unsigned char *buf) { OPENSSL_free(buf); });
- /* 获取加密内容 */
- QString inputQstr = this->ui->plainTextEditInput->toPlainText();
- /* 生成加密上下文 */
- std::shared_ptr sm4Ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
- if (sm4Ctx == NULL) {
- /* 错误处理 */
- getError();
- return;
- }
- /* 选定模式初始化加密 */
- int modeIndex = this->ui->comboBoxMode->currentIndex();
- if (modeIndex == 0) {
- /* CBC模式 */
- QString ivQstr = this->ui->lineEditCBCIV->text();
- long ivlen = ivQstr.size();
- std::shared_ptr iv(OPENSSL_hexstr2buf(ivQstr.toStdString().c_str(), &ivlen),
- [](unsigned char *buf) { OPENSSL_free(buf); });
- if (!EVP_EncryptInit(sm4Ctx.get(), EVP_sm4_cbc(), key.get(), iv.get())) {
- /* 错误处理 */
- getError();
- return;
- }
- } else if (modeIndex == 1) {
- /* ECB模式 */
- if (!EVP_EncryptInit(sm4Ctx.get(), EVP_sm4_ecb(), key.get(), NULL)) {
- /* 错误处理 */
- getError();
- return;
- }
- } else {
- getError();
+ QString ivQstr = this->ui->lineEditIV->text();
+ QString inputQstr = this->ui->plainTextEditPlain->toPlainText();
+ std::vector key, iv, outbuf;
+ std::vector outhex;
+ size_t outlen;
+
+ if (keyQstr.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入密钥!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
return;
}
- /* 加密 */
- int outputLen = 0, tmpLen = 0;
- std::shared_ptr output(
- new unsigned char[inputQstr.size() + EVP_MAX_BLOCK_LENGTH]);
- if (!EVP_EncryptUpdate(sm4Ctx.get(),
- output.get(),
- &outputLen,
- (unsigned char *) inputQstr.toStdString().c_str(),
- inputQstr.size())) {
- /* 错误处理 */
- getError();
+ if (algo != "SM4-ECB" && ivQstr.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入初始化向量IV!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
return;
}
- if (!EVP_EncryptFinal(sm4Ctx.get(), output.get() + outputLen, &tmpLen)) {
- /* 错误处理 */
- getError();
+
+ key.reserve(keyQstr.size() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(key.data(), key.capacity(), NULL, keyQstr.toStdString().c_str(), '\0')
+ != 1) {
+ printTSError();
return;
}
- /* 将加密结果以16进制显示到输出栏 */
- std::shared_ptr outHex(OPENSSL_buf2hexstr(output.get(), outputLen + tmpLen),
- [](char *buf) { OPENSSL_free(buf); });
- this->ui->textBrowserOutput->setText(QString(outHex.get()));
+
+ iv.reserve(ivQstr.size() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(iv.data(), iv.capacity(), NULL, ivQstr.toStdString().c_str(), '\0')
+ != 1) {
+ printTSError();
+ return;
+ }
+
+ outbuf.reserve(inputQstr.size() + 16);
+
+ if (do_sm4_crypt(algo.toStdString().c_str(),
+ 1,
+ key.data(),
+ iv.data(),
+ (const unsigned char *) inputQstr.toStdString().c_str(),
+ inputQstr.size(),
+ outbuf.data(),
+ &outlen)
+ != 1) {
+ printTSError();
+ return;
+ }
+
+ outhex.reserve(outlen * 2 + 1);
+
+ if (OPENSSL_buf2hexstr_ex(outhex.data(), outhex.capacity(), NULL, outbuf.data(), outlen, '\0')
+ != 1) {
+ printTSError();
+ return;
+ }
+
+ this->ui->plainTextEditCipher->setPlainText(QString(outhex.data()));
}
void Sm4encrypt::on_pushButtonDecrypt_clicked()
{
- /* 获取密钥 */
+ QString algo = this->ui->comboBoxMode->currentText();
QString keyQstr = this->ui->lineEditKey->text();
- long keyLen = keyQstr.size();
- std::shared_ptr key(OPENSSL_hexstr2buf(keyQstr.toStdString().c_str(), &keyLen),
- [](unsigned char *buf) { OPENSSL_free(buf); });
- /* 获取解密内容 */
- QString inputQstr = this->ui->plainTextEditInput->toPlainText();
- long inputlen = inputQstr.size();
- std::shared_ptr input(OPENSSL_hexstr2buf(inputQstr.toStdString().c_str(),
- &inputlen),
- [](unsigned char *buf) { OPENSSL_free(buf); });
- /* 生成解密上下文 */
- std::shared_ptr sm4Ctx(EVP_CIPHER_CTX_new(), EVP_CIPHER_CTX_free);
- if (sm4Ctx == NULL) {
- /* 错误处理 */
- getError();
- return;
- }
- /* 选定模式初始化解密 */
- int modeIndex = this->ui->comboBoxMode->currentIndex();
- if (modeIndex == 0) {
- /* CBC模式 */
- QString ivQstr = this->ui->lineEditCBCIV->text();
- long ivlen = ivQstr.size();
- std::shared_ptr iv(OPENSSL_hexstr2buf(ivQstr.toStdString().c_str(), &ivlen),
- [](unsigned char *buf) { OPENSSL_free(buf); });
- if (!EVP_DecryptInit(sm4Ctx.get(), EVP_sm4_cbc(), key.get(), iv.get())) {
- /* 错误处理 */
- getError();
- return;
- }
- } else if (modeIndex == 1) {
- /* ECB模式 */
- if (!EVP_DecryptInit(sm4Ctx.get(), EVP_sm4_ecb(), key.get(), NULL)) {
- /* 错误处理 */
- getError();
- return;
- }
- } else {
- getError();
+ QString ivQstr = this->ui->lineEditIV->text();
+ QString inputQstr = this->ui->plainTextEditCipher->toPlainText();
+ std::vector key, iv, input;
+ std::vector outbuf;
+ size_t outlen;
+
+ if (keyQstr.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入密钥!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+
+ if (algo != "SM4-ECB" && ivQstr.isEmpty()) {
+ QMessageBox::warning(NULL,
+ "warning",
+ QString("请输入初始化向量IV!"),
+ QMessageBox::Close,
+ QMessageBox::Close);
+ return;
+ }
+
+ key.reserve(keyQstr.size() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(key.data(), key.capacity(), NULL, keyQstr.toStdString().c_str(), '\0')
+ != 1) {
+ printTSError();
return;
}
- /* 解密 */
- int outputLen = 0, tmpLen = 0;
- std::shared_ptr output(new unsigned char[inputlen]);
- if (!EVP_DecryptUpdate(sm4Ctx.get(), output.get(), &outputLen, input.get(), inputlen)) {
- /* 错误处理 */
- getError();
+
+ iv.reserve(ivQstr.size() / 2);
+
+ if (OPENSSL_hexstr2buf_ex(iv.data(), iv.capacity(), NULL, ivQstr.toStdString().c_str(), '\0')
+ != 1) {
+ printTSError();
+ return;
+ }
+
+ input.reserve(inputQstr.size() / 2);
+ if (OPENSSL_hexstr2buf_ex(input.data(),
+ input.capacity(),
+ NULL,
+ inputQstr.toStdString().c_str(),
+ '\0')
+ != 1) {
+ printTSError();
+ return;
+ }
+
+ outbuf.reserve(input.capacity());
+
+ if (do_sm4_crypt(algo.toStdString().c_str(),
+ 0,
+ key.data(),
+ iv.data(),
+ input.data(),
+ input.capacity(),
+ (unsigned char *) outbuf.data(),
+ &outlen)
+ != 1) {
+ printTSError();
return;
}
- if (!EVP_DecryptFinal(sm4Ctx.get(), output.get() + outputLen, &tmpLen)) {
- /* 错误处理 */
- getError();
+
+ this->ui->plainTextEditPlain->setPlainText(
+ QString::fromStdString(std::string(outbuf.data(), outlen)));
+}
+
+void Sm4encrypt::on_pushButtonRandomIV_clicked()
+{
+ unsigned char buf[16];
+ std::vector hex;
+
+ if (RAND_bytes(buf, sizeof(buf)) != 1) {
+ printTSError();
+ return;
+ }
+
+ hex.reserve(sizeof(buf) * 2 + 1);
+
+ if (OPENSSL_buf2hexstr_ex(hex.data(), hex.capacity(), NULL, buf, sizeof(buf), '\0') != 1) {
+ printTSError();
return;
}
- /* 将解密结果显示到输出栏 */
- this->ui->textBrowserOutput->setText(
- QString::asprintf("%.*s", outputLen + tmpLen, output.get()));
+
+ this->ui->lineEditIV->setText(hex.data());
+}
+
+void Sm4encrypt::on_pushButtonRandomKey_clicked()
+{
+ unsigned char buf[16];
+ std::vector hex;
+
+ if (RAND_bytes(buf, sizeof(buf)) != 1) {
+ printTSError();
+ return;
+ }
+
+ hex.reserve(sizeof(buf) * 2 + 1);
+
+ if (OPENSSL_buf2hexstr_ex(hex.data(), hex.capacity(), NULL, buf, sizeof(buf), '\0') != 1) {
+ printTSError();
+ return;
+ }
+
+ this->ui->lineEditKey->setText(hex.data());
+}
+
+void Sm4encrypt::on_comboBoxMode_currentTextChanged(const QString &arg1)
+{
+ if (arg1 == "SM4-ECB") {
+ this->ui->lineEditIV->setEnabled(false);
+ this->ui->lineEditIV->hide();
+ } else {
+ this->ui->lineEditIV->setEnabled(true);
+ this->ui->lineEditIV->show();
+ }
}
diff --git a/sm4encrypt.h b/sm4encrypt.h
index 1faa441..bfd6777 100644
--- a/sm4encrypt.h
+++ b/sm4encrypt.h
@@ -18,10 +18,16 @@ class Sm4encrypt : public QWidget
~Sm4encrypt();
private slots:
- void on_pushButtonGen_clicked();
+ void on_pushButtonEncrypt_clicked();
void on_pushButtonDecrypt_clicked();
+ void on_pushButtonRandomIV_clicked();
+
+ void on_pushButtonRandomKey_clicked();
+
+ void on_comboBoxMode_currentTextChanged(const QString &arg1);
+
private:
Ui::Sm4encrypt *ui;
};
diff --git a/sm4encrypt.ui b/sm4encrypt.ui
index 198bd79..d5e7724 100644
--- a/sm4encrypt.ui
+++ b/sm4encrypt.ui
@@ -14,91 +14,41 @@
Form
- -
-
-
-
-
-
-
- 12
-
-
-
-
-
- CBC
-
-
- -
-
- EBC
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
-
-
-
- 12
-
-
-
- 初始IV:
-
-
-
- -
-
-
-
- 12
-
-
-
- 1F:B2:D4:2F:B3:6E:2E:88:A2:20:B0:4F:2E:49:AA:13
-
-
-
-
-
-
-
-
-
-
- -
-
+
-
+
12
-
- 加密/解密结果:
-
+
-
+
+ SM4-CBC
+
+
+ -
+
+ SM4-ECB
+
+
+ -
+
+ SM4-CFB
+
+
+ -
+
+ SM4-OFB
+
+
+ -
+
+ SM4-CTR
+
+
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
+
-
@@ -106,12 +56,12 @@
- 加密/解密内容:
+ 明文:
- -
-
+
-
+
12
@@ -122,66 +72,59 @@
- -
-
-
- Qt::Vertical
+
-
+
+
+
+ 12
+
-
-
- 20
- 40
-
+
+ 加密模式:
-
+
- -
-
+
-
+
12
- 3F:34:2E:9D:67:D6:CE:7B:E7:01:75:6A:F7:BA:C8:F2
+
+
+
+ hex格式
- -
-
+
-
+
12
+
+ 初始化向量:
+
- -
-
+
-
+
12
- 密钥:
+ 密文:
- -
+
-
-
-
-
-
-
- 12
-
-
-
- 加密
-
-
-
-
@@ -196,37 +139,84 @@
- -
-
+
-
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
12
- 加密模式:
+ 密钥:
+
+
+
+ -
+
+
+
+ 12
+
+
+
+
+
+
+ hex格式
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 加密
+
+
+
+ -
+
+
+ hex格式
+
+
+
+ -
+
+
+ 随机
+
+
+
+ -
+
+
+ 随机
-
-
- comboBoxMode
- currentIndexChanged(int)
- stackedWidget
- setCurrentIndex(int)
-
-
- 112
- 178
-
-
- 169
- 189
-
-
-
-
+
diff --git a/tlcpclient.cpp b/tlcpclient.cpp
index 0636e91..a127aed 100644
--- a/tlcpclient.cpp
+++ b/tlcpclient.cpp
@@ -1,6 +1,6 @@
#include "tlcpclient.h"
#include "ui_tlcpclient.h"
-static SSL *ssl;
+
TLCPclient::TLCPclient(QWidget *parent)
: QWidget(parent)
, ui(new Ui::TLCPclient)
@@ -12,53 +12,84 @@ TLCPclient::TLCPclient(QWidget *parent)
TLCPclient::~TLCPclient()
{
delete ui;
+ SSL_free(ssl);
+ ssl = NULL;
+ SSL_CTX_free(ctx);
+ ctx = NULL;
+ socket.close();
}
void TLCPclient::on_pushButtonConnect_clicked()
{
+ int ret, err;
+
if (ui->pushButtonConnect->text() == "连接服务器") {
- //载入SSL相关信息
- SSL_library_init();
- SSL_load_error_strings();
- OpenSSL_add_all_algorithms();
//获取域名端口
QString addrQstr = this->ui->lineEditAddr->text();
QString portQstr = this->ui->lineEditPort->text();
+ QString cipherList = this->ui->lineEditCiphers->text();
// 创建一个 QSslSocket对象设置地址并连接
- QTcpSocket socket;
- socket.connectToHost(addrQstr, portQstr.toInt());
- if (!socket.waitForConnected()) {
+
+ this->socket.reset();
+ this->socket.connectToHost(addrQstr, portQstr.toInt());
+ if (!this->socket.waitForConnected()) {
QMessageBox::warning(NULL,
"connect failed",
- QString("TCP connection to server failed"),
+ QString("TCP连接失败,请确认服务器地址&端口号是否正确"),
QMessageBox::Ok,
QMessageBox::Ok);
+ return;
}
//TCP已连接,准备SSL连接
- const SSL_METHOD *method = NTLS_client_method();
- std::shared_ptr ssl_ctx(SSL_CTX_new(method), SSL_CTX_free);
- SSL_CTX_enable_ntls(ssl_ctx.get());
- SSL_CTX_set_verify(ssl_ctx.get(), SSL_VERIFY_NONE, NULL);
- ssl = SSL_new(ssl_ctx.get());
- SSL_set_fd(ssl, socket.socketDescriptor());
- if (SSL_connect(ssl) == 1) {
+ if (this->ctx == NULL) {
+ this->ctx = SSL_CTX_new(NTLS_client_method());
+ if (this->ctx == NULL) {
+ return;
+ }
+
+ SSL_CTX_enable_ntls(this->ctx);
+ SSL_CTX_set_verify(this->ctx, SSL_VERIFY_NONE, NULL);
+ }
+
+ if (SSL_CTX_set_cipher_list(this->ctx, cipherList.toStdString().c_str()) != 1) {
+ QMessageBox::warning(NULL,
+ "set cipher list failed",
+ QString("设置密码套件失败,请确认套件格式是否正确"),
+ QMessageBox::Ok,
+ QMessageBox::Ok);
+ return;
+ }
+
+ SSL_free(this->ssl);
+ this->ssl = SSL_new(this->ctx);
+ SSL_set_fd(ssl, this->socket.socketDescriptor());
+
+ if (BIO_socket_nbio(this->socket.socketDescriptor(), 0) != 1) {
+ QMessageBox::warning(NULL,
+ "set blocking failed",
+ QString("设置阻塞模式失败"),
+ QMessageBox::Ok,
+ QMessageBox::Ok);
+ return;
+ }
+
+ ret = SSL_connect(this->ssl);
+ if (ret == 1) {
//SSL连接成功
ui->pushButtonConnect->setText("断开服务器");
- QMessageBox::information(NULL,
- "connect success",
- QString("TLCP connection to server successful"),
- QMessageBox::Ok,
- QMessageBox::Ok);
+
+ this->ui->textBrowserDebug->append(QString("TLCP握手成功\n"));
ui->pushButtonSend->setEnabled(true);
} else {
+ err = SSL_get_error(this->ssl, ret);
+
//SSL连接失败
- SSL_shutdown(ssl);
- SSL_free(ssl);
+ SSL_shutdown(this->ssl);
QMessageBox::warning(NULL,
"connect failed",
- QString("SSL connection to server failed"),
+ QString("TLCP连接失败,err:%1").arg(err),
QMessageBox::Ok,
QMessageBox::Ok);
return;
@@ -66,42 +97,61 @@ void TLCPclient::on_pushButtonConnect_clicked()
} else {
ui->pushButtonConnect->setText("连接服务器");
ui->pushButtonSend->setEnabled(false);
- if (ssl != NULL) {
- SSL_shutdown(ssl);
- SSL_free(ssl);
+ if (this->ssl != NULL) {
+ SSL_shutdown(this->ssl);
}
- QMessageBox::information(NULL,
- "connect closed",
- QString("client closed connection"),
- QMessageBox::Ok,
- QMessageBox::Ok);
+
+ this->ui->textBrowserDebug->append(QString("客户端关闭连接\n"));
}
}
void TLCPclient::on_pushButtonSend_clicked()
{
- SSL_set_msg_callback(ssl, trace_cb);
+ // SSL_set_msg_callback(ssl, trace_cb);
//获取发送内容
QString inputQstr = this->ui->plainTextEditInput->toPlainText();
- int ret = SSL_write(ssl, inputQstr.toStdString().c_str(), inputQstr.size());
+ int ret = SSL_write(this->ssl, inputQstr.toStdString().c_str(), inputQstr.size());
if (ret < 0) {
- //发送失败
- getError();
- return;
- }
- SSL_set_connect_state(ssl);
- char rxbuf[256] = {0};
- int rxlen = SSL_read(ssl, rxbuf, 256);
- if (rxlen < 0) {
- int err = SSL_get_error(ssl, rxlen);
- while (err == 2) {
- rxlen = SSL_read(ssl, rxbuf, 256);
- err = SSL_get_error(ssl, rxlen);
+ int err = SSL_get_error(this->ssl, ret);
+
+ if (err == SSL_ERROR_SYSCALL && !socket.isOpen()) {
+ QMessageBox::warning(NULL,
+ "write failed",
+ QString("TLCP发送数据失败,服务端已经关闭连接"),
+ QMessageBox::Ok,
+ QMessageBox::Ok);
+ return;
+ } else {
+ QMessageBox::warning(NULL,
+ "write failed",
+ QString("TLCP发送数据失败,err:%1").arg(err),
+ QMessageBox::Ok,
+ QMessageBox::Ok);
+ //发送失败
+ // getError();
+ return;
}
- getError();
} else {
- //输出到反馈栏
+ this->ui->textBrowserDebug->append(QString(">>>:\n") + inputQstr + QString("\n"));
+ }
+
+ char rxbuf[16384] = {0};
+ ret = SSL_read(this->ssl, rxbuf, sizeof(rxbuf));
+ if (ret < 0) {
+ int err = SSL_get_error(this->ssl, ret);
+
+ QMessageBox::warning(NULL,
+ "read failed",
+ QString("读失败,err:%1").arg(err),
+ QMessageBox::Ok,
+ QMessageBox::Ok);
+ return;
+ } else {
+ // 输出到接收
this->ui->textBrowserOutput->setText(QString::asprintf("%s", rxbuf));
+
+ this->ui->textBrowserDebug->append(QString("<<<:\n") + QString::asprintf("%s", rxbuf)
+ + QString("\n"));
}
}
diff --git a/tlcpclient.h b/tlcpclient.h
index 8840bd7..9660b33 100644
--- a/tlcpclient.h
+++ b/tlcpclient.h
@@ -2,6 +2,7 @@
#define TLCPCLIENT_H
#include
+#include
#include
#include
#include
@@ -33,6 +34,9 @@ private slots:
private:
Ui::TLCPclient *ui;
+ QTcpSocket socket;
+ SSL_CTX *ctx;
+ SSL *ssl;
};
#endif // TLCPCLIENT_H
diff --git a/tlcpclient.ui b/tlcpclient.ui
index 88ab966..1c23db4 100644
--- a/tlcpclient.ui
+++ b/tlcpclient.ui
@@ -6,43 +6,42 @@
0
0
- 427
- 300
+ 434
+ 426
Form
-
+
QLayout::SetMinimumSize
- -
-
+
-
+
12
- 发送内容:
+ 接收数据:
- -
-
+
-
+
12
-
- hello Tongsuo
-
+
+ 发送数据:
- -
+
-
@@ -50,11 +49,58 @@
- 112.64.122.183
+ 127.0.0.1
+
+
+ IP地址
+
+
+
+ -
+
+
+ 调试信息输出
+
+
+
+ -
+
+
+ -
+
+
+
+ Academy Engraved LET
+ 13
+
+
+
+ 服务器地址:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 12
+
+
+
+ 443
+
+
+ 端口号
- -
+
-
@@ -66,31 +112,33 @@
- -
-
+
-
+
12
- 内容反馈:
+ 发送
- -
-
+
-
+
12
-
- 服务器地址:
+
+ GET / HTTP/1.0
+
+
- -
+
-
@@ -104,38 +152,22 @@ p, li { white-space: pre-wrap; }
hr { height: 1px; border-width: 0; }
li.unchecked::marker { content: "\2610"; }
li.checked::marker { content: "\2612"; }
-</style></head><body style=" font-family:'Microsoft YaHei UI'; font-size:12pt; font-weight:400; font-style:normal;">
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html>
+</style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:12pt; font-weight:400; font-style:normal;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Microsoft YaHei UI';"><br /></p></body></html>
- -
-
-
-
- 12
-
-
+
-
+
- 发送
+ ECC-SM2-SM4-CBC-SM3
- -
-
-
-
- 0
- 0
-
-
-
-
- 12
-
-
+
-
+
- 443
+ 密码套件:
diff --git a/tserror.cpp b/tserror.cpp
index 1fff4bf..7b6a6c4 100644
--- a/tserror.cpp
+++ b/tserror.cpp
@@ -17,3 +17,18 @@ void getError()
QMessageBox::Close);
return;
}
+
+void printTSError()
+{
+ char buf[512];
+
+ ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
+
+ QMessageBox::warning(NULL,
+ "Error",
+ QString::asprintf("%s", buf),
+ QMessageBox::Close,
+ QMessageBox::Close);
+
+ return;
+}
diff --git a/tserror.h b/tserror.h
index d515bf1..3cc44f8 100644
--- a/tserror.h
+++ b/tserror.h
@@ -5,5 +5,8 @@
/* 错误处理函数 */
void getError();
+void printTSError();
+
+extern BIO *bio_err;
#endif // TSERROR_H