GM/T 0131-2023 电子签章应用接口规范:国密改造的最后一公里
核心结论:GM/T 0131-2023 定义了电子签章系统的接口规范,是国密改造中容易被忽视但必须落地的环节。规范与 GM/T 0031(2025修订)配合使用,构成完整的电子签章密码应用体系。
一、背景:为什么需要这个规范?
1.1 现实场景
某政务系统完成国密改造后,密评现场发现扣分项:
CODE
【问题】电子签章模块使用 RSA 证书进行签名
【原因】开发团队直接调用 PDF SDK,未实现 SM2 签名接口
【整改】更换国密 PDF SDK,重新实现签章流程
【成本】约 3-5 周开发 + 密评复测费用这个案例很典型:密码产品换了,应用层接口没改。
1.2 规范定位
| 标准 | 定位 | 内容 |
|---|---|---|
| GM/T 0031-2025 | 数据结构规范 | 定义电子签章的数据格式(ASN.1) |
| GM/T 0131-2023 | 接口规范 | 定义系统间调用的接口(API) |
| GM/T 0047-2024 | 检测规范 | 定义如何检测是否符合要求 |
二、核心接口概览
2.1 接口分类
规范定义了四类接口:
| 接口类型 | 功能 | 典型场景 |
|---|---|---|
| 签章接口 | 生成电子签章 | 合同签署、公文盖章 |
| 验签接口 | 验证签章有效性 | 文件验真、防篡改检查 |
| 时间戳接口 | 绑定可信时间 | 满足"签署时点"要求 |
| 证书查询接口 | 获取证书链 | 证书状态检查 |
2.2 接口数据流
CODE
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 应用系统 │────▶│ 签章服务 │────▶│ 密码机/卡 │
│ (PDF/OFD) │◀────│ (中间件) │◀────│ (国密设备) │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└────────────────────┴────────────────────┘
密码协议三、接口实现要点
3.1 签章接口实现
输入参数:
- 待签章文件(PDF/OFD 字节流)
- 签章者 SM2 私钥(来自密码机)
- 签章者 SM2 证书链
- 签章位置(页面、坐标)
- 可选:时间戳请求
- 签章后的文件
- 签章元数据(ASN.1 编码的 SES_Signature)
PYTHON
def create_electronic_seal(
document: bytes,
private_key_handle: int, # 密码机返回的句柄
cert_chain: list[bytes], # 证书链 DER 编码
seal_position: dict, # {page: int, x: float, y: float}
timestamp_request: bool = False
) -> dict:
"""
创建电子签章
返回: {
'signed_document': bytes,
'signature_info': SES_Signature ASN.1,
'timestamp': bytes | None
}
"""
# 1. 调用密码机进行 SM2 签名
signature = call_crypto_device(
op='SM2_SIGN',
key_handle=private_key_handle,
data=sm3_hash(document),
algorithm='SM2WithSM3' # OID: 1.2.156.10197.1.501
)
# 2. 构造签章数据结构(遵循 GM/T 0031)
seal_info = {
'header': 'ES',
'version': '1.0',
'vendor_id': 'XXX',
'seal_id': generate_seal_id(),
'cert_chain': cert_chain,
'signature': signature
}
# 3. 可选:获取时间戳
timestamp = None
if timestamp_request:
timestamp = call_timestamp_service(
data=sm3_hash(document),
algorithm='SM3'
)
# 4. 将签章嵌入文档
signed_doc = embed_seal_to_pdf(
document=document,
seal_info=seal_info,
position=seal_position,
timestamp=timestamp
)
return {
'signed_document': signed_doc,
'signature_info': encode_asn1(seal_info),
'timestamp': timestamp
}3.2 验签接口实现
关键检查点:
- 签名算法是否为 SM2WithSM3
- 证书链是否完整(签名证书 + 中间证书 + 根证书)
- 证书是否在有效期内
- 证书是否被吊销(CRL/OCSP)
- 时间戳是否有效(如要求)
PYTHON
def verify_electronic_seal(
document: bytes,
signature_info: bytes,
check_revocation: bool = True
) -> dict:
"""
验证电子签章
返回: {
'valid': bool,
'reason': str,
'cert_info': dict
}
"""
# 1. 解析 ASN.1 数据结构
seal_data = parse_asn1(signature_info)
# 2. 验证签名算法
if seal_data['algorithm'] != 'SM2WithSM3':
return {'valid': False, 'reason': '非国密算法'}
# 3. 验证证书链
cert_chain = seal_data['cert_chain']
if not verify_cert_chain(cert_chain):
return {'valid': False, 'reason': '证书链验证失败'}
# 4. 检查吊销状态
if check_revocation:
if not check_crl_or_ocsp(cert_chain):
return {'valid': False, 'reason': '证书已吊销'}
# 5. 验证签名值
signature = seal_data['signature']
public_key = cert_chain[0].public_key
if not verify_sm2_signature(public_key, sm3_hash(document), signature):
return {'valid': False, 'reason': '签名验证失败'}
# 6. 验证时间戳(如有)
if seal_data.get('timestamp'):
if not verify_timestamp(seal_data['timestamp'], sm3_hash(document)):
return {'valid': False, 'reason': '时间戳验证失败'}
return {
'valid': True,
'reason': '验证通过',
'cert_info': {
'subject': cert_chain[0].subject,
'issuer': cert_chain[0].issuer,
'valid_from': cert_chain[0].not_before,
'valid_to': cert_chain[0].not_after
}
}四、常见实现陷阱
4.1 陷阱一:ASN.1 编码错误
错误做法:
PYTHON
# ❌ 错误:使用 JSON 存储签章数据
seal_data = {
'algorithm': 'SM2WithSM3',
'signature': 'xxx',
'timestamp': 'yyy'
}正确做法:
PYTHON
# ✅ 正确:使用 ASN.1 DER 编码
from pyasn1.codec.der import encoder
from pyasn1.type import univ
class SES_Signature(univ.Sequence):
componentType = univ.OrderedDict([
('algorithm', univ.ObjectIdentifier()),
('signatureValue', univ.OctetString()),
('timestamp', univ.OctetString().optional())
])
seal_data = SES_Signature()
seal_data['algorithm'] = '1.2.156.10197.1.501' # SM2WithSM3
seal_data['signatureValue'] = signature_bytes
encoded = encoder.encode(seal_data)4.2 陷阱二:忽略证书吊销检查
密评要求:必须检查证书吊销状态。
实现建议:
PYTHON
def check_cert_revocation(cert_chain: list) -> bool:
"""
检查证书吊销状态
优先使用 OCSP,降级使用 CRL
"""
# 1. 尝试 OCSP 查询
try:
ocsp_url = cert_chain[0].extensions.get_ocsp_url()
if ocsp_url:
response = query_ocsp(ocsp_url, cert_chain[0])
if response.is_good:
return True
except Exception:
pass
# 2. 降级到 CRL 检查
crl_url = cert_chain[0].extensions.get_crl_url()
if crl_url:
crl = fetch_crl(crl_url)
return not crl.is_revoked(cert_chain[0].serial_number)
# 3. 都无法获取时,记录警告但不拒绝
log_warning("无法获取证书吊销状态,建议检查网络连接")
return True4.3 陷阱三:时间戳服务未集成
问题:很多系统只实现了签章,未集成时间戳服务。
影响:无法证明"签署时点",在纠纷中处于劣势。
解决方案:
PYTHON
def add_timestamp(seal_info: dict, timestamp_service_url: str) -> dict:
"""
添加可信时间戳
符合 GM/T 0033-2023 时间戳接口规范
"""
# 1. 构造时间戳请求
request = {
'version': 1,
'message_imprint': {
'hashAlgorithm': '1.2.156.10197.1.401', # SM3
'hashedMessage': sm3_hash(seal_info['document'])
},
'reqPolicy': '1.2.156.10197.2.1' # 政务时间戳策略
}
# 2. 调用时间戳服务
response = call_timestamp_service(
url=timestamp_service_url,
request=request
)
# 3. 验证时间戳响应
if not verify_timestamp_response(response):
raise ValueError("时间戳验证失败")
seal_info['timestamp'] = response
return seal_info五、密评合规检查清单
5.1 算法合规
| 检查项 | 要求 | 常见问题 |
|---|---|---|
| 签名算法 | SM2WithSM3 | 使用 RSA+SHA256 |
| 杂凑算法 | SM3 | 使用 SHA-256 |
| 证书算法 | SM2 | 使用 RSA 证书 |
| 时间戳算法 | SM3 | 使用 SHA-256 |
5.2 接口合规
| 检查项 | 要求 | 常见问题 |
|---|---|---|
| 接口定义 | 符合 GM/T 0131 | 自定义 JSON 接口 |
| 数据结构 | ASN.1 DER 编码 | 使用 XML/JSON |
| 参数传递 | 字节流 | 使用 Base64 字符串 |
5.3 密钥管理合规
| 检查项 | 要求 | 常见问题 |
|---|---|---|
| 私钥存储 | 密码机/密码卡 | 软存储(文件/内存) |
| 密钥生成 | 密码机内部生成 | 外部生成后导入 |
| 密钥备份 | 加密备份 | 明文备份 |
六、实施建议
6.1 分步实施路径
CODE
阶段1:基础对接(1-2周)
├── 选择国密 PDF/OFD SDK
├── 对接密码机接口
└── 实现基本签章/验签功能
阶段2:合规完善(1周)
├── 集成时间戳服务
├── 实现证书吊销检查
└── 完善日志审计
阶段3:优化提升(1周)
├── 批量签章优化
├── 性能调优
└── 异常处理完善6.2 选型建议
| 维度 | 建议 | 理由 |
|---|---|---|
| SDK 厂商 | 优先选择通过国密认证的厂商 | 降低合规风险 |
| 密码机 | 选择支持 SM2/SM3 的型号 | 基础要求 |
| 时间戳 | 选择符合 GM/T 0033 的服务 | 法律效力 |
6.3 成本控制
| 项目 | 预算区间 | 说明 |
|---|---|---|
| 国密 SDK | 5-20 万/年 | 按调用量计费 |
| 密码机 | 10-50 万 | 一次性投入 |
| 时间戳服务 | 1-5 万/年 | 按次计费 |
| 开发成本 | 3-5 人月 | 含测试 |
七、总结
GM/T 0131-2023 是电子签章系统国密改造的"最后一公里"。实施要点:
- 接口规范:使用 ASN.1 编码,不自定义 JSON/XML
- 算法合规:强制使用 SM2WithSM3,不降级使用 RSA
- 证书检查:必须实现吊销状态检查(OCSP/CRL)
- 时间戳:建议集成,增强法律效力
- 密钥管理:私钥必须存储在密码机内
参考来源
- GM/T 0131-2023《电子签章应用接口规范》
- GM/T 0031-2025《安全电子签章密码技术规范》
- GM/T 0047-2024《安全电子签章密码检测规范》
- GM/T 0033-2023《时间戳接口规范》