# SM2私钥配置说明 ## 概述 签名服务器支持多种方式配置私钥和公钥,您可以选择最适合您使用场景的方式。 --- ## 配置方式(按优先级从高到低) ### 1. 通过API接口传入(推荐)⭐ **优点**: - 最灵活,每次请求可以使用不同的私钥 - 支持多租户场景 - 无需重启服务器 - 私钥不需要存储在服务器上 **缺点**: - 需要在每次请求中传递私钥 - 需要客户端妥善保管私钥 **使用方法**: 签名时传入私钥: ```bash curl -X POST http://localhost:8888/api/sign \ -H "Content-Type: application/json" \ -d '{ "data": { "version": "1.0", "txnType": "20250", "reqOrgId": "201811200001003" }, "priKey": "您的64位十六进制私钥", "reqOrgNo": "您的机构号" }' ``` 验签时传入公钥: ```bash curl -X POST http://localhost:8888/api/verify \ -H "Content-Type: application/json" \ -d '{ "data": { "version": "1.0", "txnType": "20250" }, "sign": "签名字符串", "pubKey": "您的130位十六进制公钥", "reqOrgNo": "您的机构号" }' ``` --- ### 2. 通过命令行参数 **优点**: - 启动时指定,灵活方便 - 适合脚本自动化部署 **缺点**: - 私钥可能在进程列表中可见(不够安全) - 修改需要重启服务 **使用方法**: ```bash # 语法: java -cp "bin:lib/*" demo.com.SignServer [配置文件路径] [机构号] [私钥] [公钥] # 示例: java -cp "bin:lib/*" demo.com.SignServer \ "" \ "201811200001003" \ "3164EE0DF2BCA7A12309383E3305DD6563A28DFE53F65BBD60B3A1D7F80AC275" \ "046875695CDF1EF046ABB231FDAFA6DCA2AF1E5719EAC00DE80D65FEF03F8485DC9DCBBC10A9A46D565B4CDCEE3510F276209657CAE5BAC10C9678583A44F7F100" ``` --- ### 3. 通过环境变量(推荐用于生产环境)⭐ **优点**: - 相对安全,私钥不会出现在代码或命令行中 - 适合容器化部署(Docker、K8s) - 便于CI/CD集成 **缺点**: - 修改需要重启服务 **使用方法**: ```bash # 设置环境变量 export SM2_PRIVATE_KEY="您的64位十六进制私钥" export SLT_PUBLIC_KEY="您的130位十六进制公钥" export REQ_ORG_NO="您的机构号" # 启动服务 java -cp "bin:lib/*" demo.com.SignServer ``` Docker示例: ```bash docker run -d \ -e SM2_PRIVATE_KEY="您的私钥" \ -e SLT_PUBLIC_KEY="您的公钥" \ -e REQ_ORG_NO="您的机构号" \ -p 8888:8888 \ your-sign-server ``` --- ### 4. 通过配置文件 **优点**: - 集中管理配置 - 易于维护 - 支持多个配置项 **缺点**: - 私钥存储在文件中,需要注意文件权限 - 修改需要重启服务 **使用方法**: 1. 创建配置文件 `config.properties`: ```properties # 机构配置 reqOrgNo=201811200001003 # SM2私钥(64位十六进制) priKey=3164EE0DF2BCA7A12309383E3305DD6563A28DFE53F65BBD60B3A1D7F80AC275 # 平台公钥(130位十六进制) sltPubKey=046875695CDF1EF046ABB231FDAFA6DCA2AF1E5719EAC00DE80D65FEF03F8485DC9DCBBC10A9A46D565B4CDCEE3510F276209657CAE5BAC10C9678583A44F7F100 ``` 2. 设置文件权限(重要!): ```bash chmod 600 config.properties ``` 3. 启动服务: ```bash # 使用默认配置文件(config.properties) java -cp "bin:lib/*" demo.com.SignServer # 或指定配置文件路径 java -cp "bin:lib/*" demo.com.SignServer /path/to/your/config.properties ``` --- ### 5. 代码中的默认配置 **优点**: - 开箱即用,适合快速测试 **缺点**: - 不安全,不适合生产环境 - 私钥写死在代码中 - 修改需要重新编译 **使用方法**: 修改 `SignServer.java` 文件: ```java // 请求机构号 private static String reqOrgNo = "您的机构号"; // 请求机构的私钥 private static String priKey = "您的SM2私钥"; // 平台给商户的公钥 private static String sltPubKey = "您的SM2公钥"; ``` 然后重新编译并启动。 --- ## 配置优先级 当多种配置方式同时存在时,优先级为: ``` API接口传入 > 命令行参数 > 环境变量 > 配置文件 > 代码默认值 ``` **说明**: - 高优先级的配置会覆盖低优先级的配置 - 如果某个参数在高优先级中未设置,则使用低优先级的值 --- ## 使用场景建议 ### 场景1:开发测试 **建议**: 使用 **API接口传入** 或 **配置文件** - 快速测试不同的密钥 - 便于调试 ### 场景2:生产环境(单机部署) **建议**: 使用 **配置文件** + 严格的文件权限 - 集中管理 - 注意设置 `chmod 600` 保护配置文件 ### 场景3:生产环境(容器化) **建议**: 使用 **环境变量** 或 **Secret管理** - 与Kubernetes Secrets或Docker Secrets集成 - 不将私钥写入镜像 ### 场景4:多租户SaaS服务 **建议**: 使用 **API接口传入** - 每个租户使用自己的密钥 - 服务器不存储任何私钥 - 最安全的方案 --- ## 安全建议 ### ⚠️ 重要安全提示 1. **永远不要将私钥提交到代码仓库** ```bash # 添加到 .gitignore config.properties *.key ``` 2. **使用配置文件时,严格限制文件权限** ```bash chmod 600 config.properties chown app_user:app_group config.properties ``` 3. **生产环境建议使用密钥管理服务** - AWS KMS - Azure Key Vault - HashiCorp Vault 4. **启用HTTPS** - 如果通过API传递私钥,必须使用HTTPS - 防止私钥在网络传输中被窃取 5. **日志脱敏** - 服务器日志中会隐藏私钥中间部分 - 格式:`3164EE0D...F80AC275` --- ## SM2密钥格式说明 ### 私钥格式 - **长度**: 64位十六进制字符(32字节) - **示例**: `3164EE0DF2BCA7A12309383E3305DD6563A28DFE53F65BBD60B3A1D7F80AC275` - **字符集**: 0-9, A-F(大小写均可) ### 公钥格式(非压缩) - **长度**: 130位十六进制字符(65字节) - **前缀**: 04(表示非压缩格式) - **示例**: `046875695CDF1EF046ABB231FDAFA6DCA2AF1E5719EAC00DE80D65FEF03F8485DC9DCBBC10A9A46D565B4CDCEE3510F276209657CAE5BAC10C9678583A44F7F100` --- ## 常见问题 ### Q1: 私钥格式错误怎么办? **A**: 确保私钥是64位的十六进制字符串,不包含空格、换行等其他字符。 ### Q2: 可以在一次请求中只传私钥,不传机构号吗? **A**: 可以,如果不传机构号,会使用服务器配置的默认机构号。 ### Q3: API传入的私钥会被服务器保存吗? **A**: 不会,私钥仅在当次请求中使用,请求结束后立即释放,不会持久化存储。 ### Q4: 多个客户端可以使用不同的私钥吗? **A**: 可以,通过API接口传入私钥的方式,每个客户端都可以使用自己的私钥。 --- ## 快速测试 启动服务器后,测试不同配置方式: ```bash # 测试1:使用服务器默认配置 curl -X POST http://localhost:8888/api/sign \ -H "Content-Type: application/json" \ -d '{"data": {"version": "1.0"}}' # 测试2:传入自定义私钥 curl -X POST http://localhost:8888/api/sign \ -H "Content-Type: application/json" \ -d '{ "data": {"version": "1.0"}, "priKey": "3164EE0DF2BCA7A12309383E3305DD6563A28DFE53F65BBD60B3A1D7F80AC275", "reqOrgNo": "TEST123" }' ``` --- ## 总结 选择合适的配置方式取决于您的具体需求: | 配置方式 | 灵活性 | 安全性 | 适用场景 | |---------|--------|--------|----------| | API传入 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 多租户、SaaS | | 命令行参数 | ⭐⭐⭐⭐ | ⭐⭐ | 脚本部署 | | 环境变量 | ⭐⭐⭐ | ⭐⭐⭐⭐ | 容器化部署 | | 配置文件 | ⭐⭐ | ⭐⭐⭐ | 单机部署 | | 代码默认值 | ⭐ | ⭐ | 仅供测试 | **生产环境推荐**: API传入(多租户)或 环境变量(单租户)