Stefan Oltmann
12/07/2023, 3:51 PMOleg Yukhnevich
12/07/2023, 4:24 PMcryptogrpahy-kotlin
instead of JDK APIs): https://github.com/PhilJay/JWT/blob/master/src/main/java/com/philjay/jwt/JWT.kt
overall to verify you just need to split header+payload and signature and then call one function. F.e. if you already know the algorithm (after parsing header), you can do something like this:
val token: String = ...
val headerAndPayload = token.substringBeforeLast(".")
val signature = token.substringAfterLast(".")
// here goes cryptography-kotlin code
val result: Boolean = CryptographyProvider.Default.get(RSA.PKCS1) // or other algorithm, depending on what is in token
.publicKeyDecoder(SHA256) // or other algorithm, depending on what is in token
.decodeFrom(KEY_FORMAT, KEY_DATA) // depending on public key format
.signatureVerifier() // this will return SignatureVerifier which can be cached and used to verify any amount of signatures
.verifySignature(headerAndPayload.encodeToByteArray(), signature.encodeToByteArray())
David Kanenwisher
12/07/2023, 4:25 PMStefan Oltmann
12/07/2023, 4:28 PMStefan Oltmann
12/07/2023, 4:32 PMOleg Yukhnevich
12/07/2023, 4:46 PMI wonder why no one build and released a JWT library for this so faryou can be first 🙂 Also, I was thinking of including this functionality into
cryptography-kotlin
someday, though, there a lot more other foundational things need to be done 🙂
There are potentially a lot of pitfalls in rolling your own JWT verification codeAs far as I remember, JWT/JOSE/etc have rather simple specs but of course I can not know everything upfront But what you've send is for OAuth, which is a little different thing, and yes, it's much harder to make it right Overall, all time, if there is a possibility, it's better to use something already existing via expect/actual - this is BTW the underlying principle which l used in cryptography-kotlin 🙂
David Kanenwisher
12/07/2023, 4:57 PMStefan Oltmann
12/08/2023, 3:08 PMval kf = KeyFactory.getInstance("RSA")
val modulus = BigInteger(1, decoder.decode(n))
val exponent = BigInteger(1, decoder.decode(e))
return kf.generatePublic(RSAPublicKeySpec(modulus, exponent))
val rsaSignature = Signature.getInstance(verifyAlgorithm)
rsaSignature.initVerify(rsa)
rsaSignature.update(header)
rsaSignature.update(tokenDelimiter.code.toByte())
rsaSignature.update(payload)
rsaSignature.verify(tokenSignature)
Stefan Oltmann
12/08/2023, 3:08 PMStefan Oltmann
12/08/2023, 3:09 PMStefan Oltmann
12/08/2023, 3:11 PM