Android端基于EC私钥生成DER格式ECDSA SHA256 X-Signature咨询
Android端ECDSA(SHA256)生成X-Signature实现方案
该需求完全可实现,你现有逻辑大部分正确,仅输出环节存在错误,以下是具体问题说明和修正方案
疑问解答
- 关于update方法入参:你理解的完全正确,就是传入X-Timestamp字符串的字节数组,注意显式指定UTF-8字符集,避免不同系统默认字符集差异导致签名不一致。
- 关于X-Timestamp与签名逻辑的关联:你当前的写法已经完成了关联逻辑——把时间戳转成字符串后传入update方法,Signature实例会对该内容做SHA256摘要,再用EC私钥做签名,只要验签侧传入完全相同的时间戳字符串即可完成验签。
- 关于DER格式输出:
SHA256withECDSA算法的sign()方法返回的字节数组本身就是标准DER格式的签名结果,你现有代码错误使用了Base64编码,而需求要求的是DER字节数组转十六进制字符串(你给出的预期输出示例就是典型的十六进制格式)。
修正后的完整实现代码
1. 补充字节数组转十六进制字符串工具方法
fun ByteArray.toHexString(): String { return joinToString("") { "%02x".format(it) } }
2. 完整签名流程代码
// 1. 解析EC私钥(你的私钥已移除头尾标识和空格,直接传入即可) val privateKeyString = "你处理好的无首尾无空格的私钥字符串" val sigBytes: ByteArray = Base64Utils.decode(privateKeyString) val privateKeySpec = PKCS8EncodedKeySpec(sigBytes) val keyFactory = KeyFactory.getInstance("EC") val privateKey : PrivateKey = keyFactory.generatePrivate(privateKeySpec) // 2. 生成不带毫秒的Unix时间戳,可直接作为X-Timestamp请求头使用 val unixTime = System.currentTimeMillis() / 1000L val xTimestamp = unixTime.toString() // 3. 执行签名 val signature: ByteArray = Signature.getInstance("SHA256withECDSA").run { initSign(privateKey) // 显式指定UTF-8字符集转字节数组,保证多端一致性 update(xTimestamp.toByteArray(Charsets.UTF_8)) sign() } // 4. DER字节数组转十六进制字符串,得到最终X-Signature val xSignature = signature.toHexString()
注意事项
- 如果使用Android系统自带的
android.util.Base64做私钥解码,需要指定flag为Base64.NO_WRAP,避免解码出错。 - 十六进制输出如果要求大写,把工具方法里的
%02x改成%02X即可。
内容的提问来源于stack exchange,提问作者Andrey Kijonok
相关产品推荐
相关产品推荐

