GM/T 0019-2023 通用密码服务接口规范:国密应用开发的统一语言

标准规范 · 2026-08-12

在国密改造中,开发者最常遇到的问题之一:同样的 SM2 签名操作,在不同厂商的密码设备(USB Key、服务器密码机、硬件安全模块 HSM)上调用方式完全不同。甲厂商用 sm2Sign(data, keyRef),乙厂商用 cryptSign(keyHandle, data, digestAlg),丙厂商用 signWithKey(keyId, message, options)。这种"万国接口"的局面导致每个项目都要重新适配底层设备,移植成本极高。

GM/T 0019-2023《通用密码服务接口规范》 正是为了解决这个问题而生。它定义了统一的密码服务接口(CSP, Cryptographic Service Provider),让上层应用无需关心底层设备细节,即可调用国密算法服务。

标准背景与定位

为什么需要通用接口?

国密算法的应用场景已从传统的 PKI/CA 扩展到:政务系统、金融交易、物联网设备、移动端应用、云计算服务等。不同场景使用的密码设备形态各异:

设备类型典型厂商接口差异
USB Key(智能密码钥匙)三未信安、江南信安、格尔软件各自私有 SDK
服务器密码机三未信安、吉大正元、卫士通网络协议不同
硬件安全模块(HSM)IBM、Thales、众安科技API 风格迥异
云密码服务阿里云、腾讯云、华为云REST API vs SDK
如果没有统一接口,开发者需要为每种设备编写专属适配层。GM/T 0019-2023 通过定义一套标准化接口,使应用代码可以"一次编写,多处运行"。

标准关系图

与 GM/T 0018 的关系

GM/T 0019 与 GM/T 0018-2023《密码设备应用接口规范》是配套的姊妹标准:

维度GM/T 0018-2023GM/T 0019-2023
定位密码设备产品规范密码服务接口规范
对象设备厂商应用开发者
内容设备应提供的功能接口如何调用
关系设备实现 0018应用调用 0019
类比硬件规格书软件 API 文档
简单来说:0018 规定设备"能做什么",0019 规定应用"怎么用"。设备厂商按照 0018 实现硬件功能,同时提供符合 0019 的软件接口;应用开发者按照 0019 编写代码,无需关心底层设备型号。

核心接口框架

接口分层架构

GM/T 0019-2023 将密码服务接口分为四个层次:

Layer 1:设备管理层接口

设备管理层是最底层的接口,负责与密码设备建立连接和管理会话。

#### 设备初始化与连接

关键参数说明:

参数类型说明
device_idstring设备唯一标识,由 CSP_EnumDevices 返回
flagsenum会话访问模式,可读可写需同时设置
session_handlepointer输出参数,后续操作使用此句柄
常见错误码:

错误码含义排查建议
CSP_ERR_DEVICE_NOT_FOUND设备未连接检查 USB Key 是否插入,服务是否启动
CSP_ERR_SESSION_FULL会话数超限检查是否有未关闭的会话泄漏
CSP_ERR_INVALID_HANDLE句柄无效检查会话是否已关闭
#### 设备状态查询

C
// 查询设备状态
typedef struct {
    unsigned int is_online;       // 1=在线,0=离线
    unsigned int firmware_version; // 固件版本
    unsigned int free_memory;     // 可用存储空间(字节)
    unsigned int error_code;      // 最后一次错误码
} CSP_DEVICE_STATUS;

int CSP_GetDeviceStatus(
    const char *device_id,
    CSP_DEVICE_STATUS *status
);

Layer 2:密钥管理层接口

密钥管理是密码服务中最敏感的部分,GM/T 0019-2023 对密钥的生成、导入、导出、存储、销毁都做了严格规范。

#### 密钥生成

密钥生成示例(SM2 密钥对):

#### 密钥导入与导出

安全约束:

  • 私钥导入必须有身份认证(PIN 码或生物特征)
  • 私钥导出必须是加密形式,且仅限授权人员操作
  • 所有密钥操作记录审计日志
#### 密钥销毁

C
// 安全销毁密钥(覆写存储区域)
int CSP_DestroyKey(
    void  *session_handle,
    const char *key_ref
);

// 销毁设备中所有密钥(工厂重置)
int CSP_ClearAllKeys(
    void  *session_handle,
    const char *admin_pin
);

