Python gmssl.SM4使用案例
Python gmssl.SM4使用案例
一、Python脚本实现(使用gmssl)
python/sm4_crypto_gmssl.py
#!/usr/bin/env python3
import sys
import json
from gmssl import sm4class SM4CryptoGmSSL:def __init__(self):self.sm4_crypt = sm4.CryptSM4()def encrypt(self, key_hex, iv_hex, plaintext_hex):"""SM4 CBC模式加密参数:key_hex: 128位密钥(32个hex字符)iv_hex: 128位初始化向量(32个hex字符)plaintext_hex: 128位明文(32个hex字符)返回:密文的hex字符串"""# 转换hex字符串为字节key = bytes.fromhex(key_hex)iv = bytes.fromhex(iv_hex)plaintext = bytes.fromhex(plaintext_hex)# 设置密钥和模式self.sm4_crypt.set_key(key, sm4.SM4_ENCRYPT)# CBC模式加密ciphertext = self.sm4_crypt.crypt_cbc(iv, plaintext)return ciphertext.hex()def decrypt(self, key_hex, iv_hex, ciphertext_hex):"""SM4 CBC模式解密参数:key_hex: 128位密钥(32个hex字符)iv_hex: 128位初始化向量(32个hex字符)ciphertext_hex: 128位密文(32个hex字符)返回:明文的hex字符串"""# 转换hex字符串为字节key = bytes.fromhex(key_hex)iv = bytes.fromhex(iv_hex)ciphertext = bytes.fromhex(ciphertext_hex)# 设置密钥和模式self.sm4_crypt.set_key(key, sm4.SM4_DECRYPT)# CBC模式解密plaintext = self.sm4_crypt.crypt_cbc(iv, ciphertext)return plaintext.hex()def encrypt_ecb(self, key_hex, plaintext_hex):"""SM4 ECB模式加密(无需IV)"""key = bytes.fromhex(key_hex)plaintext = bytes.fromhex(plaintext_hex)self.sm4_crypt.set_key(key, sm4.SM4_ENCRYPT)ciphertext = self.sm4_crypt.crypt_ecb(plaintext)return ciphertext.hex()def validate_hex_string(hex_str, expected_length):"""验证十六进制字符串的有效性和长度"""try:bytes.fromhex(hex_str)if len(hex_str) != expected_length:raise ValueError(f"Expected {expected_length} hex characters, got {len(hex_str)}")return Trueexcept ValueError as e:return Falsedef main():"""主函数,处理命令行参数"""if len(sys.argv) < 2:result = {"status": "error","message": "Usage: python sm4_crypto_gmssl.py <command> [args...]"}print(json.dumps(result))sys.exit(1)sm4_crypto = SM4CryptoGmSSL()command = sys.argv[1]if command == "encrypt":if len(sys.argv) != 5:result = {"status": "error","message": "Usage: python sm4_crypto_gmssl.py encrypt <key> <iv> <plaintext>"}print(json.dumps(result))sys.exit(1)key = sys.argv[2]iv = sys.argv[3]plaintext = sys.argv[4]# 验证输入if not validate_hex_string(key, 32):result = {"status": "error", "message": "Invalid key format (need 32 hex chars)"}print(json.dumps(result))sys.exit(1)if not validate_hex_string(iv, 32):result = {"status": "error", "message": "Invalid IV format (need 32 hex chars)"}print(json.dumps(result))sys.exit(1)if not validate_hex_string(plaintext, 32):result = {"status": "error", "message": "Invalid plaintext format (need 32 hex chars)"}print(json.dumps(result))sys.exit(1)try:ciphertext = sm4_crypto.encrypt(key, iv, plaintext)result = {"status": "success","operation": "encrypt","key": key,"iv": iv,"plaintext": plaintext,"ciphertext": ciphertext}except Exception as e:result = {"status": "error","message": f"Encryption failed: {str(e)}"}print(json.dumps(result))elif command == "decrypt":if len(sys.argv) != 5:result = {"status": "error","message": "Usage: python sm4_crypto_gmssl.py decrypt <key> <iv> <ciphertext>"}print(json.dumps(result))sys.exit(1)key = sys.argv[2]iv = sys.argv[3]ciphertext = sys.argv[4]# 验证输入if not validate_hex_string(key, 32):result = {"status": "error", "message": "Invalid key format (need 32 hex chars)"}print(json.dumps(result))sys.exit(1)if not validate_hex_string(iv, 32):result = {"status": "error", "message": "Invalid IV format (need 32 hex chars)"}print(json.dumps(result))sys.exit(1)if not validate_hex_string(ciphertext, 32):result = {"status": "error", "message": "Invalid ciphertext format (need 32 hex chars)"}print(json.dumps(result))sys.exit(1)try:plaintext = sm4_crypto.decrypt(key, iv, ciphertext)result = {"status": "success","operation": "decrypt","key": key,"iv": iv,"ciphertext": ciphertext,"plaintext": plaintext}except Exception as e:result = {"status": "error","message": f"Decryption failed: {str(e)}"}print(json.dumps(result))elif command == "test":# 内置测试命令test_key = "0123456789abcdef0123456789abcdef"test_iv = "fedcba9876543210fedcba9876543210"test_plaintext = "48656c6c6f20576f726c6421212121" # "Hello World!!!!!" in hextry:# 加密测试ciphertext = sm4_crypto.encrypt(test_key, test_iv, test_plaintext)# 解密测试decrypted = sm4_crypto.decrypt(test_key, test_iv, ciphertext)result = {"status": "success","test_results": {"key": test_key,"iv": test_iv,"original_plaintext": test_plaintext,"ciphertext": ciphertext,"decrypted_plaintext": decrypted,"test_passed": test_plaintext == decrypted}}except Exception as e:result = {"status": "error","message": f"Test failed: {str(e)}"}print(json.dumps(result))else:result = {"status": "error","message": f"Unknown command: {command}"}print(json.dumps(result))sys.exit(1)if __name__ == "__main__":main()
python/requirements.txt
gmssl==3.2.1
二、更新的DPI C接口
scripts/dpi_wrapper_gmssl.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "svdpi.h"#define BUFFER_SIZE 1024// 解析JSON响应,提取指定字段
static int parse_json_field(const char* json, const char* field, char* value, int max_len) {char search_pattern[64];sprintf(search_pattern, "\"%s\": \"", field);const char* field_start = strstr(json, search_pattern);if (field_start == NULL) {return -1;}field_start += strlen(search_pattern);const char* field_end = strchr(field_start, '"');if (field_end == NULL) {return -1;}int len = field_end - field_start;if (len >= max_len) {return -1;}strncpy(value, field_start, len);value[len] = '\0';return 0;
}// DPI导出函数:调用Python进行SM4加密
extern "C" int sm4_encrypt_dpi(const char* key,const char* iv,const char* plaintext,char* ciphertext
) {char cmd[BUFFER_SIZE];char result[BUFFER_SIZE];char status[32];FILE *fp;// 构建Python命令snprintf(cmd, sizeof(cmd), "cd ../python && python3 sm4_crypto_gmssl.py encrypt %s %s %s 2>&1", key, iv, plaintext);// 执行Python脚本fp = popen(cmd, "r");if (fp == NULL) {printf("Error: Failed to execute Python script\n");return -1;}// 读取完整结果result[0] = '\0';if (fgets(result, sizeof(result), fp) == NULL) {pclose(fp);printf("Error: Failed to read Python output\n");return -1;}pclose(fp);// 检查状态if (parse_json_field(result, "status", status, sizeof(status)) != 0) {printf("Error: Failed to parse status from JSON\n");return -1;}if (strcmp(status, "success") != 0) {char error_msg[256];if (parse_json_field(result, "message", error_msg, sizeof(error_msg)) == 0) {printf("Error from Python: %s\n", error_msg);}return -1;}// 提取密文if (parse_json_field(result, "ciphertext", ciphertext, 64) != 0) {printf("Error: Failed to parse ciphertext from JSON\n");return -1;}return 0;
}// DPI导出函数:调用Python进行SM4解密
extern "C" int sm4_decrypt_dpi(const char* key,const char* iv,const char* ciphertext,char* plaintext
) {char cmd[BUFFER_SIZE];char result[BUFFER_SIZE];char status[32];FILE *fp;// 构建Python命令snprintf(cmd, sizeof(cmd), "cd ../python && python3 sm4_crypto_gmssl.py decrypt %s %s %s 2>&1", key, iv, ciphertext);// 执行Python脚本fp = popen(cmd, "r");if (fp == NULL) {printf("Error: Failed to execute Python script\n");return -1;}// 读取完整结果result[0] = '\0';if (fgets(result, sizeof(result), fp) == NULL) {pclose(fp);printf("Error: Failed to read Python output\n");return -1;}pclose(fp);// 检查状态if (parse_json_field(result, "status", status, sizeof(status)) != 0) {printf("Error: Failed to parse status from JSON\n");return -1;}if (strcmp(status, "success") != 0) {char error_msg[256];if (parse_json_field(result, "message", error_msg, sizeof(error_msg)) == 0) {printf("Error from Python: %s\n", error_msg);}return -1;}// 提取明文if (parse_json_field(result, "plaintext", plaintext, 64) != 0) {printf("Error: Failed to parse plaintext from JSON\n");return -1;}return 0;
}// DPI导出函数:测试Python脚本
extern "C" int sm4_test_dpi() {char cmd[BUFFER_SIZE];char result[BUFFER_SIZE];FILE *fp;// 运行测试命令snprintf(cmd, sizeof(cmd), "cd ../python && python3 sm4_crypto_gmssl.py test 2>&1");fp = popen(cmd, "r");if (fp == NULL) {return -1;}while (fgets(result, sizeof(result), fp) != NULL) {printf("%s", result);}pclose(fp);return 0;
}
三、安装和使用说明
安装gmssl库
# 安装gmssl Python库
pip install gmssl# 或者使用requirements.txt
cd python
pip install -r requirements.txt
测试Python脚本
# 测试脚本功能
cd python
python3 sm4_crypto_gmssl.py test# 手动测试加密
python3 sm4_crypto_gmssl.py encrypt 0123456789abcdef0123456789abcdef fedcba9876543210fedcba9876543210 48656c6c6f20576f726c6421212121# 手动测试解密(使用上面加密的结果)
python3 sm4_crypto_gmssl.py decrypt 0123456789abcdef0123456789abcdef fedcba9876543210fedcba9876543210 <ciphertext_from_above>
四、Makefile更新
# 顶层Makefile# 工具和路径定义
PYTHON = python3
PYTHON_DIR = python
SRC_DIR = src
SCRIPT_DIR = scripts
WORK_DIR = work
LOG_DIR = logs# 编译选项
VCS_FLAGS = -sverilog +acc +vpi -CFLAGS "-I$(VCS_HOME)/include"
DPI_FLAGS = -LDFLAGS "-Wl,--no-as-needed".PHONY: all clean compile run test_pythonall: test_python compile run# 测试Python环境
test_python:@echo ">>> Testing Python SM4 implementation..."@cd $(PYTHON_DIR) && $(PYTHON) sm4_crypto_gmssl.py test@echo ">>> Python test completed."# 编译DPI和SystemVerilog
compile:@echo ">>> Compiling DPI wrapper..."@mkdir -p $(WORK_DIR)@gcc -fPIC -shared -o $(WORK_DIR)/dpi_wrapper.so \$(SCRIPT_DIR)/dpi_wrapper_gmssl.c \-I$(VCS_HOME)/include@echo ">>> Compiling SystemVerilog..."@vcs $(VCS_FLAGS) $(DPI_FLAGS) \-o $(WORK_DIR)/simv \$(SRC_DIR)/*.sv \$(WORK_DIR)/dpi_wrapper.so@echo ">>> Compilation completed."# 运行仿真
run:@echo ">>> Running simulation..."@mkdir -p $(LOG_DIR)@cd $(WORK_DIR) && ./simv -l ../$(LOG_DIR)/sim.log@echo ">>> Simulation completed."# 清理
clean:@echo ">>> Cleaning..."@rm -rf $(WORK_DIR) $(LOG_DIR) csrc *.daidir ucli.key@echo ">>> Clean completed."
这个使用gmssl库的实现提供了:
- 更简洁的SM4加密解密接口
- 完整的错误处理和输入验证
- JSON格式的输入输出,便于解析
- 内置测试功能,确保环境正确配置
- 详细的错误信息输出