Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ jobs:
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.manylinux_image }}
CIBW_TEST_COMMAND: python -m unittest discover {project}/tests

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
- uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: cibw-wheels-${{ matrix.os }}-${{ matrix.python }}-${{ strategy.job-index }}
path: ./wheelhouse/*.whl
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,7 @@ venv
__pycache__
zzz/
.cache/
compile_commands.json
compile_commands.json

# 运行示例/测试生成的密钥产物
*.pem
2 changes: 1 addition & 1 deletion GmSSL
Submodule GmSSL updated 452 files
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

python wrapper (C extension) of [GmSSL](https://github.com/guanzhi/GmSSL)

使用的版本是 [GmSSL-3.1.0](https://github.com/guanzhi/GmSSL/releases/tag/v3.1.0)
使用的版本是 [GmSSL-3.2.0](https://github.com/guanzhi/GmSSL/releases/tag/v3.2.0)

## 安装

Expand Down Expand Up @@ -293,3 +293,11 @@ print('plaintext', plaintext)
[SM9](docs/sm9.md)

如果要查看所有可用的 API ,可以看 [gmsslext.pyi](gmssl_pyx/gmsslext.pyi) 文件。

## 注意

GmSSL v3.2.0 修改了 SM9 PEM 文件头(即 BEGIN 与 END 行中的标识字符串),变更如下:

"ENCRYPTED SM9 ENC MASTER KEY" => "ENCRYPTED PRIVATE KEY"

"ENCRYPTED SM9 ENC PRIVATE KEY" => "ENCRYPTED PRIVATE KEY"
12 changes: 7 additions & 5 deletions gmssl_pyx/gmsslext.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def sm2_verify_sm3_digest(public_key: bytes, digest: bytes, signature: bytes) ->
"""使用 SM2 验证 SM3 摘要和签名数据

Args:
public_key: 64 字节的私钥
public_key: 64 字节的公钥
digest: SM3 摘要数据,长度为 32 字节
signature: 签名数据,编码格式为 ASN.1 DER ,模式为 rs

Expand Down Expand Up @@ -223,9 +223,11 @@ def sm4_gcm_decrypt(
iv: 初始化向量,也被叫做 nonce ,1 <= 长度 <= 64
aad: 附加数据,也被叫做 associated_data
ciphertext: 密文数据
tag: 标签
tag: 标签,12 <= 长度 <= 16

Returns: 明文数据

Raises: InvalidValueError: tag 长度非法或 tag 不匹配(认证失败)
"""
...

Expand Down Expand Up @@ -259,7 +261,7 @@ class SM9PrivateKey:
password: 密码
data: 加密的 ASN.1 DER 编码数据

Return: 私钥
Returns: 私钥
"""
...

Expand Down Expand Up @@ -347,7 +349,7 @@ class SM9MasterKey:
password: 密码
data: 加密的 ASN.1 DER 编码数据

Return: 主密钥
Returns: 主密钥
"""
...

Expand All @@ -363,7 +365,7 @@ class SM9MasterKey:
password: 密码
filepath: 文件路径

Return: 主密钥
Returns: 主密钥
"""

def encrypt_to_pem(self, password: str, filepath: str) -> None:
Expand Down
70 changes: 67 additions & 3 deletions gmssl_pyx/gmsslext_sm9.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,33 @@

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#include "gmssl/sm9.h"
#include "gmssl/pem.h"
#include "gmssl/asn1.h"
#include "gmssl/mem.h"

#include "gmsslext.h"
#include "gmsslext_sm9.h"

static bool pem_starts_with(FILE *fp, const char *prefix) {
if (!fp || !prefix) return false;

size_t len = strlen(prefix);
if (len == 0) return true;

char buffer[128]; // 足够大
size_t read_len = fread(buffer, 1, len, fp);

// 重置文件指针到开头(重要!)
rewind(fp);

if (read_len != len) return false;

return memcmp(buffer, prefix, len) == 0;
}

/*
* SM9 wrapper
*/
Expand All @@ -24,6 +45,7 @@ typedef struct {
} SM9PrivateKeyObject;

static void SM9PrivateKey_dealloc(SM9PrivateKeyObject *self) {
gmssl_secure_clear(&self->key, sizeof(self->key));
Py_TYPE(self)->tp_free((PyObject *)self);
}

Expand Down Expand Up @@ -181,6 +203,20 @@ static PyObject *SM9PrivateKey_encrypt_to_der(SM9PrivateKeyObject *self,
return Py_BuildValue("y#", (char *)buf, (Py_ssize_t)len);
}

static int sm9_enc_key_info_decrypt_from_pem_v3_1_1(SM9_ENC_KEY *key, const char *pass, FILE *fp)
{
uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE];
const uint8_t *cp = buf;
size_t len;

