I want to sign a JWT with an elliptic curve key in Kotlin like this:
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())
}
This should work, as I get a JWT signed with SECP256K1 from a php service and I can validate it fine. For testing, I want to create my own JWT in the same way, and see how my code handles expired tokens, missing claims, and so on.
But when I run the above code, it throws this exception:
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
How can I sign the JWT with the SECP256K1 algorithm?
If I understand right when "EC" algorithm is set then it will generally use ECDSA for signing. Try to specify ECDSA directly and it should work.