Layer 3:密码算法层接口

密码算法层是应用最频繁的部分,提供 SM2/SM3/SM4/SM9/ZUC 等算法的直接调用。

#### SM2 签名接口

签名数据格式:

GM/T 0019-2023 规定 SM2 签名采用 r || s 格式(GB/T 32918.2-2016),长度为 64 字节(32 字节 r + 32 字节 s)。部分厂商可能返回 DER 编码格式,接口层应统一转换为标准格式。

#### SM3 杂凑接口

C
// SM3 杂凑计算
int CSP_SM3_Hash(
    const unsigned char *message,
    unsigned int         message_len,
    unsigned char       *digest,       // 输出,32 字节
    unsigned int        *digest_len
);

// SM3 增量计算(大数据场景)
int CSP_SM3_Init(void **context);
int CSP_SM3_Update(void *context, const unsigned char *data, unsigned int len);
int CSP_SM3_Final(void *context, unsigned char *digest, unsigned int *digest_len);

#### SM4 加密接口

填充模式说明:

模式填充方式适用场景
ECBPKCS7 padding固定长度数据加密
CBCPKCS7 padding一般数据加密
CTR无需填充流式数据加密
GCM无需填充(AEAD)需要认证的加密场景
#### SM9 标识密码接口

Layer 4:应用接口层

应用接口层提供高级封装,适合业务开发人员直接使用。

#### 证书操作接口

#### 数字信封接口

错误码规范

GM/T 0019-2023 统一定义了密码服务的错误码,避免各厂商自定义错误码导致的兼容问题。

错误码分类

类别范围说明
成功0x00000000操作成功
通用错误0x80000000-0x800000FF通用性错误
设备错误0x80010000-0x8001FFFF设备相关错误
会话错误0x80020000-0x8002FFFF会话管理错误
密钥错误0x80030000-0x8003FFFF密钥操作错误
算法错误0x80040000-0x8004FFFF算法调用错误
证书错误0x80050000-0x8005FFFF证书操作错误
内存错误0x80060000-0x8006FFFF内存分配错误

常用错误码

错误码宏定义含义
0x80000001CSP_ERR_GENERAL通用错误
0x80000002CSP_ERR_INVALID_PARAM参数无效
0x80010001CSP_ERR_DEVICE_NOT_FOUND设备未找到
0x80010002CSP_ERR_DEVICE_BUSY设备忙
0x80020001CSP_ERR_INVALID_SESSION会话无效
0x80020002CSP_ERR_SESSION_EXISTS会话已存在
0x80030001CSP_ERR_KEY_NOT_FOUND密钥未找到
0x80030002CSP_ERR_KEY_INVALID密钥无效
0x80030003CSP_ERR_KEY_UNEXPORTABLE密钥不可导出
0x80040001CSP_ERR_ALG_UNSUPPORTED算法不支持
0x80040002CSP_ERR_ALG_INVALID_PARAM算法参数无效
0x80050001CSP_ERR_CERT_INVALID证书无效
0x80050002CSP_ERR_CERT_EXPIRED证书已过期
0x80050003CSP_ERR_CERT_REVOKED证书已吊销

与国密生态的集成

密码设备驱动适配

设备厂商需要按照 GM/T 0019-2023 实现适配层,将设备私有 API 转换为标准接口:

国密 TLS 库集成

国密 TLS 库(如 Tongsuo、BabaSSL、GmSSL)可通过 GM/T 0019 接口调用硬件密码服务:

国密应用开发框架

主流国密开发框架已内置 GM/T 0019 支持:

框架语言GM/T 0019 支持
TongsuoC原生支持
BabaSSLC原生支持
GmSSLC/Python通过插件支持
go-gmsslGo通过 CGO 调用
Java-GMJava通过 JNI 调用

开发实战注意事项

坑 1:会话泄漏

现象:应用运行一段时间后,新无法打开密码设备会话,报错 CSP_ERR_SESSION_FULL。

原因:每次调用 CSP_OpenSession 后未调用 CSP_CloseSession,导致会话资源泄漏。

解决方案:

C
void *session = NULL;
int ret = CSP_OpenSession(device_id, flags, &session);
if (ret != CSP_SUCCESS) {
    // 错误处理
    return ret;
}

