我想在 Kotlin 中使用椭圆曲线密钥签署 JWT,如下所示:
import com.nimbusds.jose.JOSEObjectType
import com.nimbusds.jose.JWSAlgorithm
import com.nimbusds.jose.JWSHeader
import com.nimbusds.jose.crypto.ECDSASigner
import com.nimbusds.jwt.JWTClaimsSet
import com.nimbusds.jwt.SignedJWT
import org.bouncycastle.jce.provider.BouncyCastleProvider
import java.security.KeyPairGenerator
import java.security.Security
import java.security.interfaces.ECPrivateKey
import java.security.spec.ECGenParameterSpec
fun main() {
Security.addProvider(BouncyCastleProvider())
val ecKPGen = KeyPairGenerator.getInstance("EC", "BC")
ecKPGen.initialize(ECGenParameterSpec("secp256k1"))
val header = JWSHeader.Builder(JWSAlgorithm.ES256K)
.type(JOSEObjectType.JWT)
.build()
val payload = JWTClaimsSet.Builder()
.issuer("me")
.build()
val signedJWT = SignedJWT(header, payload)
val keyPair = ecKPGen.generateKeyPair()
signedJWT.sign(ECDSASigner(keyPair.private as ECPrivateKey)) // line 27, exception thrown here
println(signedJWT.serialize())
}
这应该可行,因为我从 php 服务获得了使用 SECP256K1 签名的 JWT,并且我可以很好地验证它。为了进行测试,我想以相同的方式创建自己的 JWT,并查看我的代码如何处理过期的令牌、丢失的声明等。
但是当我运行上面的代码时,它抛出了这个异常:
Exception in thread "main" com.nimbusds.jose.JOSEException: Curve not supported: org.bouncycastle.jce.spec.ECNamedCurveSpec@611889f4
at com.nimbusds.jose.crypto.ECDSASigner.sign(ECDSASigner.java:287)
at com.nimbusds.jose.JWSObject.sign(JWSObject.java:315)
at McveKt.main(mcve.kt:27)
at McveKt.main(mcve.kt)
Caused by: java.security.SignatureException: Curve not supported: org.bouncycastle.jce.spec.ECNamedCurveSpec@611889f4
at jdk.crypto.ec/sun.security.ec.ECDSASignature.engineSign(ECDSASignature.java:485)
at java.base/java.security.Signature$Delegate.engineSign(Signature.java:1423)
at java.base/java.security.Signature.sign(Signature.java:712)
at com.nimbusds.jose.crypto.ECDSASigner.sign(ECDSASigner.java:283)
... 3 more
如何使用 SECP256K1 算法对 JWT 进行签名?
如果我理解正确时设置“EC”算法,那么它通常会使用 ECDSA 进行签名。尝试直接指定 ECDSA,它应该可以工作。