Android Kotlin用BouncyCastle实现PS256验签遇算法不存在异常求助
问题
在Android平台使用Kotlin结合BouncyCastle实现PS256签名验证时,查阅文档得知BouncyCastle支持SHA256withRSAandMGF1算法,但运行时抛出「无此算法」异常,请求解决。
相关实现代码:
fun verifySignedContent(cert: String, jwtS: String): Boolean { val certFactory: CertificateFactory = CertificateFactory.getInstance("X.509") val bytes = ByteArrayInputStream(cert.toByteArray()) Security.addProvider(BouncyCastleProvider()) val signedJWT = SignedJWT.parse(jwtS) val signature = signedJWT.signature val sig = Signature.getInstance("SHA256withRSAandMGF1", "BC") println("Signature: " + signature.toJSONString()) sig.initVerify(certFactory.generateCertificate(bytes)) sig.update(signature.decode()) val flagSig = sig.verify(signedJWT.signature.decode()) println("Signature is valid: $flagSig") return flagSig }
已添加的Gradle依赖:
implementation 'org.bouncycastle:bcprov-jdk18on:1.71' implementation 'org.bouncycastle:bcpkix-jdk18on:1.71'
解决方案
- 修正算法名称:PS256对应的标准算法标识在BouncyCastle中是
SHA256withRSA/PSS,而非SHA256withRSAandMGF1——后者不是Java兼容的标准算法命名,这是导致「无此算法」异常的核心原因。 - 提前加载Provider:将
Security.addProvider(BouncyCastleProvider())放在所有加密操作之前,确保BouncyCastle被优先作为算法提供者。 - 修正验证输入数据:签名验证需要对JWT的原始签名输入(header与payload通过
.拼接的字节数据)进行哈希,而非直接传入签名值。可通过SignedJWT的signingInput属性直接获取该数据。 - 明确PSS参数(可选但推荐):手动配置
PSSParameterSpec,指定哈希算法、MGF1参数、盐长度(PS256对应32字节),确保与签名生成端的参数完全一致,避免因默认参数差异导致验证失败。
修正后的代码:
fun verifySignedContent(cert: String, jwtS: String): Boolean { // 优先加载BouncyCastle Provider Security.addProvider(BouncyCastleProvider()) // 指定BC作为证书工厂的提供者 val certFactory = CertificateFactory.getInstance("X.509", "BC") val certInputStream = ByteArrayInputStream(cert.toByteArray()) val x509Cert = certFactory.generateCertificate(certInputStream) as X509Certificate val signedJWT = SignedJWT.parse(jwtS) // 使用正确的PS256对应算法名称 val sig = Signature.getInstance("SHA256withRSA/PSS", "BC") // 配置符合PS256标准的PSS参数 val pssSpec = PSSParameterSpec( "SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, // PS256要求盐长度等于哈希长度(SHA256为32字节) 1 ) sig.setParameter(pssSpec) sig.initVerify(x509Cert.publicKey) // 更新JWT的签名输入数据(header + "." + payload) sig.update(signedJWT.signingInput) // 验证签名值 val isValid = sig.verify(signedJWT.signature.decode()) println("Signature is valid: $isValid") return isValid }
内容的提问来源于stack exchange,提问作者Sarthak
相关产品推荐
相关产品推荐

