You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.13 11:06:02