├── version.h
├── certs.qrc
├── tserror.h
├── certs
├── ca.key
├── subca.key
├── ca.pem
└── subca.pem
├── README.md
├── CHANGES
├── about.h
├── main.cpp
├── about.cpp
├── sm3hash.h
├── mainwindow.h
├── mainwindow.cpp
├── randnum.h
├── sm2cert.h
├── sm2key.h
├── sm2signverify.h
├── sm2.h
├── sm4encrypt.h
├── sm2encrypt.h
├── .gitignore
├── tserror.cpp
├── tlcpclient.h
├── sm3hash.cpp
├── sm2key.cpp
├── randnum.cpp
├── TongsuoToolbox_v01.pro
├── sm2key.ui
├── sm3hash.ui
├── sm2encrypt.ui
├── randnum.ui
├── .clang-format
├── .github
└── workflows
│ ├── ci.yml
│ └── release.yml
├── about.ui
├── sm2signverify.ui
├── mainwindow.ui
├── sm2cert.ui
├── sm2.cpp
├── sm2encrypt.cpp
├── tlcpclient.ui
├── tlcpclient.cpp
├── sm4encrypt.ui
├── sm2signverify.cpp
├── sm4encrypt.cpp
├── LICENSE
└── sm2cert.cpp
/version.h:
--------------------------------------------------------------------------------
1 | #ifndef VERSION_H
2 | #define VERSION_H
3 |
4 | static const char *version = "1.0.0";
5 |
6 | #endif // VERSION_H
7 |
--------------------------------------------------------------------------------
/certs.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | certs/subca.pem
4 | certs/subca.key
5 |
6 |
7 |
--------------------------------------------------------------------------------
/tserror.h:
--------------------------------------------------------------------------------
1 | #ifndef TSERROR_H
2 | #define TSERROR_H
3 | #include
4 | #include
5 |
6 | /* 错误处理函数 */
7 | void getError();
8 | void printTSError();
9 |
10 | extern BIO *bio_err;
11 |
12 | #endif // TSERROR_H
13 |
--------------------------------------------------------------------------------
/certs/ca.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgTSHZtff0A3YHhojG
3 | HKIu0odvPip6+39lsguxDH3m+TmhRANCAARC7ZCfZAaqCbMEh1K3pEj2S6/ty2yN
4 | C6x0zIbyxq+mib7qTssQcLrsPMe1EGb2FZQpGk4L9mOzBNlijoi1ocb5
5 | -----END PRIVATE KEY-----
6 |
--------------------------------------------------------------------------------
/certs/subca.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgC2yI3oPT4cnM8fGf
3 | J/emyP9/Qr87/x1RO5sNMnm5ioqhRANCAAR73c9xN7bdOrqUQhe/77qxwerRbzZe
4 | wZ65DXOMgIztuCiCEQLh0CfjPLV98LxHbUhTc1EJWhDGofTqh8VFQNYj
5 | -----END PRIVATE KEY-----
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tsapp
2 | 基于铜锁密码库开发的商用密码工具箱桌面应用程序
3 |
4 | # 功能与特性
5 |
6 | > 多数功能都支持用户自输入密钥
7 |
8 | - 随机数生成
9 | - SM2密钥对生成
10 | - SM2加解密
11 | - SM2签名与验签
12 | - SM3摘要
13 | - SM4加解密
14 | - 签发SM2证书
15 | - TLCP客户端
16 |
17 | # 配置与安装
18 |
19 | 可以直接安装使用该应用程序,或使用源码在本地使用QT启动。
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/CHANGES:
--------------------------------------------------------------------------------
1 |
2 | tsapp CHANGES
3 | -------------
4 |
5 | Changes with 1.0.0 [xx XXX xxxx]
6 |
7 | *) 支持随机数生成器
8 |
9 | *) 支持SM2密钥对生成
10 |
11 | *) 支持SM2签名和验签
12 |
13 | *) 支持SM2加密和解密
14 |
15 | *) 支持SM3杂凑
16 |
17 | *) 支持SM4加解密,模式包括CBC、ECB、CFB、OFB、CTR
18 |
19 | *) 支持双证书签发
20 |
21 | *) 支持TLCP客户端
22 |
--------------------------------------------------------------------------------
/about.h:
--------------------------------------------------------------------------------
1 | #ifndef ABOUT_H
2 | #define ABOUT_H
3 |
4 | #include
5 |
6 | namespace Ui {
7 | class About;
8 | }
9 |
10 | class About : public QDialog
11 | {
12 | Q_OBJECT
13 |
14 | public:
15 | explicit About(QWidget *parent = nullptr);
16 | ~About();
17 |
18 | private slots:
19 | void on_pushButton_clicked();
20 |
21 | private:
22 | Ui::About *ui;
23 | };
24 |
25 | #endif // ABOUT_H
26 |
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 | #include
4 |
5 | BIO *bio_err = NULL;
6 |
7 | int main(int argc, char *argv[])
8 | {
9 | if (!OPENSSL_init_ssl(OPENSSL_INIT_NO_LOAD_CONFIG, NULL))
10 | return 1;
11 |
12 | bio_err = BIO_new_fp(stderr, BIO_NOCLOSE | BIO_FP_TEXT);
13 |
14 | QApplication a(argc, argv);
15 | MainWindow w;
16 | w.show();
17 | return a.exec();
18 | }
19 |
--------------------------------------------------------------------------------
/about.cpp:
--------------------------------------------------------------------------------
1 | #include "about.h"
2 | #include "ui_about.h"
3 | #include "version.h"
4 |
5 | About::About(QWidget *parent)
6 | : QDialog(parent)
7 | , ui(new Ui::About)
8 | {
9 | ui->setupUi(this);
10 |
11 | QString text = ui->textBrowser->toHtml();
12 |
13 | text.replace("|version|", version);
14 |
15 | ui->textBrowser->setHtml(text);
16 | }
17 |
18 | About::~About()
19 | {
20 | delete ui;
21 | }
22 |
23 | void About::on_pushButton_clicked()
24 | {
25 | this->close();
26 | }
27 |
--------------------------------------------------------------------------------
/sm3hash.h:
--------------------------------------------------------------------------------
1 | #ifndef SM3HASH_H
2 | #define SM3HASH_H
3 |
4 | #include "tserror.h"
5 | #include
6 | #include
7 | #include
8 |
9 | namespace Ui {
10 | class Sm3Hash;
11 | }
12 |
13 | class Sm3Hash : public QWidget
14 | {
15 | Q_OBJECT
16 |
17 | public:
18 | explicit Sm3Hash(QWidget *parent = nullptr);
19 | ~Sm3Hash();
20 |
21 | private slots:
22 | void on_pushButtonGen_clicked();
23 |
24 | private:
25 | Ui::Sm3Hash *ui;
26 | };
27 |
28 | #endif // SM3HASH_H
29 |
--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include "about.h"
5 | #include
6 |
7 | namespace Ui {
8 | class MainWindow;
9 | }
10 |
11 | class MainWindow : public QMainWindow
12 | {
13 | Q_OBJECT
14 |
15 | public:
16 | explicit MainWindow(QWidget *parent = nullptr);
17 | ~MainWindow();
18 |
19 | private slots:
20 | void on_action_about_triggered();
21 |
22 | void on_action_exit_triggered();
23 |
24 | void on_listWidget_currentRowChanged(int currentRow);
25 |
26 | private:
27 | Ui::MainWindow *ui;
28 |
29 | About *about;
30 | };
31 |
32 | #endif // MAINWINDOW_H
33 |
--------------------------------------------------------------------------------
/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include "ui_mainwindow.h"
3 |
4 | MainWindow::MainWindow(QWidget *parent)
5 | : QMainWindow(parent)
6 | , ui(new Ui::MainWindow)
7 | {
8 | ui->setupUi(this);
9 | about = new About();
10 | }
11 |
12 | MainWindow::~MainWindow()
13 | {
14 | delete ui;
15 | }
16 |
17 | void MainWindow::on_action_about_triggered()
18 | {
19 | about->show();
20 | }
21 |
22 | void MainWindow::on_action_exit_triggered()
23 | {
24 | this->close();
25 | }
26 |
27 | void MainWindow::on_listWidget_currentRowChanged(int currentRow)
28 | {
29 | this->ui->stackedWidget->setCurrentIndex(currentRow);
30 | }
31 |
--------------------------------------------------------------------------------
/randnum.h:
--------------------------------------------------------------------------------
1 | #ifndef RANDNUM_H
2 | #define RANDNUM_H
3 |
4 | #include "tserror.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | namespace Ui {
16 | class RandNum;
17 | }
18 |
19 | class RandNum : public QWidget
20 | {
21 | Q_OBJECT
22 |
23 | public:
24 | explicit RandNum(QWidget *parent = nullptr);
25 | ~RandNum();
26 |
27 | private slots:
28 | void on_pushButtonGen_clicked();
29 |
30 | private:
31 | Ui::RandNum *ui;
32 | };
33 |
34 | #endif // RANDNUM_H
35 |
--------------------------------------------------------------------------------
/sm2cert.h:
--------------------------------------------------------------------------------
1 | #ifndef SM2CERT_H
2 | #define SM2CERT_H
3 |
4 | #include "tserror.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | namespace Ui {
18 | class Sm2Cert;
19 | }
20 |
21 | class Sm2Cert : public QWidget
22 | {
23 | Q_OBJECT
24 |
25 | public:
26 | explicit Sm2Cert(QWidget *parent = nullptr);
27 | ~Sm2Cert();
28 |
29 | private slots:
30 | void on_pushButtonGen_clicked();
31 |
32 | private:
33 | Ui::Sm2Cert *ui;
34 | };
35 |
36 | #endif // SM2CERT_H
37 |
--------------------------------------------------------------------------------
/sm2key.h:
--------------------------------------------------------------------------------
1 | #ifndef SM2KEY_H
2 | #define SM2KEY_H
3 |
4 | #include "tserror.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include
16 |
17 | namespace Ui {
18 | class Sm2Key;
19 | }
20 |
21 | class Sm2Key : public QWidget
22 | {
23 | Q_OBJECT
24 |
25 | public:
26 | explicit Sm2Key(QWidget *parent = nullptr);
27 | ~Sm2Key();
28 |
29 | private slots:
30 | void on_pushButtonGen_clicked();
31 |
32 | private:
33 | Ui::Sm2Key *ui;
34 | };
35 |
36 | #endif // SM2KEY_H
37 |
--------------------------------------------------------------------------------
/sm2signverify.h:
--------------------------------------------------------------------------------
1 | #ifndef SM2SIGNVERIFY_H
2 | #define SM2SIGNVERIFY_H
3 |
4 | #include "tserror.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | namespace Ui {
12 | class Sm2SignVerify;
13 | }
14 |
15 | class Sm2SignVerify : public QWidget
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | explicit Sm2SignVerify(QWidget *parent = nullptr);
21 | ~Sm2SignVerify();
22 |
23 | private slots:
24 | void on_pushButtonGenKey_clicked();
25 |
26 | void on_pushButtonSign_clicked();
27 |
28 | void on_pushButtonVerify_clicked();
29 |
30 | private:
31 | Ui::Sm2SignVerify *ui;
32 | };
33 |
34 | #endif // SM2SIGNVERIFY_H
35 |
--------------------------------------------------------------------------------
/sm2.h:
--------------------------------------------------------------------------------
1 | #ifndef SM2_H
2 | #define SM2_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | int sm2_key_get_pub_pem(const EVP_PKEY *pkey, std::string &pem);
14 | int sm2_key_get_priv_pem(const EVP_PKEY *pkey, std::string &pem);
15 | int sm2_key_get_pub_hex(const EVP_PKEY *pkey, std::string &hex);
16 | int sm2_key_get_priv_hex(const EVP_PKEY *pkey, std::string &hex);
17 | EVP_PKEY *sm2_key_new_from_raw_pub(const std::string &pub);
18 | EVP_PKEY *sm2_key_new_from_raw_pub_and_priv(const std::string &pub, const std::string &priv);
19 |
20 | #endif // SM2_H
21 |
--------------------------------------------------------------------------------
/certs/ca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIB3jCCAYSgAwIBAgIBAjAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
3 | A1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0GA1UEAwwGQ0Eg
4 | U00yMCAXDTI0MDcwNzA0Mjc0NVoYDzIxMjQwNjEzMDQyNzQ1WjBFMQswCQYDVQQG
5 | EwJBQjELMAkGA1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0G
6 | A1UEAwwGQ0EgU00yMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEQu2Qn2QGqgmz
7 | BIdSt6RI9kuv7ctsjQusdMyG8savpom+6k7LEHC67DzHtRBm9hWUKRpOC/ZjswTZ
8 | Yo6ItaHG+aNjMGEwHQYDVR0OBBYEFGPkDCglafjEeeT2wufS/PqKqSP+MB8GA1Ud
9 | IwQYMBaAFGPkDCglafjEeeT2wufS/PqKqSP+MA8GA1UdEwEB/wQFMAMBAf8wDgYD
10 | VR0PAQH/BAQDAgGGMAoGCCqBHM9VAYN1A0gAMEUCIQDOKNIcpCOnL/qFC9nYHSY0
11 | fHWiGgZLLVFkamCN0meRNgIgUfW1xK+7rZddJSHqJKIeHJp28PlKBXY8oIuGhhEz
12 | EqQ=
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/sm4encrypt.h:
--------------------------------------------------------------------------------
1 | #ifndef SM4ENCRYPT_H
2 | #define SM4ENCRYPT_H
3 |
4 | #include "tserror.h"
5 | #include
6 | #include
7 | #include
8 | namespace Ui {
9 | class Sm4encrypt;
10 | }
11 |
12 | class Sm4encrypt : public QWidget
13 | {
14 | Q_OBJECT
15 |
16 | public:
17 | explicit Sm4encrypt(QWidget *parent = nullptr);
18 | ~Sm4encrypt();
19 |
20 | private slots:
21 | void on_pushButtonEncrypt_clicked();
22 |
23 | void on_pushButtonDecrypt_clicked();
24 |
25 | void on_pushButtonRandomIV_clicked();
26 |
27 | void on_pushButtonRandomKey_clicked();
28 |
29 | void on_comboBoxMode_currentTextChanged(const QString &arg1);
30 |
31 | private:
32 | Ui::Sm4encrypt *ui;
33 | };
34 |
35 | #endif // SM4ENCRYPT_H
36 |
--------------------------------------------------------------------------------
/certs/subca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIB4zCCAYqgAwIBAgIBAjAKBggqgRzPVQGDdTBFMQswCQYDVQQGEwJBQjELMAkG
3 | A1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjEPMA0GA1UEAwwGQ0Eg
4 | U00yMCAXDTI0MDcwNzA0Mjc0NloYDzIxMjQwNjEzMDQyNzQ2WjBIMQswCQYDVQQG
5 | EwJBQjELMAkGA1UECAwCQ0QxCzAJBgNVBAoMAkdIMQswCQYDVQQLDAJJSjESMBAG
6 | A1UEAwwJU1VCQ0EgU00yMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEe93PcTe2
7 | 3Tq6lEIXv++6scHq0W82XsGeuQ1zjICM7bgoghEC4dAn4zy1ffC8R21IU3NRCVoQ
8 | xqH06ofFRUDWI6NmMGQwHQYDVR0OBBYEFCi8tdpCMx+yoWdWdO3IZ6xxDhljMB8G
9 | A1UdIwQYMBaAFGPkDCglafjEeeT2wufS/PqKqSP+MBIGA1UdEwEB/wQIMAYBAf8C
10 | AQAwDgYDVR0PAQH/BAQDAgGGMAoGCCqBHM9VAYN1A0cAMEQCIH6UJaA1ppUtSbHn
11 | 3JRGdRHpVKgGaxRkqIVIrfgLnG8IAiBrcRv26xSHRe1eFT9BoJkIiFNTb/gbPdjS
12 | 0kQ4AdEHkQ==
13 | -----END CERTIFICATE-----
14 |
--------------------------------------------------------------------------------
/sm2encrypt.h:
--------------------------------------------------------------------------------
1 | #ifndef SM2ENCRYPT_H
2 | #define SM2ENCRYPT_H
3 |
4 | #include "tserror.h"
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 | #include
15 |
16 | namespace Ui {
17 | class Sm2Encrypt;
18 | }
19 |
20 | class Sm2Encrypt : public QWidget
21 | {
22 | Q_OBJECT
23 |
24 | public:
25 | explicit Sm2Encrypt(QWidget *parent = nullptr);
26 | ~Sm2Encrypt();
27 |
28 | private slots:
29 | void on_pushButtonEncrypt_clicked();
30 |
31 | void on_pushButtonDecrypt_clicked();
32 |
33 | void on_pushButtonGen_clicked();
34 |
35 | private:
36 | Ui::Sm2Encrypt *ui;
37 | };
38 |
39 | #endif // SM2ENCRYPT_H
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # C++ objects and libs
2 | *.slo
3 | *.lo
4 | *.o
5 | *.a
6 | *.la
7 | *.lai
8 | *.so
9 | *.so.*
10 | *.dll
11 | *.dylib
12 |
13 | # Qt-es
14 | object_script.*.Release
15 | object_script.*.Debug
16 | *_plugin_import.cpp
17 | /.qmake.cache
18 | /.qmake.stash
19 | *.pro.user
20 | *.pro.user.*
21 | *.qbs.user
22 | *.qbs.user.*
23 | *.moc
24 | moc_*.cpp
25 | moc_*.h
26 | qrc_*.cpp
27 | ui_*.h
28 | *.qmlc
29 | *.jsc
30 | Makefile*
31 | *build-*
32 | *.qm
33 | *.prl
34 |
35 | # Qt unit tests
36 | target_wrapper.*
37 |
38 | # QtCreator
39 | *.autosave
40 |
41 | # QtCreator Qml
42 | *.qmlproject.user
43 | *.qmlproject.user.*
44 |
45 | # QtCreator CMake
46 | CMakeLists.txt.user*
47 |
48 | # QtCreator 4.8< compilation database
49 | compile_commands.json
50 |
51 | # QtCreator local machine specific files for imported projects
52 | *creator.user*
53 |
54 | *_qmlcache.qrc
55 |
56 | # Tongsuo
57 | /Tongsuo
--------------------------------------------------------------------------------
/tserror.cpp:
--------------------------------------------------------------------------------
1 | #include "tserror.h"
2 |
3 | void getError()
4 | {
5 | unsigned long er = 0;
6 | char erbuf[512] = {0};
7 | size_t erlen = 512;
8 | /* 获取错误号 */
9 | er = ERR_get_error();
10 | /* 将错误号转变为对应字符串 */
11 | ERR_error_string_n(er, erbuf, erlen);
12 | /* 弹窗显示 */
13 | QMessageBox::warning(NULL,
14 | "warning",
15 | QString::asprintf("%s", erbuf),
16 | QMessageBox::Close,
17 | QMessageBox::Close);
18 | return;
19 | }
20 |
21 | void printTSError()
22 | {
23 | char buf[512];
24 |
25 | ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
26 |
27 | QMessageBox::warning(NULL,
28 | "Error",
29 | QString::asprintf("%s", buf),
30 | QMessageBox::Close,
31 | QMessageBox::Close);
32 |
33 | return;
34 | }
35 |
--------------------------------------------------------------------------------
/tlcpclient.h:
--------------------------------------------------------------------------------
1 | #ifndef TLCPCLIENT_H
2 | #define TLCPCLIENT_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | namespace Ui {
12 | class TLCPclient;
13 | }
14 |
15 | class TLCPclient : public QWidget
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | explicit TLCPclient(QWidget *parent = nullptr);
21 | ~TLCPclient();
22 | static void trace_cb(int write_p,
23 | int version,
24 | int content_type,
25 | const void *buf,
26 | size_t msglen,
27 | SSL *ssl,
28 | void *arg);
29 | private slots:
30 | void on_pushButtonConnect_clicked();
31 |
32 | void on_pushButtonSend_clicked();
33 |
34 | private:
35 | Ui::TLCPclient *ui;
36 | QTcpSocket socket;
37 | SSL_CTX *ctx;
38 | SSL *ssl;
39 | };
40 |
41 | #endif // TLCPCLIENT_H
42 |
--------------------------------------------------------------------------------
/sm3hash.cpp:
--------------------------------------------------------------------------------
1 | #include "sm3hash.h"
2 | #include "ui_sm3hash.h"
3 |
4 | Sm3Hash::Sm3Hash(QWidget *parent)
5 | : QWidget(parent)
6 | , ui(new Ui::Sm3Hash)
7 | {
8 | ui->setupUi(this);
9 | }
10 |
11 | Sm3Hash::~Sm3Hash()
12 | {
13 | delete ui;
14 | }
15 |
16 | void Sm3Hash::on_pushButtonGen_clicked()
17 | {
18 | QString input = this->ui->plainTextEditInput->toPlainText();
19 | unsigned char md[32] = {};
20 | unsigned char hex[65];
21 | size_t mdlen = 0;
22 |
23 | if (input.isEmpty()) {
24 | if (input.isEmpty()) {
25 | QMessageBox::warning(NULL,
26 | "warning",
27 | QString("请输入数据!"),
28 | QMessageBox::Close,
29 | QMessageBox::Close);
30 | return;
31 | }
32 | }
33 |
34 | if (!EVP_Q_digest(NULL, "SM3", NULL, input.toStdString().c_str(), input.size(), md, &mdlen)) {
35 | printTSError();
36 | return;
37 | }
38 |
39 | if (OPENSSL_buf2hexstr_ex((char *) hex, sizeof(hex), NULL, md, mdlen, '\0') != 1) {
40 | printTSError();
41 | return;
42 | }
43 |
44 | this->ui->textBrowserOutput->setText(
45 | QString::fromStdString(std::string((char *) hex, sizeof(hex))));
46 | }
47 |
--------------------------------------------------------------------------------
/sm2key.cpp:
--------------------------------------------------------------------------------
1 | #include "sm2key.h"
2 | #include "sm2.h"
3 | #include "ui_sm2key.h"
4 |
5 | Sm2Key::Sm2Key(QWidget *parent)
6 | : QWidget(parent)
7 | , ui(new Ui::Sm2Key)
8 | {
9 | ui->setupUi(this);
10 | }
11 |
12 | Sm2Key::~Sm2Key()
13 | {
14 | delete ui;
15 | }
16 |
17 | void Sm2Key::on_pushButtonGen_clicked()
18 | {
19 | EVP_PKEY *pkey = NULL;
20 | std::string pem, hex;
21 |
22 | pkey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
23 | if (pkey == NULL) {
24 | printTSError();
25 | goto end;
26 | }
27 |
28 | if (!sm2_key_get_priv_pem(pkey, pem)) {
29 | printTSError();
30 | goto end;
31 | }
32 |
33 | this->ui->textBrowserPrivPem->setText(QString::fromStdString(pem));
34 |
35 | if (!sm2_key_get_pub_pem(pkey, pem)) {
36 | printTSError();
37 | goto end;
38 | }
39 |
40 | this->ui->textBrowserPubPem->setText(QString::fromStdString(pem));
41 |
42 | if (!sm2_key_get_pub_hex(pkey, hex)) {
43 | printTSError();
44 | goto end;
45 | }
46 |
47 | this->ui->textBrowserPubkey->setText(QString::fromStdString(hex));
48 |
49 | if (!sm2_key_get_priv_hex(pkey, hex)) {
50 | printTSError();
51 | goto end;
52 | }
53 |
54 | this->ui->textBrowserPrivkey->setText(QString::fromStdString(hex));
55 |
56 | end:
57 | EVP_PKEY_free(pkey);
58 | return;
59 | }
60 |
--------------------------------------------------------------------------------
/randnum.cpp:
--------------------------------------------------------------------------------
1 | #include "randnum.h"
2 | #include "ui_randnum.h"
3 |
4 | RandNum::RandNum(QWidget *parent)
5 | : QWidget(parent)
6 | , ui(new Ui::RandNum)
7 | {
8 | ui->setupUi(this);
9 | /* 限制只能输入整数且范围为[1,128 * 1024]*/
10 | QIntValidator *aIntValidator = new QIntValidator;
11 | aIntValidator->setRange(1, 131072);
12 | ui->lineEditInput->setValidator(aIntValidator);
13 | }
14 |
15 | RandNum::~RandNum()
16 | {
17 | delete ui;
18 | }
19 |
20 | void RandNum::on_pushButtonGen_clicked()
21 | {
22 | QString inputByte = this->ui->lineEditInput->text();
23 | int randNumByte = inputByte.toInt();
24 | size_t len = randNumByte * 2 + 1;
25 | std::vector buf;
26 | std::vector str;
27 |
28 | buf.reserve(randNumByte);
29 |
30 | int ret = RAND_bytes((unsigned char *) buf.data(), randNumByte);
31 |
32 | if (ret == 0) {
33 | printTSError();
34 | } else {
35 | str.reserve(len);
36 |
37 | if (OPENSSL_buf2hexstr_ex(str.data(),
38 | len,
39 | NULL,
40 | (unsigned char *) buf.data(),
41 | randNumByte,
42 | '\0')
43 | != 1)
44 | return;
45 |
46 | this->ui->textBrowserOutput->setText(QString::fromStdString(std::string(str.data(), len)));
47 | }
48 |
49 | return;
50 | }
51 |
--------------------------------------------------------------------------------
/TongsuoToolbox_v01.pro:
--------------------------------------------------------------------------------
1 | QT += core gui
2 |
3 | QT += network
4 |
5 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
6 |
7 | CONFIG += c++17
8 |
9 | # You can make your code fail to compile if it uses deprecated APIs.
10 | # In order to do so, uncomment the following line.
11 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
12 |
13 | TARGET=tsapp
14 |
15 | SOURCES += \
16 | about.cpp \
17 | main.cpp \
18 | mainwindow.cpp \
19 | randnum.cpp \
20 | sm2.cpp \
21 | sm2cert.cpp \
22 | sm2encrypt.cpp \
23 | sm2key.cpp \
24 | sm2signverify.cpp \
25 | sm3hash.cpp \
26 | sm4encrypt.cpp \
27 | tlcpclient.cpp \
28 | tserror.cpp
29 |
30 | HEADERS += \
31 | about.h \
32 | mainwindow.h \
33 | randnum.h \
34 | sm2.h \
35 | sm2cert.h \
36 | sm2encrypt.h \
37 | sm2key.h \
38 | sm2signverify.h \
39 | sm3hash.h \
40 | sm4encrypt.h \
41 | tlcpclient.h \
42 | tserror.h \
43 | version.h
44 |
45 | # Default rules for deployment.
46 | target.path = $$(PREFIX)
47 | !isEmpty(target.path): INSTALLS += target
48 |
49 | win32: LIBS += -ladvapi32 -lcrypt32 -lgdi32 -luser32 -lws2_32 -L$$(TONGSUO_HOME)/lib -llibssl -llibcrypto
50 | else:unix: LIBS += -L$$(TONGSUO_HOME)/lib -lssl -lcrypto
51 |
52 | INCLUDEPATH += $$(TONGSUO_HOME)/include
53 | DEPENDPATH += $$(TONGSUO_HOME)/include
54 |
55 | win32-g++: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib/libcrypto.lib.a $$(TONGSUO_HOME)/lib/libssl.lib.a
56 | else:win32:!win32-g++: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib/libcrypto.lib $$(TONGSUO_HOME)/lib/libssl.lib
57 | else:unix: PRE_TARGETDEPS += $$(TONGSUO_HOME)/lib/libssl.a $$(TONGSUO_HOME)/lib/libcrypto.a
58 |
59 | FORMS += \
60 | about.ui \
61 | mainwindow.ui \
62 | randnum.ui \
63 | sm2cert.ui \
64 | sm2encrypt.ui \
65 | sm2key.ui \
66 | sm2signverify.ui \
67 | sm3hash.ui \
68 | sm4encrypt.ui \
69 | tlcpclient.ui
70 |
71 | RESOURCES += \
72 | certs.qrc
73 |
74 | DISTFILES +=
75 |
--------------------------------------------------------------------------------
/sm2key.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sm2Key
4 |
5 |
6 |
7 | 0
8 | 0
9 | 573
10 | 503
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
-
20 |
21 |
22 | -
23 |
24 |
25 | -
26 |
27 |
28 | SM2私钥(PEM)
29 |
30 |
31 |
32 | -
33 |
34 |
35 | SM2私钥
36 |
37 |
38 |
39 | -
40 |
41 |
42 | SM2公钥(x||y)
43 |
44 |
45 |
46 | -
47 |
48 |
49 | 生成密钥对
50 |
51 |
52 |
53 | -
54 |
55 |
56 | -
57 |
58 |
59 | SM2公钥(PEM)
60 |
61 |
62 |
63 | -
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/sm3hash.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sm3Hash
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
-
20 |
21 |
22 |
23 | 12
24 |
25 |
26 |
27 | 输入内容:
28 |
29 |
30 |
31 | -
32 |
33 |
34 |
35 | 12
36 |
37 |
38 |
39 | hex格式
40 |
41 |
42 |
43 | -
44 |
45 |
46 |
47 | 12
48 |
49 |
50 |
51 | hello SM3
52 |
53 |
54 |
55 | -
56 |
57 |
58 |
59 | 12
60 |
61 |
62 |
63 | 杂凑结果:
64 |
65 |
66 |
67 | -
68 |
69 |
70 |
71 | 12
72 |
73 |
74 |
75 | 生成
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/sm2encrypt.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sm2Encrypt
4 |
5 |
6 |
7 | 0
8 | 0
9 | 436
10 | 412
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
-
20 |
21 |
22 | hex格式
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 | hex格式
54 |
55 |
56 |
57 | -
58 |
59 |
60 | 公钥
61 |
62 |
63 |
64 | -
65 |
66 |
67 | hex格式
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 |
--------------------------------------------------------------------------------
/randnum.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | RandNum
4 |
5 |
6 |
7 | 0
8 | 0
9 | 740
10 | 531
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
-
20 |
21 |
22 | 生成随机数
23 |
24 |
25 |
26 | -
27 |
28 |
29 |
30 | 0
31 | 0
32 |
33 |
34 |
35 |
36 | 10
37 | 10
38 |
39 |
40 |
41 | 128
42 |
43 |
44 |
45 | -
46 |
47 |
48 | 字节
49 |
50 |
51 |
52 | -
53 |
54 |
55 | Qt::Horizontal
56 |
57 |
58 |
59 | 40
60 | 20
61 |
62 |
63 |
64 |
65 | -
66 |
67 |
68 | Qt::Horizontal
69 |
70 |
71 |
72 | 40
73 | 20
74 |
75 |
76 |
77 |
78 | -
79 |
80 |
81 | Qt::Vertical
82 |
83 |
84 |
85 | 20
86 | 40
87 |
88 |
89 |
90 |
91 | -
92 |
93 |
94 |
95 | 0
96 | 0
97 |
98 |
99 |
100 | hex格式
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | # clang-format >= 15
2 | ---
3 | Language: Cpp
4 | AccessModifierOffset: -4
5 | AlignAfterOpenBracket: Align
6 | AlignConsecutiveAssignments: false
7 | AlignConsecutiveDeclarations: false
8 | AlignEscapedNewlines: DontAlign
9 | AlignOperands: true
10 | AlignTrailingComments: true
11 | AllowAllParametersOfDeclarationOnNextLine: true
12 | AllowShortBlocksOnASingleLine: Never
13 | AllowShortCaseLabelsOnASingleLine: false
14 | AllowShortFunctionsOnASingleLine: Inline
15 | AllowShortIfStatementsOnASingleLine: false
16 | AllowShortLoopsOnASingleLine: false
17 | AlwaysBreakAfterReturnType: None
18 | AlwaysBreakBeforeMultilineStrings: false
19 | AlwaysBreakTemplateDeclarations: Yes
20 | BinPackArguments: false
21 | BinPackParameters: false
22 | BraceWrapping:
23 | AfterClass: true
24 | AfterControlStatement: Never
25 | AfterEnum: false
26 | AfterFunction: true
27 | AfterNamespace: false
28 | AfterObjCDeclaration: false
29 | AfterStruct: true
30 | AfterUnion: false
31 | BeforeCatch: false
32 | BeforeElse: false
33 | IndentBraces: false
34 | SplitEmptyFunction: false
35 | SplitEmptyRecord: false
36 | SplitEmptyNamespace: false
37 | BreakBeforeBinaryOperators: All
38 | BreakBeforeBraces: Custom
39 | BreakBeforeInheritanceComma: false
40 | BreakBeforeTernaryOperators: true
41 | BreakConstructorInitializersBeforeComma: false
42 | BreakConstructorInitializers: BeforeComma
43 | BreakAfterJavaFieldAnnotations: false
44 | BreakStringLiterals: true
45 | ColumnLimit: 100
46 | CommentPragmas: '^ IWYU pragma:'
47 | CompactNamespaces: false
48 | ConstructorInitializerAllOnOneLineOrOnePerLine: false
49 | ConstructorInitializerIndentWidth: 4
50 | ContinuationIndentWidth: 4
51 | Cpp11BracedListStyle: true
52 | DerivePointerAlignment: false
53 | DisableFormat: false
54 | ExperimentalAutoDetectBinPacking: false
55 | FixNamespaceComments: true
56 | ForEachMacros:
57 | - forever # avoids { wrapped to next line
58 | - foreach
59 | - Q_FOREACH
60 | - BOOST_FOREACH
61 | IncludeCategories:
62 | - Regex: '^
2 |
3 | About
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 300
11 |
12 |
13 |
14 | About tsapp
15 |
16 |
17 | -
18 |
19 |
20 | 关闭
21 |
22 |
23 |
24 | -
25 |
26 |
27 | Qt::Horizontal
28 |
29 |
30 |
31 | 40
32 | 20
33 |
34 |
35 |
36 |
37 | -
38 |
39 |
40 | About tsapp
41 |
42 |
43 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
44 | <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><title>About tsapp</title><style type="text/css">
45 | p, li { white-space: pre-wrap; }
46 | hr { height: 1px; border-width: 0; }
47 | li.unchecked::marker { content: "\2610"; }
48 | li.checked::marker { content: "\2612"; }
49 | </style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:13pt; font-weight:400; font-style:normal;">
50 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:18pt; font-weight:700;">铜锁密码工具箱(tsapp)|version|</span></p>
51 | <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>
52 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">铜锁密码工具箱(tsapp)基于铜锁密码库(<a href="https://github.com/Tongsuo-Project/Tongsuo"><span style=" text-decoration: underline; color:#094fd1;">https://github.com/Tongsuo-Project/Tongsuo</span></a>)提供的密码学能力开发的商用密码工具箱桌面应用程序。</p>
53 | <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>
54 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">图形用户界面基于Qt框架开发。</p>
55 | <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>
56 | <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">本项目地址<a href="https://github.com/Tongsuo-Project/tsapp"><span style=" text-decoration: underline; color:#094fd1;">https://github.com/Tongsuo-Project/tsapp</span></a>,欢迎提交issue和PR。</p></body></html>
57 |
58 |
59 | true
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/sm2signverify.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sm2SignVerify
4 |
5 |
6 |
7 | 0
8 | 0
9 | 390
10 | 318
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
-
20 |
21 |
22 |
23 | 12
24 |
25 |
26 |
27 | 待签名/验签数据:
28 |
29 |
30 |
31 | -
32 |
33 |
34 |
35 | 12
36 |
37 |
38 |
39 | 生成密钥对
40 |
41 |
42 |
43 | -
44 |
45 |
46 |
47 | 12
48 |
49 |
50 |
51 | 私钥:
52 |
53 |
54 |
55 | -
56 |
57 |
58 |
59 | 12
60 |
61 |
62 |
63 | hex格式
64 |
65 |
66 |
67 | -
68 |
69 |
70 |
71 | 12
72 |
73 |
74 |
75 | 公钥:
76 |
77 |
78 |
79 | -
80 |
81 |
82 |
83 | 12
84 |
85 |
86 |
87 | hex格式
88 |
89 |
90 |
91 | -
92 |
93 |
94 |
95 | 12
96 |
97 |
98 |
99 | 签名:
100 |
101 |
102 |
103 | -
104 |
105 |
106 |
107 | 12
108 |
109 |
110 |
111 | 生成签名
112 |
113 |
114 |
115 | -
116 |
117 |
118 |
119 | 12
120 |
121 |
122 |
123 | 验证签名
124 |
125 |
126 |
127 | -
128 |
129 |
130 | -
131 |
132 |
133 | hex格式
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 | 铜锁密码工具箱(tsapp)
15 |
16 |
17 |
18 | -
19 |
20 |
-
21 |
22 |
23 |
24 | 200
25 | 16777215
26 |
27 |
28 |
-
29 |
30 | 随机数生成
31 |
32 |
33 | -
34 |
35 | SM2密钥生成
36 |
37 |
38 | -
39 |
40 | SM2签名验签
41 |
42 |
43 | -
44 |
45 | SM2加解密
46 |
47 |
48 | -
49 |
50 | SM3杂凑
51 |
52 |
53 | -
54 |
55 | SM4加解密
56 |
57 |
58 | -
59 |
60 | 双证书签发
61 |
62 |
63 | -
64 |
65 | TLCP客户端
66 |
67 |
68 |
69 |
70 | -
71 |
72 |
73 | 0
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
108 |
109 |
110 |
111 | 关于tsapp
112 |
113 |
114 |
115 |
116 | 退出tsapp
117 |
118 |
119 |
120 |
121 |
122 | RandNum
123 | QWidget
124 |
125 | 1
126 |
127 |
128 | Sm2Key
129 | QWidget
130 |
131 | 1
132 |
133 |
134 | Sm2SignVerify
135 | QWidget
136 |
137 | 1
138 |
139 |
140 | Sm2Encrypt
141 | QWidget
142 |
143 | 1
144 |
145 |
146 | Sm3Hash
147 | QWidget
148 |
149 | 1
150 |
151 |
152 | Sm4encrypt
153 | QWidget
154 |
155 | 1
156 |
157 |
158 | Sm2Cert
159 | QWidget
160 |
161 | 1
162 |
163 |
164 | TLCPclient
165 | QWidget
166 |
167 | 1
168 |
169 |
170 |
171 |
172 |
173 |
--------------------------------------------------------------------------------
/sm2cert.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sm2Cert
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 314
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 |
21 | 10
22 |
23 |
24 |
25 |
26 | -
27 |
28 |
29 |
30 | 10
31 |
32 |
33 |
34 |
35 | -
36 |
37 |
38 | 0
39 |
40 |
-
41 |
42 |
43 |
44 | 12
45 |
46 |
47 |
48 |
49 |
50 |
51 | /C=AB/ST=CD/L=EF/O=GH/OU=IJ/CN=test
52 |
53 |
54 | 一般为域名
55 |
56 |
57 |
58 |
59 |
60 | -
61 |
62 |
63 |
64 | 10
65 |
66 |
67 |
68 |
69 | -
70 |
71 |
72 |
73 | 12
74 |
75 |
76 |
77 | 加密证书&私钥:
78 |
79 |
80 |
81 | -
82 |
83 |
84 |
85 | 10
86 |
87 |
88 |
89 |
90 | -
91 |
92 |
93 | Qt::Vertical
94 |
95 |
96 |
97 | 20
98 | 40
99 |
100 |
101 |
102 |
103 | -
104 |
105 |
106 |
107 | 12
108 |
109 |
110 |
111 | 有效天数:
112 |
113 |
114 |
115 | -
116 |
117 |
118 |
119 | 12
120 |
121 |
122 |
123 | 签名证书&私钥:
124 |
125 |
126 |
127 | -
128 |
129 |
130 | Qt::Vertical
131 |
132 |
133 |
134 | 20
135 | 40
136 |
137 |
138 |
139 |
140 | -
141 |
142 |
143 |
144 | 12
145 |
146 |
147 |
148 | 365
149 |
150 |
151 |
152 |
153 |
154 |
155 | -
156 |
157 |
158 |
159 | 12
160 |
161 |
162 |
163 | 主体名称:
164 |
165 |
166 |
167 | -
168 |
169 |
170 |
171 | 12
172 |
173 |
174 |
175 | 生成证书
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/sm2.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | EVP_PKEY *sm2_key_new_from_raw_pub(const std::string &pub)
5 | {
6 | std::string hex;
7 | std::vector buf;
8 | OSSL_PARAM_BLD *keybld = NULL;
9 | OSSL_PARAM *keyparams = NULL;
10 | EVP_PKEY_CTX *keyctx = NULL;
11 | EVP_PKEY *pkey = NULL;
12 |
13 | hex = std::string("04") + pub;
14 |
15 | keybld = OSSL_PARAM_BLD_new();
16 | if (keybld == NULL)
17 | goto end;
18 |
19 | buf.reserve(hex.length() / 2);
20 |
21 | if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, hex.c_str(), '\0') != 1)
22 | goto end;
23 |
24 | if (!OSSL_PARAM_BLD_push_utf8_string(keybld, OSSL_PKEY_PARAM_GROUP_NAME, "SM2", 3))
25 | goto end;
26 |
27 | if (!OSSL_PARAM_BLD_push_octet_string(keybld,
28 | OSSL_PKEY_PARAM_PUB_KEY,
29 | buf.data(),
30 | buf.capacity()))
31 | goto end;
32 |
33 | keyparams = OSSL_PARAM_BLD_to_param(keybld);
34 | keyctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL);
35 |
36 | if (keyctx == NULL || keyparams == NULL)
37 | goto end;
38 |
39 | if (EVP_PKEY_fromdata_init(keyctx) <= 0
40 | || EVP_PKEY_fromdata(keyctx, &pkey, EVP_PKEY_PUBLIC_KEY, keyparams) <= 0)
41 | goto end;
42 | end:
43 | EVP_PKEY_CTX_free(keyctx);
44 | OSSL_PARAM_free(keyparams);
45 | OSSL_PARAM_BLD_free(keybld);
46 | return pkey;
47 | }
48 |
49 | EVP_PKEY *sm2_key_new_from_raw_pub_and_priv(const std::string &pub, const std::string &priv)
50 | {
51 | std::string hex;
52 | std::vector buf;
53 | OSSL_PARAM_BLD *keybld = NULL;
54 | OSSL_PARAM *keyparams = NULL;
55 | EVP_PKEY_CTX *keyctx = NULL;
56 | EVP_PKEY *pkey = NULL;
57 | BIGNUM *bn = NULL;
58 |
59 | keybld = OSSL_PARAM_BLD_new();
60 | if (keybld == NULL)
61 | goto end;
62 |
63 | if (!OSSL_PARAM_BLD_push_utf8_string(keybld, OSSL_PKEY_PARAM_GROUP_NAME, "SM2", 3))
64 | goto end;
65 |
66 | buf.clear();
67 | buf.reserve(priv.length() / 2);
68 |
69 | if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, priv.c_str(), '\0') != 1)
70 | goto end;
71 |
72 | bn = BN_new();
73 | if (bn == NULL)
74 | goto end;
75 |
76 | if (BN_bin2bn(buf.data(), buf.capacity(), bn) == NULL
77 | || !OSSL_PARAM_BLD_push_BN(keybld, OSSL_PKEY_PARAM_PRIV_KEY, bn))
78 | goto end;
79 |
80 | hex = std::string("04") + pub;
81 |
82 | buf.clear();
83 | buf.reserve(hex.length() / 2);
84 |
85 | if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, hex.c_str(), '\0') != 1)
86 | goto end;
87 |
88 | if (!OSSL_PARAM_BLD_push_octet_string(keybld,
89 | OSSL_PKEY_PARAM_PUB_KEY,
90 | buf.data(),
91 | buf.capacity()))
92 | goto end;
93 |
94 | keyparams = OSSL_PARAM_BLD_to_param(keybld);
95 | keyctx = EVP_PKEY_CTX_new_from_name(NULL, "SM2", NULL);
96 |
97 | if (keyctx == NULL || keyparams == NULL)
98 | goto end;
99 |
100 | if (EVP_PKEY_fromdata_init(keyctx) <= 0
101 | || EVP_PKEY_fromdata(keyctx, &pkey, EVP_PKEY_KEYPAIR, keyparams) <= 0)
102 | goto end;
103 | end:
104 | BN_free(bn);
105 | EVP_PKEY_CTX_free(keyctx);
106 | OSSL_PARAM_free(keyparams);
107 | OSSL_PARAM_BLD_free(keybld);
108 | return pkey;
109 | }
110 |
111 | int sm2_key_get_priv_pem(const EVP_PKEY *pkey, std::string &pem)
112 | {
113 | int ret = 0;
114 | BIO *out = NULL;
115 | long len;
116 | char *buf = NULL;
117 |
118 | out = BIO_new(BIO_s_mem());
119 | if (out == NULL)
120 | goto end;
121 |
122 | if (!PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, NULL))
123 | goto end;
124 |
125 | len = BIO_get_mem_data(out, &buf);
126 |
127 | pem = std::string(buf, len);
128 |
129 | ret = 1;
130 | end:
131 | BIO_free(out);
132 | return ret;
133 | }
134 |
135 | int sm2_key_get_pub_pem(const EVP_PKEY *pkey, std::string &pem)
136 | {
137 | int ret = 0;
138 | BIO *out = NULL;
139 | long len;
140 | char *buf = NULL;
141 |
142 | out = BIO_new(BIO_s_mem());
143 | if (out == NULL)
144 | goto end;
145 |
146 | if (!PEM_write_bio_PUBKEY(out, pkey))
147 | goto end;
148 |
149 | len = BIO_get_mem_data(out, &buf);
150 |
151 | pem = std::string(buf, len);
152 |
153 | ret = 1;
154 | end:
155 | BIO_free(out);
156 | return ret;
157 | }
158 |
159 | int sm2_key_get_pub_hex(const EVP_PKEY *pkey, std::string &hex)
160 | {
161 | BIGNUM *qx = NULL, *qy = NULL;
162 | char *pubx = NULL, *puby = NULL;
163 |
164 | if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &qx)
165 | || !EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &qy))
166 | return 0;
167 |
168 | pubx = BN_bn2hex(qx);
169 | puby = BN_bn2hex(qy);
170 |
171 | hex = std::string(pubx) + std::string(puby);
172 |
173 | BN_clear_free(qx);
174 | BN_clear_free(qy);
175 | OPENSSL_free(pubx);
176 | OPENSSL_free(puby);
177 |
178 | return 1;
179 | }
180 |
181 | int sm2_key_get_priv_hex(const EVP_PKEY *pkey, std::string &hex)
182 | {
183 | BIGNUM *priv = NULL;
184 | char *buf = NULL;
185 |
186 | if (!EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv))
187 | return 0;
188 |
189 | buf = BN_bn2hex(priv);
190 |
191 | hex = std::string(buf);
192 |
193 | OPENSSL_free(buf);
194 | BN_clear_free(priv);
195 |
196 | return 1;
197 | }
198 |
--------------------------------------------------------------------------------
/sm2encrypt.cpp:
--------------------------------------------------------------------------------
1 | #include "sm2encrypt.h"
2 | #include "sm2.h"
3 | #include "ui_sm2encrypt.h"
4 |
5 | Sm2Encrypt::Sm2Encrypt(QWidget *parent)
6 | : QWidget(parent)
7 | , ui(new Ui::Sm2Encrypt)
8 | {
9 | ui->setupUi(this);
10 | }
11 |
12 | Sm2Encrypt::~Sm2Encrypt()
13 | {
14 | delete ui;
15 | }
16 |
17 | void Sm2Encrypt::on_pushButtonEncrypt_clicked()
18 | {
19 | QString input = this->ui->textEditPlain->toPlainText();
20 | QString pubQstrInput = this->ui->plainTextEditPub->toPlainText();
21 | EVP_PKEY_CTX *encctx = NULL;
22 | EVP_PKEY *pkey = NULL;
23 | size_t outlen;
24 | std::vector buf;
25 | std::vector str;
26 |
27 | if (pubQstrInput.isEmpty()) {
28 | QMessageBox::warning(NULL,
29 | "warning",
30 | QString("请输入公钥!"),
31 | QMessageBox::Close,
32 | QMessageBox::Close);
33 | return;
34 | }
35 |
36 | if (input.isEmpty()) {
37 | QMessageBox::warning(NULL,
38 | "warning",
39 | QString("请输入明文!"),
40 | QMessageBox::Close,
41 | QMessageBox::Close);
42 | return;
43 | }
44 |
45 | pkey = sm2_key_new_from_raw_pub(pubQstrInput.toStdString());
46 | if (pkey == NULL) {
47 | printTSError();
48 | goto end;
49 | }
50 |
51 | encctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
52 | if (encctx == NULL)
53 | goto end;
54 |
55 | if (EVP_PKEY_encrypt_init(encctx) <= 0
56 | || EVP_PKEY_encrypt(encctx,
57 | NULL,
58 | &outlen,
59 | (const unsigned char *) input.toStdString().c_str(),
60 | input.toStdString().length())
61 | <= 0)
62 | goto end;
63 |
64 | buf.clear();
65 | buf.reserve(outlen);
66 |
67 | if (EVP_PKEY_encrypt(encctx,
68 | buf.data(),
69 | &outlen,
70 | (const unsigned char *) input.toStdString().c_str(),
71 | input.toStdString().length())
72 | <= 0)
73 | goto end;
74 |
75 | str.reserve(outlen * 2 + 1);
76 | if (OPENSSL_buf2hexstr_ex(str.data(), str.capacity(), NULL, buf.data(), outlen, '\0') != 1) {
77 | printTSError();
78 | goto end;
79 | }
80 |
81 | this->ui->textEditCipher->setText(QString::fromStdString(std::string(str.data(), outlen * 2)));
82 |
83 | end:
84 | EVP_PKEY_free(pkey);
85 | }
86 |
87 | void Sm2Encrypt::on_pushButtonDecrypt_clicked()
88 | {
89 | QString input = this->ui->textEditCipher->toPlainText();
90 | QString pubQstrInput = this->ui->plainTextEditPub->toPlainText();
91 | QString privQstrInput = this->ui->plainTextEditPriv->toPlainText();
92 | EVP_PKEY_CTX *encctx = NULL;
93 | EVP_PKEY *pkey = NULL;
94 | size_t outlen;
95 | std::vector buf;
96 | std::vector str;
97 |
98 | if (pubQstrInput.isEmpty() || privQstrInput.isEmpty()) {
99 | QMessageBox::warning(NULL,
100 | "warning",
101 | QString("请输入公钥和私钥!"),
102 | QMessageBox::Close,
103 | QMessageBox::Close);
104 | return;
105 | }
106 |
107 | if (input.isEmpty()) {
108 | QMessageBox::warning(NULL,
109 | "warning",
110 | QString("请输入密文!"),
111 | QMessageBox::Close,
112 | QMessageBox::Close);
113 | return;
114 | }
115 |
116 | pkey = sm2_key_new_from_raw_pub_and_priv(pubQstrInput.toStdString(),
117 | privQstrInput.toStdString());
118 | if (pkey == NULL) {
119 | printTSError();
120 | goto end;
121 | }
122 |
123 | encctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
124 | if (encctx == NULL)
125 | goto end;
126 |
127 | buf.clear();
128 | buf.reserve(input.length() / 2);
129 |
130 | if (OPENSSL_hexstr2buf_ex(buf.data(), buf.capacity(), NULL, input.toStdString().c_str(), '\0')
131 | != 1) {
132 | printTSError();
133 | goto end;
134 | }
135 |
136 | if (EVP_PKEY_decrypt_init(encctx) <= 0
137 | || EVP_PKEY_decrypt(encctx, NULL, &outlen, buf.data(), buf.capacity()) <= 0)
138 | goto end;
139 |
140 | str.clear();
141 | str.reserve(outlen);
142 |
143 | if (EVP_PKEY_decrypt(encctx, (unsigned char *) str.data(), &outlen, buf.data(), buf.capacity())
144 | <= 0)
145 | goto end;
146 |
147 | this->ui->textEditPlain->setText(QString::fromStdString(std::string(str.data(), outlen)));
148 |
149 | end:
150 | EVP_PKEY_free(pkey);
151 | }
152 |
153 | void Sm2Encrypt::on_pushButtonGen_clicked()
154 | {
155 | EVP_PKEY *pkey = NULL;
156 | std::string hex;
157 |
158 | pkey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
159 | if (pkey == NULL) {
160 | printTSError();
161 | goto end;
162 | }
163 |
164 | if (!sm2_key_get_pub_hex(pkey, hex)) {
165 | printTSError();
166 | goto end;
167 | }
168 |
169 | this->ui->plainTextEditPub->setPlainText(QString::fromStdString(hex));
170 |
171 | if (!sm2_key_get_priv_hex(pkey, hex)) {
172 | printTSError();
173 | goto end;
174 | }
175 |
176 | this->ui->plainTextEditPriv->setPlainText(QString::fromStdString(hex));
177 |
178 | end:
179 | EVP_PKEY_free(pkey);
180 | return;
181 | }
182 |
--------------------------------------------------------------------------------
/tlcpclient.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | TLCPclient
4 |
5 |
6 |
7 | 0
8 | 0
9 | 434
10 | 426
11 |
12 |
13 |
14 | Form
15 |
16 |
17 |
18 | QLayout::SetMinimumSize
19 |
20 | -
21 |
22 |
23 |
24 | 12
25 |
26 |
27 |
28 | 接收数据:
29 |
30 |
31 |
32 | -
33 |
34 |
35 |
36 | 12
37 |
38 |
39 |
40 | 发送数据:
41 |
42 |
43 |
44 | -
45 |
46 |
47 |
48 | 12
49 |
50 |
51 |
52 | 127.0.0.1
53 |
54 |
55 | IP地址
56 |
57 |
58 |
59 | -
60 |
61 |
62 | 调试信息输出
63 |
64 |
65 |
66 | -
67 |
68 |
69 | -
70 |
71 |
72 |
73 | Academy Engraved LET
74 | 13
75 |
76 |
77 |
78 | 服务器地址:
79 |
80 |
81 |
82 | -
83 |
84 |
85 |
86 | 0
87 | 0
88 |
89 |
90 |
91 |
92 | 12
93 |
94 |
95 |
96 | 443
97 |
98 |
99 | 端口号
100 |
101 |
102 |
103 | -
104 |
105 |
106 |
107 | 12
108 |
109 |
110 |
111 | 连接服务器
112 |
113 |
114 |
115 | -
116 |
117 |
118 |
119 | 12
120 |
121 |
122 |
123 | 发送
124 |
125 |
126 |
127 | -
128 |
129 |
130 |
131 | 12
132 |
133 |
134 |
135 | GET / HTTP/1.0
136 |
137 |
138 |
139 |
140 |
141 | -
142 |
143 |
144 |
145 | 12
146 |
147 |
148 |
149 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
150 | <html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css">
151 | p, li { white-space: pre-wrap; }
152 | hr { height: 1px; border-width: 0; }
153 | li.unchecked::marker { content: "\2610"; }
154 | li.checked::marker { content: "\2612"; }
155 | </style></head><body style=" font-family:'.AppleSystemUIFont'; font-size:12pt; font-weight:400; font-style:normal;">
156 | <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>
157 |
158 |
159 |
160 | -
161 |
162 |
163 | ECC-SM2-SM4-CBC-SM3
164 |
165 |
166 |
167 | -
168 |
169 |
170 | 密码套件:
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: release
2 |
3 | on:
4 | workflow_dispatch:
5 | tags:
6 | - '*'
7 | env:
8 | TONGSUO_VERSION: 8.4.0
9 |
10 | permissions:
11 | contents: write
12 |
13 | jobs:
14 | new_release:
15 | runs-on: ubuntu-latest
16 | outputs:
17 | upload_url: ${{ steps.create_release.outputs.upload_url }}
18 | steps:
19 | - name: Create Release
20 | id: create_release
21 | uses: actions/create-release@v1
22 | env:
23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
24 | with:
25 | tag_name: ${{ github.ref }}
26 | release_name: Release ${{ github.ref }}
27 | body: |
28 | Changes in this Release
29 | - First Change
30 | - Second Change
31 | draft: true
32 | prerelease: true
33 |
34 | build_linux_macos:
35 | runs-on: ${{ matrix.os}}
36 | needs: [new_release]
37 | strategy:
38 | matrix:
39 | os: [macos-latest, ubuntu-20.04]
40 | name: "build-${{ matrix.os }}"
41 | steps:
42 | - name: build Tongsuo
43 | run: |
44 | wget "https://github.com/Tongsuo-Project/Tongsuo/archive/refs/tags/${TONGSUO_VERSION}.tar.gz"
45 | tar zxf "${TONGSUO_VERSION}.tar.gz"
46 | pushd "Tongsuo-${TONGSUO_VERSION}"
47 | ./config --prefix=${RUNNER_TEMP}/tongsuo --libdir=${RUNNER_TEMP}/tongsuo/lib no-shared no-dso enable-ntls --release
48 | make -s -j4
49 | make install
50 | popd
51 | - uses: actions/checkout@v3
52 | - name: install QT
53 | uses: jurplel/install-qt-action@v4
54 | with:
55 | version: 6.5.3
56 |
57 | - name: build tsapp
58 | run: |
59 | TONGSUO_HOME=${RUNNER_TEMP}/tongsuo PREFIX=${RUNNER_TEMP}/tsapp qmake
60 | make -s -j4
61 | make install
62 | find ${RUNNER_TEMP}/tsapp
63 |
64 | - name: package for macos
65 | run: |
66 | macdeployqt tsapp.app -qmldir=. -verbose=1 -dmg
67 | if: ${{ matrix.os == 'macos-latest' }}
68 |
69 | - name: upload artifact for macos
70 | uses: actions/upload-release-asset@v1
71 | env:
72 | GITHUB_TOKEN: ${{ github.token }}
73 | with:
74 | upload_url: ${{ needs.new_release.outputs.upload_url }}
75 | asset_path: tsapp.dmg
76 | asset_name: tsapp-${{ runner.os }}.dmg
77 | asset_content_type: application/octet-stream
78 | if: ${{ matrix.os == 'macos-latest' }}
79 |
80 | - name: install linuxdeployqt and package for linux
81 | run: |
82 | wget https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
83 | chmod +x linuxdeployqt-continuous-x86_64.AppImage
84 | cp linuxdeployqt-continuous-x86_64.AppImage /usr/local/bin/linuxdeployqt
85 | mkdir -p ${RUNNER_TEMP}/Install/tsapp/
86 | cp ${RUNNER_TEMP}/tsapp/tsapp ${RUNNER_TEMP}/Install/tsapp/
87 | cd ${RUNNER_TEMP}/Install/tsapp/
88 | linuxdeployqt tsapp -appimage -no-copy-copyright-files -no-plugins -no-translations || echo
89 | cd ..
90 | tar czf tsapp.tgz tsapp
91 | if: ${{ matrix.os == 'ubuntu-20.04' }}
92 |
93 | - name: upload artifact for linux
94 | uses: actions/upload-release-asset@v1
95 | env:
96 | GITHUB_TOKEN: ${{ github.token }}
97 | with:
98 | upload_url: ${{ needs.new_release.outputs.upload_url }}
99 | asset_path: ${{ runner.temp }}/Install/tsapp.tgz
100 | asset_name: tsapp-${{ runner.os }}.tgz
101 | asset_content_type: application/x-compressed-tar
102 | if: ${{ matrix.os == 'ubuntu-20.04' }}
103 |
104 | build_windows:
105 | runs-on: windows-latest
106 | needs: [new_release]
107 | steps:
108 | - run: choco install -y winrar
109 | - uses: ilammy/msvc-dev-cmd@v1
110 | with:
111 | arch: win64
112 | - uses: ilammy/setup-nasm@v1
113 | with:
114 | platform: win64
115 | - uses: shogo82148/actions-setup-perl@v1
116 | - name: Download Tongsuo source
117 | run: |
118 | wget "https://github.com/Tongsuo-Project/Tongsuo/archive/refs/tags/${env:TONGSUO_VERSION}.tar.gz" -OutFile "${env:TONGSUO_VERSION}.tar.gz"
119 | shell: powershell
120 | - run: |
121 | "C:\Program Files\WinRAR\WinRAR.exe" -INUL x %TONGSUO_VERSION%.tar.gz
122 | shell: cmd
123 | - name: build Tongsuo
124 | shell: cmd
125 | run: |
126 | pushd "Tongsuo-%TONGSUO_VERSION%"
127 | mkdir _build
128 | pushd _build
129 | perl ..\Configure no-makedepend no-shared enable-ntls VC-WIN64A --prefix=%RUNNER_TEMP%\tongsuo
130 | nmake /S
131 | nmake install_sw
132 | popd
133 | popd
134 | - uses: actions/checkout@v3
135 | - name: install QT
136 | uses: jurplel/install-qt-action@v4
137 | with:
138 | version: 6.5.3
139 |
140 | - name: build tsapp
141 | shell: cmd
142 | run: |
143 | set TONGSUO_HOME=%RUNNER_TEMP%\tongsuo
144 | set PREFIX=%RUNNER_TEMP%\tsapp
145 | qmake
146 | nmake /S
147 | nmake install
148 |
149 | - name: package
150 | shell: cmd
151 | run: |
152 | set PKG_DIR=tsapp-WIN64
153 | mkdir %PKG_DIR%
154 | cp %RUNNER_TEMP%\tsapp\tsapp.exe %PKG_DIR%\
155 | windeployqt --qmldir . %PKG_DIR%\tsapp.exe
156 | "C:\Program Files\WinRAR\WinRAR.exe" a tsapp.zip %PKG_DIR%\
157 | cd
158 | dir
159 |
160 | - name: upload artifact
161 | uses: actions/upload-release-asset@v1
162 | env:
163 | GITHUB_TOKEN: ${{ github.token }}
164 | with:
165 | upload_url: ${{ needs.new_release.outputs.upload_url }}
166 | asset_path: ${{ github.workspace }}\tsapp.zip
167 | asset_name: tsapp-${{ runner.os }}.zip
168 | asset_content_type: application/zip
169 |
170 |
--------------------------------------------------------------------------------
/tlcpclient.cpp:
--------------------------------------------------------------------------------
1 | #include "tlcpclient.h"
2 | #include "ui_tlcpclient.h"
3 |
4 | TLCPclient::TLCPclient(QWidget *parent)
5 | : QWidget(parent)
6 | , ui(new Ui::TLCPclient)
7 | {
8 | ui->setupUi(this);
9 | ui->pushButtonSend->setEnabled(false);
10 | }
11 |
12 | TLCPclient::~TLCPclient()
13 | {
14 | delete ui;
15 | SSL_free(ssl);
16 | ssl = NULL;
17 | SSL_CTX_free(ctx);
18 | ctx = NULL;
19 | socket.close();
20 | }
21 |
22 | void TLCPclient::on_pushButtonConnect_clicked()
23 | {
24 | int ret, err;
25 |
26 | if (ui->pushButtonConnect->text() == "连接服务器") {
27 | //获取域名端口
28 | QString addrQstr = this->ui->lineEditAddr->text();
29 | QString portQstr = this->ui->lineEditPort->text();
30 | QString cipherList = this->ui->lineEditCiphers->text();
31 | // 创建一个 QSslSocket对象设置地址并连接
32 |
33 | this->socket.reset();
34 | this->socket.connectToHost(addrQstr, portQstr.toInt());
35 | if (!this->socket.waitForConnected()) {
36 | QMessageBox::warning(NULL,
37 | "connect failed",
38 | QString("TCP连接失败,请确认服务器地址&端口号是否正确"),
39 | QMessageBox::Ok,
40 | QMessageBox::Ok);
41 | return;
42 | }
43 |
44 | //TCP已连接,准备SSL连接
45 | if (this->ctx == NULL) {
46 | this->ctx = SSL_CTX_new(NTLS_client_method());
47 | if (this->ctx == NULL) {
48 | return;
49 | }
50 |
51 | SSL_CTX_enable_ntls(this->ctx);
52 | SSL_CTX_set_verify(this->ctx, SSL_VERIFY_NONE, NULL);
53 | }
54 |
55 | if (SSL_CTX_set_cipher_list(this->ctx, cipherList.toStdString().c_str()) != 1) {
56 | QMessageBox::warning(NULL,
57 | "set cipher list failed",
58 | QString("设置密码套件失败,请确认套件格式是否正确"),
59 | QMessageBox::Ok,
60 | QMessageBox::Ok);
61 | return;
62 | }
63 |
64 | SSL_free(this->ssl);
65 | this->ssl = SSL_new(this->ctx);
66 | SSL_set_fd(ssl, this->socket.socketDescriptor());
67 |
68 | if (BIO_socket_nbio(this->socket.socketDescriptor(), 0) != 1) {
69 | QMessageBox::warning(NULL,
70 | "set blocking failed",
71 | QString("设置阻塞模式失败"),
72 | QMessageBox::Ok,
73 | QMessageBox::Ok);
74 | return;
75 | }
76 |
77 | ret = SSL_connect(this->ssl);
78 | if (ret == 1) {
79 | //SSL连接成功
80 | ui->pushButtonConnect->setText("断开服务器");
81 |
82 | this->ui->textBrowserDebug->append(QString("TLCP握手成功\n"));
83 |
84 | ui->pushButtonSend->setEnabled(true);
85 | } else {
86 | err = SSL_get_error(this->ssl, ret);
87 |
88 | //SSL连接失败
89 | SSL_shutdown(this->ssl);
90 | QMessageBox::warning(NULL,
91 | "connect failed",
92 | QString("TLCP连接失败,err:%1").arg(err),
93 | QMessageBox::Ok,
94 | QMessageBox::Ok);
95 | return;
96 | }
97 | } else {
98 | ui->pushButtonConnect->setText("连接服务器");
99 | ui->pushButtonSend->setEnabled(false);
100 | if (this->ssl != NULL) {
101 | SSL_shutdown(this->ssl);
102 | }
103 |
104 | this->ui->textBrowserDebug->append(QString("客户端关闭连接\n"));
105 | }
106 | }
107 |
108 | void TLCPclient::on_pushButtonSend_clicked()
109 | {
110 | // SSL_set_msg_callback(ssl, trace_cb);
111 | //获取发送内容
112 | QString inputQstr = this->ui->plainTextEditInput->toPlainText();
113 | int ret = SSL_write(this->ssl, inputQstr.toStdString().c_str(), inputQstr.size());
114 | if (ret < 0) {
115 | int err = SSL_get_error(this->ssl, ret);
116 |
117 | if (err == SSL_ERROR_SYSCALL && !socket.isOpen()) {
118 | QMessageBox::warning(NULL,
119 | "write failed",
120 | QString("TLCP发送数据失败,服务端已经关闭连接"),
121 | QMessageBox::Ok,
122 | QMessageBox::Ok);
123 | return;
124 | } else {
125 | QMessageBox::warning(NULL,
126 | "write failed",
127 | QString("TLCP发送数据失败,err:%1").arg(err),
128 | QMessageBox::Ok,
129 | QMessageBox::Ok);
130 | //发送失败
131 | // getError();
132 | return;
133 | }
134 | } else {
135 | this->ui->textBrowserDebug->append(QString(">>>:\n") + inputQstr + QString("\n"));
136 | }
137 |
138 | char rxbuf[16384] = {0};
139 | ret = SSL_read(this->ssl, rxbuf, sizeof(rxbuf));
140 | if (ret < 0) {
141 | int err = SSL_get_error(this->ssl, ret);
142 |
143 | QMessageBox::warning(NULL,
144 | "read failed",
145 | QString("读失败,err:%1").arg(err),
146 | QMessageBox::Ok,
147 | QMessageBox::Ok);
148 | return;
149 | } else {
150 | // 输出到接收
151 | this->ui->textBrowserOutput->setText(QString::asprintf("%s", rxbuf));
152 |
153 | this->ui->textBrowserDebug->append(QString("<<<:\n") + QString::asprintf("%s", rxbuf)
154 | + QString("\n"));
155 | }
156 | }
157 |
158 | void TLCPclient::trace_cb(
159 | int write_p, int version, int content_type, const void *buf, size_t msglen, SSL *ssl, void *arg)
160 | {
161 | std::shared_ptr bio(BIO_new(BIO_s_mem()), BIO_free);
162 | arg = bio.get();
163 | SSL_trace(write_p, version, content_type, buf, msglen, ssl, arg);
164 | int len = BIO_pending((BIO *) arg);
165 | char argbuf[1024] = {};
166 | BIO_read((BIO *) arg, argbuf, len);
167 | }
168 |
--------------------------------------------------------------------------------
/sm4encrypt.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | Sm4encrypt
4 |
5 |
6 |
7 | 0
8 | 0
9 | 400
10 | 329
11 |
12 |
13 |
14 | Form
15 |
16 |
17 | -
18 |
19 |
20 |
21 | 12
22 |
23 |
24 |
-
25 |
26 | SM4-CBC
27 |
28 |
29 | -
30 |
31 | SM4-ECB
32 |
33 |
34 | -
35 |
36 | SM4-CFB
37 |
38 |
39 | -
40 |
41 | SM4-OFB
42 |
43 |
44 | -
45 |
46 | SM4-CTR
47 |
48 |
49 |
50 |
51 | -
52 |
53 |
54 |
55 | 12
56 |
57 |
58 |
59 | 明文:
60 |
61 |
62 |
63 | -
64 |
65 |
66 |
67 | 12
68 |
69 |
70 |
71 | hello tongsuo
72 |
73 |
74 |
75 | -
76 |
77 |
78 |
79 | 12
80 |
81 |
82 |
83 | 加密模式:
84 |
85 |
86 |
87 | -
88 |
89 |
90 |
91 | 12
92 |
93 |
94 |
95 |
96 |
97 |
98 | hex格式
99 |
100 |
101 |
102 | -
103 |
104 |
105 |
106 | 12
107 |
108 |
109 |
110 | 初始化向量:
111 |
112 |
113 |
114 | -
115 |
116 |
117 |
118 | 12
119 |
120 |
121 |
122 | 密文:
123 |
124 |
125 |
126 | -
127 |
128 |
-
129 |
130 |
131 |
132 | 12
133 |
134 |
135 |
136 | 解密
137 |
138 |
139 |
140 |
141 |
142 | -
143 |
144 |
145 | -
146 |
147 |
148 | Qt::Vertical
149 |
150 |
151 |
152 | 20
153 | 40
154 |
155 |
156 |
157 |
158 | -
159 |
160 |
161 |
162 | 12
163 |
164 |
165 |
166 | 密钥:
167 |
168 |
169 |
170 | -
171 |
172 |
173 |
174 | 12
175 |
176 |
177 |
178 |
179 |
180 |
181 | hex格式
182 |
183 |
184 |
185 | -
186 |
187 |
188 |
189 | 12
190 |
191 |
192 |
193 | 加密
194 |
195 |
196 |
197 | -
198 |
199 |
200 | hex格式
201 |
202 |
203 |
204 | -
205 |
206 |
207 | 随机
208 |
209 |
210 |
211 | -
212 |
213 |
214 | 随机
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
--------------------------------------------------------------------------------
/sm2signverify.cpp:
--------------------------------------------------------------------------------
1 | #include "sm2signverify.h"
2 | #include "sm2.h"
3 | #include "ui_sm2signverify.h"
4 |
5 | Sm2SignVerify::Sm2SignVerify(QWidget *parent)
6 | : QWidget(parent)
7 | , ui(new Ui::Sm2SignVerify)
8 | {
9 | ui->setupUi(this);
10 | }
11 |
12 | Sm2SignVerify::~Sm2SignVerify()
13 | {
14 | delete ui;
15 | }
16 |
17 | void Sm2SignVerify::on_pushButtonGenKey_clicked()
18 | {
19 | EVP_PKEY *pkey = NULL;
20 | std::string hex;
21 |
22 | pkey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
23 | if (pkey == NULL) {
24 | printTSError();
25 | goto end;
26 | }
27 |
28 | if (!sm2_key_get_pub_hex(pkey, hex)) {
29 | printTSError();
30 | goto end;
31 | }
32 |
33 | this->ui->plainTextEditPubKey->setPlainText(QString::fromStdString(hex));
34 |
35 | if (!sm2_key_get_priv_hex(pkey, hex)) {
36 | printTSError();
37 | goto end;
38 | }
39 |
40 | this->ui->lineEditPriKey->setText(QString::fromStdString(hex));
41 |
42 | end:
43 | EVP_PKEY_free(pkey);
44 | return;
45 | }
46 |
47 | void Sm2SignVerify::on_pushButtonSign_clicked()
48 | {
49 | /* 获取私钥 */
50 | QString pubQstr = this->ui->plainTextEditPubKey->toPlainText();
51 | QString priQstr = this->ui->lineEditPriKey->text();
52 | QString inputQstr = this->ui->textEditData->toPlainText();
53 | EVP_PKEY *pkey = NULL;
54 | EVP_MD_CTX *mctx = NULL;
55 | size_t siglen = 0;
56 | std::vector sig;
57 | std::vector str;
58 |
59 | if (priQstr.isEmpty()) {
60 | QMessageBox::warning(NULL,
61 | "warning",
62 | QString("请输入或生成私钥!"),
63 | QMessageBox::Close,
64 | QMessageBox::Close);
65 | return;
66 | }
67 |
68 | if (inputQstr.isEmpty()) {
69 | QMessageBox::warning(NULL,
70 | "warning",
71 | QString("请输入待签名数据!"),
72 | QMessageBox::Close,
73 | QMessageBox::Close);
74 | return;
75 | }
76 |
77 | pkey = sm2_key_new_from_raw_pub_and_priv(pubQstr.toStdString(), priQstr.toStdString());
78 | if (pkey == NULL) {
79 | printTSError();
80 | return;
81 | }
82 |
83 | mctx = EVP_MD_CTX_new();
84 | if (mctx == NULL)
85 | goto end;
86 |
87 | if (!EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, pkey)
88 | || !EVP_DigestSign(mctx,
89 | NULL,
90 | &siglen,
91 | (unsigned char *) inputQstr.toStdString().c_str(),
92 | inputQstr.size())) {
93 | printTSError();
94 | goto end;
95 | }
96 |
97 | sig.reserve(siglen);
98 |
99 | if (EVP_DigestSign(mctx,
100 | sig.data(),
101 | &siglen,
102 | (unsigned char *) inputQstr.toStdString().c_str(),
103 | inputQstr.size())
104 | != 1) {
105 | printTSError();
106 | goto end;
107 | }
108 |
109 | str.reserve(siglen * 2 + 1);
110 |
111 | if (OPENSSL_buf2hexstr_ex(str.data(), str.capacity(), NULL, sig.data(), siglen, '\0') != 1) {
112 | printTSError();
113 | goto end;
114 | }
115 |
116 | this->ui->plainTextEditSign->setPlainText(
117 | QString::fromStdString(std::string(str.data(), str.capacity())));
118 | end:
119 | EVP_MD_CTX_free(mctx);
120 | EVP_PKEY_free(pkey);
121 | return;
122 | }
123 |
124 | void Sm2SignVerify::on_pushButtonVerify_clicked()
125 | {
126 | QString pubQstrInput = this->ui->plainTextEditPubKey->toPlainText();
127 | QString inputQstr = this->ui->textEditData->toPlainText();
128 | QString signQstr = this->ui->plainTextEditSign->toPlainText();
129 | std::vector sig;
130 | EVP_PKEY *pkey = NULL;
131 | EVP_MD_CTX *mctx = NULL;
132 | int ret;
133 |
134 | if (pubQstrInput.isEmpty()) {
135 | QMessageBox::warning(NULL,
136 | "warning",
137 | QString("请输入公钥!"),
138 | QMessageBox::Close,
139 | QMessageBox::Close);
140 | return;
141 | }
142 |
143 | if (signQstr.isEmpty()) {
144 | QMessageBox::warning(NULL,
145 | "warning",
146 | QString("请输入签名!"),
147 | QMessageBox::Close,
148 | QMessageBox::Close);
149 | return;
150 | }
151 |
152 | sig.reserve(signQstr.size() / 2);
153 |
154 | if (OPENSSL_hexstr2buf_ex(sig.data(), sig.capacity(), NULL, signQstr.toStdString().c_str(), '\0')
155 | != 1) {
156 | printTSError();
157 | goto end;
158 | }
159 |
160 | pkey = sm2_key_new_from_raw_pub(pubQstrInput.toStdString());
161 | if (pkey == NULL) {
162 | printTSError();
163 | goto end;
164 | }
165 |
166 | mctx = EVP_MD_CTX_new();
167 | if (mctx == NULL)
168 | goto end;
169 |
170 | if (!EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey)) {
171 | printTSError();
172 | goto end;
173 | }
174 | /* 验签 */
175 | ret = EVP_DigestVerify(mctx,
176 | sig.data(),
177 | sig.capacity(),
178 | (unsigned char *) inputQstr.toStdString().c_str(),
179 | inputQstr.size());
180 | if (ret == 1) {
181 | QMessageBox::information(NULL,
182 | "success",
183 | QString("验签成功!"),
184 | QMessageBox::Close,
185 | QMessageBox::Close);
186 | } else if (ret == 0) {
187 | QMessageBox::warning(NULL,
188 | "failed",
189 | QString("验签失败!"),
190 | QMessageBox::Close,
191 | QMessageBox::Close);
192 | } else {
193 | getError();
194 | return;
195 | }
196 | end:
197 | EVP_MD_CTX_free(mctx);
198 | EVP_PKEY_free(pkey);
199 | return;
200 | }
201 |
--------------------------------------------------------------------------------
/sm4encrypt.cpp:
--------------------------------------------------------------------------------
1 | #include "sm4encrypt.h"
2 | #include "ui_sm4encrypt.h"
3 | #include
4 |
5 | Sm4encrypt::Sm4encrypt(QWidget *parent)
6 | : QWidget(parent)
7 | , ui(new Ui::Sm4encrypt)
8 | {
9 | ui->setupUi(this);
10 | }
11 |
12 | Sm4encrypt::~Sm4encrypt()
13 | {
14 | delete ui;
15 | }
16 |
17 | static int do_sm4_crypt(const char *algo,
18 | int enc,
19 | const unsigned char *key,
20 | const unsigned char *iv,
21 | const unsigned char *input,
22 | size_t inlen,
23 | unsigned char *output,
24 | size_t *outlen)
25 | {
26 | int ret = 0;
27 | EVP_CIPHER_CTX *ctx = NULL;
28 | EVP_CIPHER *cipher = NULL;
29 | int len, lenf;
30 |
31 | ctx = EVP_CIPHER_CTX_new();
32 | if (ctx == NULL)
33 | goto end;
34 |
35 | cipher = EVP_CIPHER_fetch(NULL, algo, NULL);
36 | if (cipher == NULL)
37 | goto end;
38 |
39 | if (!EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc))
40 | goto end;
41 |
42 | if (!EVP_CipherUpdate(ctx, output, &len, input, inlen))
43 | goto end;
44 |
45 | if (!EVP_CipherFinal_ex(ctx, output + len, &lenf))
46 | goto end;
47 |
48 | *outlen = len + lenf;
49 | ret = 1;
50 | end:
51 | EVP_CIPHER_CTX_free(ctx);
52 | return ret;
53 | }
54 |
55 | void Sm4encrypt::on_pushButtonEncrypt_clicked()
56 | {
57 | QString algo = this->ui->comboBoxMode->currentText();
58 | QString keyQstr = this->ui->lineEditKey->text();
59 | QString ivQstr = this->ui->lineEditIV->text();
60 | QString inputQstr = this->ui->plainTextEditPlain->toPlainText();
61 | std::vector key, iv, outbuf;
62 | std::vector outhex;
63 | size_t outlen;
64 |
65 | if (keyQstr.isEmpty()) {
66 | QMessageBox::warning(NULL,
67 | "warning",
68 | QString("请输入密钥!"),
69 | QMessageBox::Close,
70 | QMessageBox::Close);
71 | return;
72 | }
73 |
74 | if (algo != "SM4-ECB" && ivQstr.isEmpty()) {
75 | QMessageBox::warning(NULL,
76 | "warning",
77 | QString("请输入初始化向量IV!"),
78 | QMessageBox::Close,
79 | QMessageBox::Close);
80 | return;
81 | }
82 |
83 | key.reserve(keyQstr.size() / 2);
84 |
85 | if (OPENSSL_hexstr2buf_ex(key.data(), key.capacity(), NULL, keyQstr.toStdString().c_str(), '\0')
86 | != 1) {
87 | printTSError();
88 | return;
89 | }
90 |
91 | iv.reserve(ivQstr.size() / 2);
92 |
93 | if (OPENSSL_hexstr2buf_ex(iv.data(), iv.capacity(), NULL, ivQstr.toStdString().c_str(), '\0')
94 | != 1) {
95 | printTSError();
96 | return;
97 | }
98 |
99 | outbuf.reserve(inputQstr.size() + 16);
100 |
101 | if (do_sm4_crypt(algo.toStdString().c_str(),
102 | 1,
103 | key.data(),
104 | iv.data(),
105 | (const unsigned char *) inputQstr.toStdString().c_str(),
106 | inputQstr.size(),
107 | outbuf.data(),
108 | &outlen)
109 | != 1) {
110 | printTSError();
111 | return;
112 | }
113 |
114 | outhex.reserve(outlen * 2 + 1);
115 |
116 | if (OPENSSL_buf2hexstr_ex(outhex.data(), outhex.capacity(), NULL, outbuf.data(), outlen, '\0')
117 | != 1) {
118 | printTSError();
119 | return;
120 | }
121 |
122 | this->ui->plainTextEditCipher->setPlainText(QString(outhex.data()));
123 | }
124 |
125 | void Sm4encrypt::on_pushButtonDecrypt_clicked()
126 | {
127 | QString algo = this->ui->comboBoxMode->currentText();
128 | QString keyQstr = this->ui->lineEditKey->text();
129 | QString ivQstr = this->ui->lineEditIV->text();
130 | QString inputQstr = this->ui->plainTextEditCipher->toPlainText();
131 | std::vector key, iv, input;
132 | std::vector outbuf;
133 | size_t outlen;
134 |
135 | if (keyQstr.isEmpty()) {
136 | QMessageBox::warning(NULL,
137 | "warning",
138 | QString("请输入密钥!"),
139 | QMessageBox::Close,
140 | QMessageBox::Close);
141 | return;
142 | }
143 |
144 | if (algo != "SM4-ECB" && ivQstr.isEmpty()) {
145 | QMessageBox::warning(NULL,
146 | "warning",
147 | QString("请输入初始化向量IV!"),
148 | QMessageBox::Close,
149 | QMessageBox::Close);
150 | return;
151 | }
152 |
153 | key.reserve(keyQstr.size() / 2);
154 |
155 | if (OPENSSL_hexstr2buf_ex(key.data(), key.capacity(), NULL, keyQstr.toStdString().c_str(), '\0')
156 | != 1) {
157 | printTSError();
158 | return;
159 | }
160 |
161 | iv.reserve(ivQstr.size() / 2);
162 |
163 | if (OPENSSL_hexstr2buf_ex(iv.data(), iv.capacity(), NULL, ivQstr.toStdString().c_str(), '\0')
164 | != 1) {
165 | printTSError();
166 | return;
167 | }
168 |
169 | input.reserve(inputQstr.size() / 2);
170 | if (OPENSSL_hexstr2buf_ex(input.data(),
171 | input.capacity(),
172 | NULL,
173 | inputQstr.toStdString().c_str(),
174 | '\0')
175 | != 1) {
176 | printTSError();
177 | return;
178 | }
179 |
180 | outbuf.reserve(input.capacity());
181 |
182 | if (do_sm4_crypt(algo.toStdString().c_str(),
183 | 0,
184 | key.data(),
185 | iv.data(),
186 | input.data(),
187 | input.capacity(),
188 | (unsigned char *) outbuf.data(),
189 | &outlen)
190 | != 1) {
191 | printTSError();
192 | return;
193 | }
194 |
195 | this->ui->plainTextEditPlain->setPlainText(
196 | QString::fromStdString(std::string(outbuf.data(), outlen)));
197 | }
198 |
199 | void Sm4encrypt::on_pushButtonRandomIV_clicked()
200 | {
201 | unsigned char buf[16];
202 | std::vector hex;
203 |
204 | if (RAND_bytes(buf, sizeof(buf)) != 1) {
205 | printTSError();
206 | return;
207 | }
208 |
209 | hex.reserve(sizeof(buf) * 2 + 1);
210 |
211 | if (OPENSSL_buf2hexstr_ex(hex.data(), hex.capacity(), NULL, buf, sizeof(buf), '\0') != 1) {
212 | printTSError();
213 | return;
214 | }
215 |
216 | this->ui->lineEditIV->setText(hex.data());
217 | }
218 |
219 | void Sm4encrypt::on_pushButtonRandomKey_clicked()
220 | {
221 | unsigned char buf[16];
222 | std::vector hex;
223 |
224 | if (RAND_bytes(buf, sizeof(buf)) != 1) {
225 | printTSError();
226 | return;
227 | }
228 |
229 | hex.reserve(sizeof(buf) * 2 + 1);
230 |
231 | if (OPENSSL_buf2hexstr_ex(hex.data(), hex.capacity(), NULL, buf, sizeof(buf), '\0') != 1) {
232 | printTSError();
233 | return;
234 | }
235 |
236 | this->ui->lineEditKey->setText(hex.data());
237 | }
238 |
239 | void Sm4encrypt::on_comboBoxMode_currentTextChanged(const QString &arg1)
240 | {
241 | if (arg1 == "SM4-ECB") {
242 | this->ui->lineEditIV->setEnabled(false);
243 | this->ui->lineEditIV->hide();
244 | } else {
245 | this->ui->lineEditIV->setEnabled(true);
246 | this->ui->lineEditIV->show();
247 | }
248 | }
249 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/sm2cert.cpp:
--------------------------------------------------------------------------------
1 | #include "sm2cert.h"
2 | #include "ui_sm2cert.h"
3 | #include
4 |
5 | Sm2Cert::Sm2Cert(QWidget *parent)
6 | : QWidget(parent)
7 | , ui(new Ui::Sm2Cert)
8 | {
9 | ui->setupUi(this);
10 | }
11 |
12 | Sm2Cert::~Sm2Cert()
13 | {
14 | delete ui;
15 | }
16 |
17 | static char *opt_getprog(void)
18 | {
19 | return (char *) "";
20 | }
21 |
22 | /*
23 | * name is expected to be in the format /type0=value0/type1=value1/type2=...
24 | * where + can be used instead of / to form multi-valued RDNs if canmulti
25 | * and characters may be escaped by \
26 | */
27 | static X509_NAME *parse_name(const char *cp, int chtype, int canmulti, const char *desc)
28 | {
29 | int nextismulti = 0;
30 | char *work;
31 | X509_NAME *n;
32 |
33 | if (*cp++ != '/') {
34 | BIO_printf(bio_err,
35 | "%s: %s name is expected to be in the format "
36 | "/type0=value0/type1=value1/type2=... where characters may "
37 | "be escaped by \\. This name is not in that format: '%s'\n",
38 | opt_getprog(),
39 | desc,
40 | --cp);
41 | return NULL;
42 | }
43 |
44 | n = X509_NAME_new();
45 | if (n == NULL) {
46 | BIO_printf(bio_err, "%s: Out of memory\n", opt_getprog());
47 | return NULL;
48 | }
49 | work = OPENSSL_strdup(cp);
50 | if (work == NULL) {
51 | BIO_printf(bio_err, "%s: Error copying %s name input\n", opt_getprog(), desc);
52 | goto err;
53 | }
54 |
55 | while (*cp != '\0') {
56 | char *bp = work;
57 | char *typestr = bp;
58 | unsigned char *valstr;
59 | int nid;
60 | int ismulti = nextismulti;
61 | nextismulti = 0;
62 |
63 | /* Collect the type */
64 | while (*cp != '\0' && *cp != '=')
65 | *bp++ = *cp++;
66 | *bp++ = '\0';
67 | if (*cp == '\0') {
68 | BIO_printf(bio_err,
69 | "%s: Missing '=' after RDN type string '%s' in %s name string\n",
70 | opt_getprog(),
71 | typestr,
72 | desc);
73 | goto err;
74 | }
75 | ++cp;
76 |
77 | /* Collect the value. */
78 | valstr = (unsigned char *) bp;
79 | for (; *cp != '\0' && *cp != '/'; *bp++ = *cp++) {
80 | /* unescaped '+' symbol string signals further member of multiRDN */
81 | if (canmulti && *cp == '+') {
82 | nextismulti = 1;
83 | break;
84 | }
85 | if (*cp == '\\' && *++cp == '\0') {
86 | BIO_printf(bio_err,
87 | "%s: Escape character at end of %s name string\n",
88 | opt_getprog(),
89 | desc);
90 | goto err;
91 | }
92 | }
93 | *bp++ = '\0';
94 |
95 | /* If not at EOS (must be + or /), move forward. */
96 | if (*cp != '\0')
97 | ++cp;
98 |
99 | /* Parse */
100 | nid = OBJ_txt2nid(typestr);
101 | if (nid == NID_undef) {
102 | BIO_printf(bio_err,
103 | "%s: Skipping unknown %s name attribute \"%s\"\n",
104 | opt_getprog(),
105 | desc,
106 | typestr);
107 | if (ismulti)
108 | BIO_printf(bio_err,
109 | "Hint: a '+' in a value string needs be escaped using '\\' else a new "
110 | "member of a multi-valued RDN is expected\n");
111 | continue;
112 | }
113 | if (*valstr == '\0') {
114 | BIO_printf(bio_err,
115 | "%s: No value provided for %s name attribute \"%s\", skipped\n",
116 | opt_getprog(),
117 | desc,
118 | typestr);
119 | continue;
120 | }
121 | if (!X509_NAME_add_entry_by_NID(
122 | n, nid, chtype, valstr, strlen((char *) valstr), -1, ismulti ? -1 : 0)) {
123 | ERR_print_errors(bio_err);
124 | BIO_printf(bio_err,
125 | "%s: Error adding %s name attribute \"/%s=%s\"\n",
126 | opt_getprog(),
127 | desc,
128 | typestr,
129 | valstr);
130 | goto err;
131 | }
132 | }
133 |
134 | OPENSSL_free(work);
135 | return n;
136 |
137 | err:
138 | X509_NAME_free(n);
139 | OPENSSL_free(work);
140 | return NULL;
141 | }
142 |
143 | static X509 *genCert(int type,
144 | X509 *midCA,
145 | EVP_PKEY *midcaPkey,
146 | QString subj,
147 | QString days,
148 | char **key,
149 | size_t *keylen)
150 | {
151 | X509_NAME *name = NULL;
152 | X509 *userCer = NULL;
153 | std::string str;
154 | long len;
155 | BIO *out = NULL;
156 | X509_EXTENSION *cert_ex = NULL;
157 | X509_REQ *userReq = NULL;
158 | ASN1_INTEGER *aserial = NULL;
159 | const X509_NAME *rootCAname;
160 | time_t curTime;
161 | ASN1_TIME *rootBeforeTime = NULL;
162 | ASN1_TIME *rootAfterTime = NULL;
163 | EVP_PKEY *userKey = EVP_PKEY_Q_keygen(NULL, NULL, "SM2");
164 |
165 | if (userKey == NULL) {
166 | printTSError();
167 | return NULL;
168 | }
169 |
170 | out = BIO_new(BIO_s_mem());
171 | if (out == NULL)
172 | goto end;
173 |
174 | if (!PEM_write_bio_PrivateKey(out, userKey, NULL, NULL, 0, NULL, NULL)) {
175 | printTSError();
176 | goto end;
177 | }
178 |
179 | len = BIO_get_mem_data(out, NULL);
180 | if (len <= 0)
181 | goto end;
182 |
183 | *key = (char *) malloc(len);
184 | if (*key == NULL)
185 | goto end;
186 |
187 | if (BIO_read(out, *key, len) != len)
188 | goto end;
189 |
190 | *keylen = len;
191 |
192 | userReq = X509_REQ_new();
193 | if (userReq == NULL)
194 | goto end;
195 |
196 | X509_REQ_set_pubkey(userReq, userKey);
197 |
198 | if (!subj.isEmpty()) {
199 | name = parse_name(subj.toStdString().c_str(), MBSTRING_ASC, 1, "subject");
200 |
201 | if (!name) {
202 | return NULL;
203 | }
204 |
205 | X509_REQ_set_subject_name(userReq, name);
206 | }
207 |
208 | if (!X509_REQ_set_version(userReq, X509_VERSION_3)
209 | || !X509_REQ_sign(userReq, userKey, EVP_sm3()) || !X509_REQ_verify(userReq, userKey))
210 | goto end;
211 |
212 | if (type == 0) {
213 | str = "Key Encipherment, Data Encipherment";
214 | } else {
215 | str = "Digital Signature";
216 | }
217 |
218 | userCer = X509_new();
219 | if (userCer == NULL)
220 | goto end;
221 |
222 | cert_ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, str.c_str());
223 | if (cert_ex == NULL)
224 | goto end;
225 |
226 | if (!X509_add_ext(userCer, cert_ex, -1) || !X509_set_version(userCer, X509_VERSION_3)
227 | || !X509_set_pubkey(userCer, userKey))
228 | goto end;
229 |
230 | aserial = ASN1_INTEGER_new();
231 |
232 | if (!ASN1_INTEGER_set(aserial, 0))
233 | goto end;
234 |
235 | if (!X509_set_serialNumber(userCer, aserial) || !X509_set_subject_name(userCer, name))
236 | goto end;
237 |
238 | rootCAname = X509_get_subject_name(midCA);
239 | if (!X509_set_issuer_name(userCer, rootCAname))
240 | goto end;
241 |
242 | curTime = time(NULL);
243 | rootBeforeTime = ASN1_TIME_new();
244 | rootAfterTime = ASN1_TIME_adj(NULL, curTime, 0, days.toInt() * 60 * 60 * 24);
245 |
246 | if (!ASN1_TIME_set(rootBeforeTime, curTime) || !X509_set_notBefore(userCer, rootBeforeTime)
247 | || !X509_set_notAfter(userCer, rootAfterTime))
248 | goto end;
249 |
250 | if (!X509_sign(userCer, midcaPkey, EVP_sm3()))
251 | goto end;
252 |
253 | end:
254 | ASN1_TIME_free(rootAfterTime);
255 | ASN1_TIME_free(rootBeforeTime);
256 | ASN1_INTEGER_free(aserial);
257 | X509_EXTENSION_free(cert_ex);
258 | X509_REQ_free(userReq);
259 | BIO_free(out);
260 | EVP_PKEY_free(userKey);
261 |
262 | return userCer;
263 | }
264 |
265 | void Sm2Cert::on_pushButtonGen_clicked()
266 | {
267 | QString subj = this->ui->lineEditSubj->text();
268 | QString days = this->ui->lineEditDays->text();
269 | QFile fsubca(":/certs/subca.pem");
270 | QFile fpkey(":/certs/subca.key");
271 | X509 *userSignCer = NULL, *userEncryptCer = NULL;
272 | char *signKey = NULL, *encKey = NULL;
273 | size_t signKeyLen, encKeyLen;
274 | QString subcaQstr, pkeyQstr;
275 | X509 *subca = NULL;
276 | EVP_PKEY *pkey = NULL;
277 | long len;
278 | char *buf = NULL;
279 | BIO *out = NULL;
280 |
281 | if (subj.isEmpty()) {
282 | QMessageBox::warning(NULL,
283 | "warning",
284 | QString("请输入主体名称!"),
285 | QMessageBox::Close,
286 | QMessageBox::Close);
287 | return;
288 | }
289 |
290 | if (days.isEmpty()) {
291 | QMessageBox::warning(NULL,
292 | "warning",
293 | QString("请输入有效期!"),
294 | QMessageBox::Close,
295 | QMessageBox::Close);
296 | return;
297 | }
298 |
299 | if (!fsubca.open(QIODevice::ReadOnly | QIODevice::Text)) {
300 | QMessageBox::warning(NULL,
301 | "warning",
302 | QString("subca.pem打开失败!"),
303 | QMessageBox::Close,
304 | QMessageBox::Close);
305 | return;
306 | }
307 |
308 | if (!fpkey.open(QIODevice::ReadOnly | QIODevice::Text)) {
309 | QMessageBox::warning(NULL,
310 | "warning",
311 | QString("subca.key打开失败!"),
312 | QMessageBox::Close,
313 | QMessageBox::Close);
314 | return;
315 | }
316 | QTextStream subcaInput(&fsubca);
317 | QTextStream pkeyInput(&fpkey);
318 |
319 | subcaQstr = subcaInput.readAll();
320 | pkeyQstr = pkeyInput.readAll();
321 |
322 | out = BIO_new(BIO_s_mem());
323 | if (out == NULL)
324 | goto end;
325 |
326 | if (BIO_write(out, subcaQstr.toStdString().c_str(), subcaQstr.size()) != subcaQstr.size())
327 | goto end;
328 |
329 | subca = PEM_read_bio_X509(out, NULL, NULL, NULL);
330 | if (subca == NULL) {
331 | this->ui->textBrowserSignKey->setText(subcaQstr);
332 | printTSError();
333 | goto end;
334 | }
335 |
336 | fsubca.close();
337 | BIO_reset(out);
338 |
339 | if (BIO_write(out, pkeyQstr.toStdString().c_str(), pkeyQstr.size()) != pkeyQstr.size())
340 | goto end;
341 |
342 | pkey = PEM_read_bio_PrivateKey(out, NULL, NULL, NULL);
343 | if (pkey == NULL) {
344 | printTSError();
345 | goto end;
346 | }
347 |
348 | fpkey.close();
349 |
350 | userSignCer = genCert(1, subca, pkey, subj, days, &signKey, &signKeyLen);
351 | if (userSignCer == NULL) {
352 | printTSError();
353 | goto end;
354 | }
355 |
356 | userEncryptCer = genCert(0, subca, pkey, subj, days, &encKey, &encKeyLen);
357 | if (userEncryptCer == NULL) {
358 | printTSError();
359 | goto end;
360 | }
361 |
362 | this->ui->textBrowserSignKey->setText(QString::fromStdString(std::string(signKey, signKeyLen)));
363 | this->ui->textBrowserEncryKey->setText(QString::fromStdString(std::string(encKey, encKeyLen)));
364 |
365 | BIO_reset(out);
366 |
367 | if (!PEM_write_bio_X509(out, userSignCer)) {
368 | printTSError();
369 | goto end;
370 | }
371 |
372 | len = BIO_get_mem_data(out, &buf);
373 | if (len <= 0)
374 | goto end;
375 |
376 | this->ui->textBrowserSignOutput->setPlainText(QString::fromStdString(std::string(buf, len)));
377 |
378 | BIO_reset(out);
379 |
380 | if (!PEM_write_bio_X509(out, userEncryptCer)) {
381 | printTSError();
382 | goto end;
383 | }
384 |
385 | len = BIO_get_mem_data(out, &buf);
386 | if (len <= 0)
387 | goto end;
388 |
389 | this->ui->textBrowserEncryptOutput->setPlainText(QString::fromStdString(std::string(buf, len)));
390 |
391 | end:
392 | EVP_PKEY_free(pkey);
393 | X509_free(subca);
394 | BIO_free(out);
395 | free(signKey);
396 | free(encKey);
397 | X509_free(userSignCer);
398 | X509_free(userEncryptCer);
399 | }
400 |
--------------------------------------------------------------------------------