// 确保无论何种路径都关闭会话
// 推荐:使用 RAII 风格封装
CSP_SessionGuard guard(session);  // 构造时打开,析构时关闭
// ... 使用 session ...
// guard 离开作用域时自动调用 CSP_CloseSession

坑 2:密钥引用标识符生命周期

现象:密钥生成成功后,再次调用 CSP_SM2_Sign 时返回 CSP_ERR_KEY_NOT_FOUND。

原因:密钥引用标识符(key_ref)仅在会话有效期内有效,会话关闭后引用失效。

解决方案:

  • 方案 A:保持会话长期存活,密钥引用持续有效
  • 方案 B:密钥导入设备后,使用持久化标识(如密钥指纹)替代引用
C
// 方案 B:获取密钥指纹作为持久化标识
unsigned char key_fingerprint[32] = {0};
unsigned int fingerprint_len = sizeof(key_fingerprint);
CSP_GetKeyFingerprint(session, key_ref, key_fingerprint, &fingerprint_len);

// 后续使用指纹查找密钥(无需保持会话)
CSP_LookupKeyByFingerprint(device_id, key_fingerprint, &key_ref);

坑 3:SM2 签名格式混淆

现象:验签返回失败,错误码 CSP_ERR_ALG_INVALID_PARAM。

原因:签名数据格式不一致。GM/T 0019-2023 规定使用 r || s 格式(64 字节),但部分设备默认返回 DER 编码格式。

解决方案:

坑 4:SM4 CBC 模式 IV 管理

现象:解密返回乱码或错误。

原因:CBC 模式的 IV 管理不当,加密和解密使用不同的 IV。

解决方案:

坑 5:SM9 身份编码一致性

现象:SM9 加密成功,解密返回 CSP_ERR_ALG_INVALID_PARAM。

原因:加密和解密使用的身份标识(identity)编码不一致。SM9 标准规定身份编码为 UTF-8 字节串,长度不超过 64 字节。

解决方案:

C
// 统一使用 UTF-8 编码身份标识
const char *identity_str = "user@example.com";
unsigned char identity[65] = {0};  // 64 字节 + null terminator
strncpy((char*)identity, identity_str, 64);
unsigned int identity_len = strlen(identity_str);

// 加密和解密使用相同的 identity_len 和 identity 数据
CSP_SM9_Encrypt(session, master_pub_ref, identity, identity_len,
               plaintext, plaintext_len, ciphertext, &ciphertext_len);

CSP_SM9_Decrypt(session, user_priv_ref, ciphertext, ciphertext_len,
               plaintext, &plaintext_len);

合规实施建议

密评要求

根据 GB/T 39786-2021《信息系统密码应用基本要求》,密码服务接口应符合以下要求:

密码级别接口要求审计要求
第一级使用符合 GM/T 0019 的接口基本操作日志
第二级使用符合 GM/T 0019 的接口完整操作日志
第三级使用符合 GM/T 0019 的接口,私钥不出设备完整日志 + 访问控制
第四级使用符合 GM/T 0019 的接口,HSM 托管完整日志 + 双因素认证

实施检查清单

开发团队应逐项检查:

  • [ ] 所有密码操作通过 GM/T 0019 标准接口调用
  • [ ] 私钥不导出密码设备(除非必要且加密导出)
  • [ ] 密钥使用完成后及时销毁引用
  • [ ] 会话使用后及时关闭
  • [ ] 所有密码操作记录审计日志
  • [ ] 错误处理符合标准错误码规范
  • [ ] SM2 签名格式统一为 r || s(64 字节)
  • [ ] SM4 CBC 模式 IV 正确管理
  • [ ] SM9 身份编码统一为 UTF-8

总结

GM/T 0019-2023 是国密应用开发的"普通话",它让不同厂商的密码设备能够被同一套代码调用,大幅降低了国密改造的适配成本。对于开发者而言,掌握这个标准意味着:

  • 移植更容易:更换密码设备只需更换驱动适配层,业务代码无需修改
  • 维护更简单:统一接口减少代码量,降低维护成本
  • 合规更便捷:符合密评要求,减少合规风险
随着国密应用的普及,GM/T 0019 将成为国密生态的基础设施标准,建议所有国密开发者深入理解并遵循。


参考资料:

相关实践: