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
相关产品推荐
相关产品推荐