if (pem_read(fp, PEM_SM9_ENC_PRIVATE_KEY_V3_1_1, buf, &len, sizeof(buf)) != 1
|| sm9_enc_key_info_decrypt_from_der(key, pass, &cp, &len) != 1
|| asn1_length_is_zero(len) != 1) {
return -1;
}
return 1;
}

static PyObject *SM9PrivateKey_decrypt_from_pem(PyTypeObject *type,
PyObject *args,
PyObject *keywds) {
Expand Down Expand Up @@ -215,7 +251,13 @@ static PyObject *SM9PrivateKey_decrypt_from_pem(PyTypeObject *type,
fclose(fp);
return NULL;
}
ret = sm9_enc_key_info_decrypt_from_pem(&self->key, password, fp);
char begin_line[80];
snprintf(begin_line, sizeof(begin_line), "-----BEGIN %s-----", PEM_SM9_ENC_PRIVATE_KEY_V3_1_1);
if (pem_starts_with(fp, begin_line)) {
ret = sm9_enc_key_info_decrypt_from_pem_v3_1_1(&self->key, password, fp);
} else {
ret = sm9_enc_key_info_decrypt_from_pem(&self->key, password, fp);
}
if (ret != GMSSL_INNER_OK) {
Py_DECREF(self);
fclose(fp);
Expand Down Expand Up @@ -365,6 +407,7 @@ typedef struct {
} SM9MasterPublicKeyObject;

static void SM9MasterPublicKey_dealloc(SM9MasterPublicKeyObject *self) {
gmssl_secure_clear(&self->master_public, sizeof(self->master_public));
Py_TYPE(self)->tp_free((PyObject *)self);
}

Expand Down Expand Up @@ -608,6 +651,7 @@ typedef struct {
} SM9MasterKeyObject;

static void SM9MasterKey_dealloc(SM9MasterKeyObject *self) {
gmssl_secure_clear(&self->master, sizeof(self->master));
Py_TYPE(self)->tp_free((PyObject *)self);
}

Expand Down Expand Up @@ -786,6 +830,20 @@ static PyObject *SM9MasterKey_encrypt_to_der(SM9MasterKeyObject *self,
return Py_BuildValue("y#", buf, (Py_ssize_t)len);
}

static int sm9_enc_master_key_info_decrypt_from_pem_v3_1_1(SM9_ENC_MASTER_KEY *msk, const char *pass, FILE *fp)
{
uint8_t buf[SM9_MAX_ENCED_PRIVATE_KEY_INFO_SIZE];
const uint8_t *cp = buf;
size_t len;

if (pem_read(fp, PEM_SM9_ENC_MASTER_KEY_V3_1_1, buf, &len, sizeof(buf)) != 1
|| sm9_enc_master_key_info_decrypt_from_der(msk, pass, &cp, &len) != 1
|| asn1_length_is_zero(len) != 1) {
return -1;
}
return 1;
}

static PyObject *SM9MasterKey_decrypt_from_pem(PyTypeObject *type,
PyObject *args,
PyObject *keywds) {
Expand Down Expand Up @@ -818,8 +876,14 @@ static PyObject *SM9MasterKey_decrypt_from_pem(PyTypeObject *type,
fclose(fp);
return NULL;
}
int ret =
sm9_enc_master_key_info_decrypt_from_pem(&self->master, password, fp);
int ret;
char begin_line[80];
snprintf(begin_line, sizeof(begin_line), "-----BEGIN %s-----", PEM_SM9_ENC_MASTER_KEY_V3_1_1);
if (pem_starts_with(fp, begin_line)) {
ret = sm9_enc_master_key_info_decrypt_from_pem_v3_1_1(&self->master, password, fp);
} else {
ret = sm9_enc_master_key_info_decrypt_from_pem(&self->master, password, fp);
}
if (ret != GMSSL_INNER_OK) {
Py_DECREF(self);
fclose(fp);
Expand Down
3 changes: 3 additions & 0 deletions gmssl_pyx/gmsslext_sm9.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ extern PyTypeObject GmsslextSM9PrivateKeyType;
extern PyTypeObject GmsslextSM9MasterPublicKeyType;
extern PyTypeObject GmsslextSM9MasterKeyType;

#define PEM_SM9_ENC_MASTER_KEY_V3_1_1 "ENCRYPTED SM9 ENC MASTER KEY"
#define PEM_SM9_ENC_PRIVATE_KEY_V3_1_1 "ENCRYPTED SM9 ENC PRIVATE KEY"

#endif // GMSSL_PYX_GMSSLEXT_SM9_H
Loading
Loading