Quero assinar um JWT com uma chave de curva elíptica em Kotlin assim:
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())
}
Isso deve funcionar, pois recebo um JWT assinado com SECP256K1 de um serviço php e posso validá-lo perfeitamente. Para testes, quero criar meu próprio JWT da mesma maneira e ver como meu código lida com tokens expirados, declarações ausentes e assim por diante.
Mas quando executo o código acima, ele lança esta exceção:
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
Como posso assinar o JWT com o algoritmo SECP256K1?
Se bem entendi quando o algoritmo "EC" é definido, geralmente ele usará ECDSA para assinatura. Tente especificar o ECDSA diretamente e deve funcionar.