Cert App Digital Certificate
· · ·
题目进度 0 / 0 ✓ 0
ODTS-54: Cert App 数字证书与电子签章——合同签署的安全基础
目标读者:想理解 ODTS 合同签署中数字证书如何工作、签章流程、证书生命周期的 BA/PM
相关文档:ODTS-47 (安全架构), ODTS-17 (交易确认), ODTS-31 (合同运营)
为什么 BA/PM 需要理解数字证书
数字证书是衍生品合同签署的”最后一公里”——它把系统里的交易数据变成具有法律效力的文件。这个环节出故障,前面的所有流程都白费。
数字签名失败的真实代价:
- 签署延迟 = 确认书逾期: 交易确认书 (confirmation) 通常要求在 T+1 内签署。如果 Cert App 签名流程卡住(证书过期、短信验证码系统故障、CA 机构响应超时),运营无法完成签署。根据 ISDA 协议,确认书逾期未签 = 交易在法律上未确认。如果一笔交易在 T+2 才完成签署,而标的在这两天内下跌了 3%,客户可以主张”交易未确认,我不承担此亏损”。 对于 5000 万名义本金的交易,3% = 150 万的潜在争议敞口。
- 证书过期批量故障: 企业证书通常有效期 3-5 年,到期前需向 CA 机构续期。如果运营忘记提前续期,某个交易台的企业证书过期——所有合同签署中断。某券商曾发生过因证书过期,整个交易台半天无法签署合同。运营紧急联系 CA 机构加急续期(加急费 5000-10000 元),但半天内约 30 份确认书积压,其中 5 份逾期到了 T+2,客户投诉。
- 运营维护成本: 一个中型券商每年需要管理 3-5 张企业证书 + 10-20 张个人证书。每张证书的申请、安装、续期、吊销操作平均消耗运营 1-2 小时。每年证书管理总耗时约 30-50 小时——这不是开发工作,是运营必须用 Excel 跟踪的”隐形事务”。
- 短信验证码瓶颈: 签署流程中短信验证码失败(手机号错误、运营商网关故障),运营无法签署。替代方案:运营需要去合规部做线下身份核实,平均耗时 2-4 小时。 如果交易员需要紧急签署一笔当天起息的交易,这 2-4 小时的延迟意味着交易起息日推迟一天。
概述
Cert App 是 ODTS 的数字证书与电子签章服务,处理合同签署全流程——从短信验证、证书获取、数据签名到签章归档。其核心设计原则是 私钥不出服务器:签名操作在客户端(浏览器/USB Key)完成,Cert App 仅提供待签名数据和验证签名结果。
签署全流程
标准签署流程
运营打开合同 → 点击"签署"
│
▼ 第1步: 短信验证
GET /cert/sendSMS?usage=sign&mobile=138****0000
← 验证码已发送(6位数字)
│
▼ 第2步: 用户输入验证码,系统验证
│
▼ 第3步: 获取待签名数据
GET /cert/getDataToSign?contractId=SNB202507001&companyId=1001
← DataToSign JSON
│
▼ 第4步: 前端/本地调用证书私钥签名 dataToSign
│ (使用系统证书或 USB Key)
│
▼ 第5步: 提交签名结果
POST /cert/sign (signedData)
│
▼ 第6步: Cert App 验证签名
│ 用 certSn 对应的公钥验证 dataToSign 签名
│
▼ 第7步: 签署完成,合同归档
│ 合同 PDF 存至 HCP
│ 签署记录写入数据库
│
▼
Contract.confirmationStatus = SENT
DataToSign 数据结构
待签名数据是 Cert App 返回的 JSON 对象:
{
"signatureId": "SIG20250716001",
"dataToSign": "base64编码的合同摘要哈希",
"certSn": "12:34:56:78:9A:BC:DE:F0",
"digestAlg": "SHA-256",
"signingTime": "2025-07-16T10:30:00+08:00"
}
| 字段 | 说明 |
|---|---|
signatureId | 本次签署唯一标识 |
dataToSign | 合同文件的摘要哈希(Base64),待数字签名 |
certSn | 证书序列号,指定签署使用哪张数字证书 |
digestAlg | 摘要算法(SHA-256) |
signingTime | 签名时间戳 |
安全关键: dataToSign 是合同 PDF 的 SHA-256 摘要,而非全文。这意味着:
- Cert App 不需要持有合同全文即可完成签署
- 签名验证等价于对整份合同的背书——任何合同修改都会导致摘要不同
- 从
dataToSign无法反推出合同内容
短信验证 API
签署前强制 SMS 验证,防止未授权操作:
GET /cert/sendSMS?usage=sign&mobile=13800138000&companyId=1001
响应:
{
"code": "0",
"message": "验证码已发送",
"data": {
"smsId": "SMS20250716001",
"expireIn": 300
}
}
- 验证码有效期: 5 分钟
- 验证码使用一次后失效
usage参数区分:sign(签署),certManage(证书管理)
证书管理 API
Cert App 提供完整的数字证书生命周期管理:
| 端点 | 方法 | 用途 |
|---|---|---|
/userCertManager/getOneUserInfo | GET | 查询单条证书申请记录 |
/userCertManager/searchUserInfo | POST | 分页搜索证书申请 |
/userCertManager/searchContractInfo | POST | 分页搜索签署合同记录 |
/userCertManager/deleteOneUserInfo | POST | 删除证书申请 |
/userCertManager/importUserInfo | POST | 导入证书申请(含附件上传) |
证书申请导入字段:
POST /userCertManager/importUserInfo 请求体:
{
"userId": "operator01",
"companyId": 1001,
"contractType": "ISDA",
"certType": "CORPORATE",
"certData": "base64编码的证书文件",
"attachmentUrl": "/hcp/cert/import/snb2025070001.pfx"
}
证书类型
| 类型 | 用途 | 颁发 | 有效期限 |
|---|---|---|---|
| 企业证书 (CORPORATE) | 公司级合同签署 | CA 机构(如 CFCA) | 3-5 年 |
| 个人证书 (PERSONAL) | 个人操作员签署 | 企业内部 CA | 1-3 年 |
| 设备证书 (DEVICE) | 系统间身份认证 | 内部 | 1 年 |
签署记录查询
POST /userCertManager/searchContractInfo 分页查询签署历史:
{
"companyId": 1001,
"contractId": "SNB202507001",
"pageNum": 1,
"pageSize": 20
}
响应:
{
"code": "0",
"data": [{
"contractId": "SNB202507001",
"signatureId": "SIG20250716001",
"signingTime": "2025-07-16T10:30:00+08:00",
"certSn": "12:34:56:78:9A:BC:DE:F0",
"signerId": "operator01",
"status": "SIGNED"
}]
}
法律合规
Cert App 的数字签名满足以下法规要求:
- 《中华人民共和国电子签名法》第十三条:使用数字证书的签名被视为可靠的电子签名,与手写签名或盖章具有同等法律效力
- 抗抵赖性 (Non-repudiation):
signingTime+signedData可举证签署人、签署时间和签署内容 - 签名验证:任何第三方可以用证书公钥验证
dataToSign的签名是否有效
关键代码目录
eds-web-app/src/.../cert/
├── CertAppClient.java ← HTTP REST 客户端封装
├── DataToSign.java ← 待签名数据 VO
├── SignResult.java ← 签名结果 VO
└── UserCertManagerClient.java ← 证书管理客户端
odyssey/.../cert/
├── CertService.java ← Odyssey 侧签署服务
└── CertConfig.java ← Cert App 连接配置