Skip to content

Commit 58c3073

Browse files
Merge pull request #1973 from walt-id/fix/jwk-key-verify-raw-js
fix: JS implementation of JWKKey signature validation
2 parents 6cf2801 + 3d5b40e commit 58c3073

2 files changed

Lines changed: 64 additions & 46 deletions

File tree

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import id.walt.crypto.keys.jwk.JWKKey
2+
import kotlinx.coroutines.test.runTest
3+
import kotlin.test.Test
4+
5+
class SignatureValidationTest {
6+
7+
@Test
8+
fun shouldValidateSignatureOfGoogleCertificate() = runTest {
9+
val key = JWKKey.importPEM(publicKeyPem).getOrThrow()
10+
val certTbs = certTbsHex.hexToByteArray()
11+
val signature = signatureHex.hexToByteArray()
12+
key.verifyRaw(signature, certTbs).getOrThrow()
13+
}
14+
15+
companion object {
16+
val publicKeyPem = """
17+
-----BEGIN PUBLIC KEY-----
18+
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE83Rzp2iLYK5DuDXFgTB7S0md+8Fhzube
19+
Rr1r1WEYNa5A3XP3iZEwWus87oV8okB2O6nGuEfYKueSkWpz6bFyOZ8pn6KY019e
20+
WIZlD6GEZQbR3IvJx3PIjGov5cSr0R2K
21+
-----END PUBLIC KEY-----
22+
""".trimIndent()
23+
24+
val certTbsHex = """
25+
30820225a00302010202107ff32d6b409d15d5965b05873a7c72e0300a06082a
26+
8648ce3d0403033047310b300906035504061302555331223020060355040a13
27+
19476f6f676c65205472757374205365727669636573204c4c43311430120603
28+
550403130b47545320526f6f74205234301e170d323331323133303930303030
29+
5a170d3239303232303134303030305a303b310b300906035504061302555331
30+
1e301c060355040a1315476f6f676c6520547275737420536572766963657331
31+
0c300a060355040313035745323059301306072a8648ce3d020106082a8648ce
32+
3d03010703420004357e1ff214ed907de19e2a344386c1d596e82770df9e04cb
33+
a9ca86790b084d468ac274a4bbd9bfeefd23d738f34bef5417e1bee7ca5525a8
34+
0c30ac2d5d4ea151a381fe3081fb300e0603551d0f0101ff040403020186301d
35+
0603551d250416301406082b0601050507030106082b06010505070302301206
36+
03551d130101ff040830060101ff020100301d0603551d0e0416041475bec477
37+
ae89f644377dcfb1681f1d1aebdc3459301f0603551d23041830168014804cd6
38+
eb74ff4936a3d5d8fcb53ec56af0941d8c303406082b06010505070101042830
39+
26302406082b060105050730028618687474703a2f2f692e706b692e676f6f67
40+
2f72342e637274302b0603551d1f042430223020a01ea01c861a687474703a2f
41+
2f632e706b692e676f6f672f722f72342e63726c30130603551d20040c300a30
42+
08060667810c010201
43+
""".replace(Regex("\\s"), "")
44+
45+
val signatureHex = """
46+
306402300bbdb83655c835a3d2d97d3973d3f7f782b809d1816fe56445dbdeaa
47+
c00e45128fac93e81f60ec2e7e442c229491ecac02302fdf0c90764c2d6961d5
48+
4ffd98981884db34ea98ec9bcd8862ffd265e5336a9a0ced2349382f51bf91d0
49+
12a2c93838da
50+
""".replace(Regex("\\s"), "")
51+
}
52+
}

waltid-libraries/crypto/waltid-crypto/src/jsMain/kotlin/id/walt/crypto/keys/jwk/JWKKey.js.kt

Lines changed: 12 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -285,54 +285,20 @@ actual class JWKKey actual constructor(
285285
detachedPlaintext: ByteArray?,
286286
customSignatureAlgorithm: String?
287287
): Result<ByteArray> {
288-
/*runCatching {
289-
require(detachedPlaintext != null) { "Detached plaintext cannot be null." }
290-
291-
// Assume a method exists to get the public key in PEM format.
292-
val pemString = exportPEM()
293-
294-
// 1. Parse the public key from PEM format to a raw binary ArrayBuffer.
295-
val publicKeyData = parsePemToBinary(pemString)
296-
297-
// 2. Get the algorithm parameters required by the Web Crypto API.
298-
val jwsAlgorithm = keyType.jwsAlg
299-
val cryptoParams = getVerificationWebCryptoParams()
300-
301-
// 3. Import the public key to create a CryptoKey object for verification.
302-
val cryptoKey = WebCrypto.subtle.importKey(
303-
"spki", // Public key format for public keys
304-
publicKeyData, // The raw key data
305-
cryptoParams.importAlgorithm,
306-
true,
307-
arrayOf("verify") // Specify that this key will be used for verification.
308-
).await()
309-
310-
// 4. IMPORTANT: Ensure the signature is in the IEEE P1363 format required by `subtle.verify`.
311-
val p1363Signature = convertDERtoIEEEP1363(signed)
312-
val signatureBuffer = (p1363Signature as Int8Array).buffer
313-
314-
// 5. Call `subtle.verify` with the key, signature, and original data.
315-
val isValid = WebCrypto.subtle.verify(
316-
cryptoParams.signAlgorithm,
317-
cryptoKey,
318-
signatureBuffer,
319-
Uint8Array(detachedPlaintext.toTypedArray())
320-
).await()
321-
322-
// 6. Check the result and return the plaintext or throw an exception.
323-
if (isValid) {
324-
detachedPlaintext
325-
} else {
326-
throw IllegalArgumentException("Signature verification failed.")
327-
}*/
328-
329-
330288
return runCatching {
289+
//needs to be same as in JVM implementation
290+
val hashingAlgorithm = when (keyType) {
291+
KeyType.Ed25519 -> null
292+
KeyType.secp256k1 -> "SHA256"
293+
KeyType.secp256r1 -> "SHA256"
294+
KeyType.secp384r1 -> "SHA384"
295+
KeyType.secp521r1 -> "SHA512"
296+
KeyType.RSA -> "SHA256"
297+
KeyType.RSA3072 -> "SHA384"
298+
KeyType.RSA4096 -> "SHA512"
299+
}
331300
val verified = crypto.verify(
332-
when (keyType) {
333-
KeyType.Ed25519 -> null
334-
else -> "sha256"
335-
},
301+
hashingAlgorithm,
336302
detachedPlaintext ?: signed,
337303
getPublicKey().exportPEM(),
338304
signed

0 commit comments

Comments
 (0)