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

SHA1withRSA算法签名验证时公钥解析及验签失败问题求助

RSA签名校验问题根因与解决方案

初始公钥解析报错原因

初始抛出InvalidKeySpecException的核心原因是你使用的原始公钥为SSH-RSA格式,而X509EncodedKeySpec仅支持解析X.509/SPKI格式的公钥二进制流,两者编码结构完全不同,无法直接解析。

公钥解析成功但验签失败的排查方案

  • *签名值编码问题:你当前代码直接调用encryptedData.toByteArray()是把字符串直接转成字节数组,绝大多数场景下后端返回的签名是Base64编码后的字符串,你需要先对其做Base64解码后再传入verify方法,而不是直接转字节数组,这是验签失败最高发的原因。
  • *待签名字符集问题:你调用rawData.toByteArray()默认使用系统默认字符集,Android默认是UTF-8,要确认后端签名时使用的字符集是否和端侧完全一致,建议显式指定字符集避免差异。
  • *算法与填充方式差异:确认后端签名使用的算法是否确实是SHA1withRSA,部分场景下后端可能实际使用的是SHA256withRSA等其他算法;同时确认后端签名使用的RSA填充方式需要和端侧默认的PKCS#1 v1.5填充保持一致。
  • *公钥参数校验:可以打印解析后公钥的modulus和exponent参数,和后端私钥对应的公钥参数做对比,避免公钥转换过程出错。

修正后的参考代码

private fun verifySignature(rawData: String, encryptedData: String){
    // 先对Base64编码的签名值解码
    val signature: ByteArray = decode(encryptedData, DEFAULT)
    try {
       val key: PublicKey = loadPublicKeyPKCS()
       val s = Signature.getInstance("SHA1withRSA")
               .apply {
                    initVerify(key)
                    // 显式指定字符集
                    update(rawData.toByteArray(StandardCharsets.UTF_8))
               }
       val valid: Boolean = s.verify(signature)
       Log.i("Utils", "验签结果:$valid")
     }catch (e: Exception){
        Log.i("Utils", "verifySignatureException: $e")
     }
}

private fun loadPublicKeyPKCS(): PublicKey {
        val data: ByteArray = decode(BuildConfig.signature_key.toByteArray(), DEFAULT)
        val spec = X509EncodedKeySpec(data)
        val fact = KeyFactory.getInstance("RSA")
        return fact.generatePublic(spec)
    }

内容的提问来源于stack exchange,提问作者Martin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 02:12:03