Skip to content

Commit 3ea21b7

Browse files
committed
Added twin extensions for jwt parser using cryptography-kotlin types
1 parent 8484024 commit 3ea21b7

File tree

3 files changed

+449
-24
lines changed

3 files changed

+449
-24
lines changed

lib/src/commonMain/kotlin/co/touchlab/kjwt/ext/JwtBuilderExt.kt

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ import dev.whyoleg.cryptography.algorithms.EC
1111
import dev.whyoleg.cryptography.algorithms.ECDSA
1212
import dev.whyoleg.cryptography.algorithms.HMAC
1313
import dev.whyoleg.cryptography.algorithms.RSA
14-
import dev.whyoleg.cryptography.algorithms.SHA256
15-
import dev.whyoleg.cryptography.algorithms.SHA384
16-
import dev.whyoleg.cryptography.algorithms.SHA512
1714

1815
/**
1916
* Signs the JWT using an HMAC algorithm with a key decoded from a String.
@@ -33,13 +30,8 @@ public suspend fun JwtBuilder.signWith(
3330
val parsedKey =
3431
CryptographyProvider.Default
3532
.get(HMAC)
36-
.keyDecoder(
37-
when (algorithm) {
38-
SigningAlgorithm.HS256 -> SHA256
39-
SigningAlgorithm.HS384 -> SHA384
40-
SigningAlgorithm.HS512 -> SHA512
41-
},
42-
).decodeFromByteArray(keyFormat, key.encodeToByteArray())
33+
.keyDecoder(algorithm.digest)
34+
.decodeFromByteArray(keyFormat, key.encodeToByteArray())
4335

4436
return signWith(algorithm, parsedKey, keyId)
4537
}
@@ -62,13 +54,8 @@ public suspend fun JwtBuilder.signWith(
6254
val parsedKey =
6355
CryptographyProvider.Default
6456
.get(RSA.PKCS1)
65-
.privateKeyDecoder(
66-
when (algorithm) {
67-
SigningAlgorithm.RS256 -> SHA256
68-
SigningAlgorithm.RS384 -> SHA384
69-
SigningAlgorithm.RS512 -> SHA512
70-
},
71-
).decodeFromByteArray(keyFormat, key.encodeToByteArray())
57+
.privateKeyDecoder(algorithm.digest)
58+
.decodeFromByteArray(keyFormat, key.encodeToByteArray())
7259

7360
return signWith(algorithm, parsedKey, keyId)
7461
}
@@ -91,13 +78,8 @@ public suspend fun JwtBuilder.signWith(
9178
val parsedKey =
9279
CryptographyProvider.Default
9380
.get(RSA.PSS)
94-
.privateKeyDecoder(
95-
when (algorithm) {
96-
SigningAlgorithm.PS256 -> SHA256
97-
SigningAlgorithm.PS384 -> SHA384
98-
SigningAlgorithm.PS512 -> SHA512
99-
},
100-
).decodeFromByteArray(keyFormat, key.encodeToByteArray())
81+
.privateKeyDecoder(algorithm.digest)
82+
.decodeFromByteArray(keyFormat, key.encodeToByteArray())
10183

10284
return signWith(algorithm, parsedKey, keyId)
10385
}
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package co.touchlab.kjwt.ext
2+
3+
import co.touchlab.kjwt.cryptography.SimpleKey
4+
import co.touchlab.kjwt.model.algorithm.EncryptionAlgorithm
5+
import co.touchlab.kjwt.model.algorithm.SigningAlgorithm
6+
import co.touchlab.kjwt.parser.JwtParserBuilder
7+
import dev.whyoleg.cryptography.CryptographyProvider
8+
import dev.whyoleg.cryptography.algorithms.EC
9+
import dev.whyoleg.cryptography.algorithms.ECDSA
10+
import dev.whyoleg.cryptography.algorithms.HMAC
11+
import dev.whyoleg.cryptography.algorithms.RSA
12+
13+
/**
14+
* Registers an HMAC verification key decoded from a String.
15+
*
16+
* @param algorithm the HMAC-based signing algorithm (HS256, HS384, or HS512).
17+
* @param key the HMAC key material encoded as a String.
18+
* @param keyFormat the format in which [key] is encoded.
19+
* @param keyId optional key ID to associate with this verifier; when set, only tokens whose `kid`
20+
* header matches will use this key. Defaults to `null` (matches any token).
21+
* @return this builder for chaining.
22+
*/
23+
public suspend fun JwtParserBuilder.verifyWith(
24+
algorithm: SigningAlgorithm.HashBased,
25+
key: String,
26+
keyFormat: HMAC.Key.Format,
27+
keyId: String? = null,
28+
): JwtParserBuilder {
29+
val parsedKey =
30+
CryptographyProvider.Default
31+
.get(HMAC)
32+
.keyDecoder(algorithm.digest)
33+
.decodeFromByteArray(keyFormat, key.encodeToByteArray())
34+
35+
return verifyWith(algorithm, parsedKey, keyId)
36+
}
37+
38+
/**
39+
* Registers an RSA PKCS#1 public key decoded from a String for JWS signature verification.
40+
*
41+
* @param algorithm the RSA PKCS#1-based signing algorithm (RS256, RS384, or RS512).
42+
* @param key the RSA public key material encoded as a String.
43+
* @param keyFormat the format in which [key] is encoded.
44+
* @param keyId optional key ID to associate with this verifier; when set, only tokens whose `kid`
45+
* header matches will use this key. Defaults to `null` (matches any token).
46+
* @return this builder for chaining.
47+
*/
48+
public suspend fun JwtParserBuilder.verifyWith(
49+
algorithm: SigningAlgorithm.PKCS1Based,
50+
key: String,
51+
keyFormat: RSA.PublicKey.Format,
52+
keyId: String? = null,
53+
): JwtParserBuilder {
54+
val parsedKey =
55+
CryptographyProvider.Default
56+
.get(RSA.PKCS1)
57+
.publicKeyDecoder(algorithm.digest)
58+
.decodeFromByteArray(keyFormat, key.encodeToByteArray())
59+
60+
return verifyWith(algorithm, parsedKey, keyId)
61+
}
62+
63+
/**
64+
* Registers an RSA PSS public key decoded from a String for JWS signature verification.
65+
*
66+
* @param algorithm the RSA PSS-based signing algorithm (PS256, PS384, or PS512).
67+
* @param key the RSA public key material encoded as a String.
68+
* @param keyFormat the format in which [key] is encoded.
69+
* @param keyId optional key ID to associate with this verifier; when set, only tokens whose `kid`
70+
* header matches will use this key. Defaults to `null` (matches any token).
71+
* @return this builder for chaining.
72+
*/
73+
public suspend fun JwtParserBuilder.verifyWith(
74+
algorithm: SigningAlgorithm.PSSBased,
75+
key: String,
76+
keyFormat: RSA.PublicKey.Format,
77+
keyId: String? = null,
78+
): JwtParserBuilder {
79+
val parsedKey =
80+
CryptographyProvider.Default
81+
.get(RSA.PSS)
82+
.publicKeyDecoder(algorithm.digest)
83+
.decodeFromByteArray(keyFormat, key.encodeToByteArray())
84+
85+
return verifyWith(algorithm, parsedKey, keyId)
86+
}
87+
88+
/**
89+
* Registers an ECDSA public key decoded from a String for JWS signature verification.
90+
*
91+
* @param algorithm the ECDSA-based signing algorithm (ES256, ES384, or ES512).
92+
* @param key the EC public key material encoded as a String.
93+
* @param keyFormat the format in which [key] is encoded.
94+
* @param keyId optional key ID to associate with this verifier; when set, only tokens whose `kid`
95+
* header matches will use this key. Defaults to `null` (matches any token).
96+
* @return this builder for chaining.
97+
*/
98+
public suspend fun JwtParserBuilder.verifyWith(
99+
algorithm: SigningAlgorithm.ECDSABased,
100+
key: String,
101+
keyFormat: EC.PublicKey.Format,
102+
keyId: String? = null,
103+
): JwtParserBuilder {
104+
val parsedKey =
105+
CryptographyProvider.Default
106+
.get(ECDSA)
107+
.publicKeyDecoder(algorithm.curve)
108+
.decodeFromByteArray(keyFormat, key.encodeToByteArray())
109+
110+
return verifyWith(algorithm, parsedKey, keyId)
111+
}
112+
113+
/**
114+
* Registers a direct key (`dir`) for JWE decryption from a raw [ByteArray].
115+
*
116+
* @param key the raw symmetric key bytes used for direct decryption.
117+
* @param keyAlgorithm the direct key encryption algorithm ([EncryptionAlgorithm.Dir]).
118+
* @param keyId optional key ID to associate with this decryptor; when set, only tokens whose `kid`
119+
* header matches will use this key. Defaults to `null` (matches any token).
120+
* @return this builder for chaining.
121+
*/
122+
public fun JwtParserBuilder.decryptWith(
123+
key: ByteArray,
124+
keyAlgorithm: EncryptionAlgorithm.Dir,
125+
keyId: String? = null,
126+
): JwtParserBuilder = decryptWith(keyAlgorithm, SimpleKey(key), keyId)
127+
128+
/**
129+
* Registers a direct key (`dir`) for JWE decryption from a UTF-8 String.
130+
*
131+
* The string is converted to bytes using UTF-8 encoding before being used as the symmetric key.
132+
*
133+
* @param key the symmetric key as a UTF-8 string.
134+
* @param keyAlgorithm the direct key encryption algorithm ([EncryptionAlgorithm.Dir]).
135+
* @param keyId optional key ID to associate with this decryptor; when set, only tokens whose `kid`
136+
* header matches will use this key. Defaults to `null` (matches any token).
137+
* @return this builder for chaining.
138+
*/
139+
public fun JwtParserBuilder.decryptWith(
140+
key: String,
141+
keyAlgorithm: EncryptionAlgorithm.Dir,
142+
keyId: String? = null,
143+
): JwtParserBuilder = decryptWith(key.encodeToByteArray(), keyAlgorithm, keyId)

0 commit comments

Comments
 (0)