kotlinjwtbouncycastlesecp256k1

How to sign a JWT with SECP256K1?


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?


Solution

  • 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.