From 1fb3ef7ec32f3ac5c8c64a6faa4ab461f0a9fb5b Mon Sep 17 00:00:00 2001 From: mikeplotean <101570226+mikeplotean@users.noreply.github.com> Date: Wed, 22 Nov 2023 17:16:14 +0200 Subject: [PATCH] test: crypto (#21) * test: crypto - import key * test: crypto - key serialization, minor refactor * test: crypto - export key * test: crypto - key sign * test: crypto - jvm-local-key-creator * test: crypto - jvm-local-key * test: crypto - signatures * test: added tse deserialization test, restructured test resources folder * test: refactor tse-key --- waltid-crypto/build.gradle.kts | 1 + .../kotlin/id/walt/crypto/keys/TSEKey.kt | 6 +- .../src/commonTest/kotlin/TSEKeyTest.kt | 139 ++++++++--- .../src/jvmTest/kotlin/ExportKeyTests.kt | 92 +++++++ .../src/jvmTest/kotlin/ImportKeyTests.kt | 131 ++++++++++ .../src/jvmTest/kotlin/ImportTestsJvm.kt | 166 ------------- waltid-crypto/src/jvmTest/kotlin/JWTTest.kt | 31 --- .../jvmTest/kotlin/JvmLocalKeyCreatorTest.kt | 135 ++++++++++ .../jvmTest/kotlin/KeySerializationTest.kt | 87 ------- .../jvmTest/kotlin/KeySerializationTests.kt | 79 ++++++ .../src/jvmTest/kotlin/KeySignTests.kt | 50 ++++ .../src/jvmTest/kotlin/LocalKeyTest.kt | 234 ++++++++++++++++++ waltid-crypto/src/jvmTest/kotlin/TestJvm.kt | 171 ++++++++++--- waltid-crypto/src/jvmTest/kotlin/TestUtils.kt | 12 + .../resources/jwk/ed25519.private.json | 9 + .../jvmTest/resources/jwk/ed25519.public.json | 8 + .../jvmTest/resources/jwk/rsa.private.json | 12 + .../src/jvmTest/resources/jwk/rsa.public.json | 6 + .../resources/jwk/secp256k1.private.json | 10 + .../resources/jwk/secp256k1.public.json | 9 + .../resources/jwk/secp256r1.private.json | 10 + .../resources/jwk/secp256r1.public.json | 9 + .../jvmTest/resources/pem/ed25519.private.pem | 6 + .../jvmTest/resources/pem/ed25519.public.pem | 3 + .../src/jvmTest/resources/pem/rsa.private.pem | 27 ++ .../src/jvmTest/resources/pem/rsa.public.pem | 9 + .../resources/pem/secp256k1.private.pem | 8 + .../resources/pem/secp256k1.public.pem | 4 + .../resources/pem/secp256r1.private.pem | 10 + .../resources/pem/secp256r1.public.pem | 4 + .../resources/public-bytes/ed25519.bin | 1 + .../jvmTest/resources/public-bytes/rsa.bin | Bin 0 -> 270 bytes .../resources/public-bytes/secp256k1.bin | Bin 0 -> 88 bytes .../resources/public-bytes/secp256r1.bin | Bin 0 -> 91 bytes .../serialized/local/ed25519.private.json | 4 + .../serialized/local/ed25519.public.json | 4 + .../serialized/local/rsa.private.json | 4 + .../serialized/local/rsa.public.json | 4 + .../serialized/local/secp256k1.private.json | 4 + .../serialized/local/secp256k1.public.json | 4 + .../serialized/local/secp256r1.private.json | 4 + .../serialized/local/secp256r1.public.json | 4 + .../serialized/tse/ed25519.private.json | 6 + .../serialized/tse/ed25519.public.json | 42 ++++ .../jvmTest/resources/signatures/ed25519.txt | 1 + .../src/jvmTest/resources/signatures/rsa.txt | 1 + .../resources/signatures/secp256k1.txt | 1 + .../resources/signatures/secp256r1.txt | 1 + 48 files changed, 1210 insertions(+), 353 deletions(-) create mode 100644 waltid-crypto/src/jvmTest/kotlin/ExportKeyTests.kt create mode 100644 waltid-crypto/src/jvmTest/kotlin/ImportKeyTests.kt delete mode 100644 waltid-crypto/src/jvmTest/kotlin/ImportTestsJvm.kt delete mode 100644 waltid-crypto/src/jvmTest/kotlin/JWTTest.kt create mode 100644 waltid-crypto/src/jvmTest/kotlin/JvmLocalKeyCreatorTest.kt delete mode 100644 waltid-crypto/src/jvmTest/kotlin/KeySerializationTest.kt create mode 100644 waltid-crypto/src/jvmTest/kotlin/KeySerializationTests.kt create mode 100644 waltid-crypto/src/jvmTest/kotlin/KeySignTests.kt create mode 100644 waltid-crypto/src/jvmTest/kotlin/LocalKeyTest.kt create mode 100644 waltid-crypto/src/jvmTest/kotlin/TestUtils.kt create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/ed25519.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/ed25519.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/rsa.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/rsa.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/secp256k1.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/secp256k1.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/secp256r1.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/jwk/secp256r1.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/pem/ed25519.private.pem create mode 100644 waltid-crypto/src/jvmTest/resources/pem/ed25519.public.pem create mode 100644 waltid-crypto/src/jvmTest/resources/pem/rsa.private.pem create mode 100644 waltid-crypto/src/jvmTest/resources/pem/rsa.public.pem create mode 100644 waltid-crypto/src/jvmTest/resources/pem/secp256k1.private.pem create mode 100644 waltid-crypto/src/jvmTest/resources/pem/secp256k1.public.pem create mode 100644 waltid-crypto/src/jvmTest/resources/pem/secp256r1.private.pem create mode 100644 waltid-crypto/src/jvmTest/resources/pem/secp256r1.public.pem create mode 100644 waltid-crypto/src/jvmTest/resources/public-bytes/ed25519.bin create mode 100644 waltid-crypto/src/jvmTest/resources/public-bytes/rsa.bin create mode 100644 waltid-crypto/src/jvmTest/resources/public-bytes/secp256k1.bin create mode 100644 waltid-crypto/src/jvmTest/resources/public-bytes/secp256r1.bin create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/rsa.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/rsa.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.private.json create mode 100644 waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.public.json create mode 100644 waltid-crypto/src/jvmTest/resources/signatures/ed25519.txt create mode 100644 waltid-crypto/src/jvmTest/resources/signatures/rsa.txt create mode 100644 waltid-crypto/src/jvmTest/resources/signatures/secp256k1.txt create mode 100644 waltid-crypto/src/jvmTest/resources/signatures/secp256r1.txt diff --git a/waltid-crypto/build.gradle.kts b/waltid-crypto/build.gradle.kts index 33be04543..ddeaae422 100644 --- a/waltid-crypto/build.gradle.kts +++ b/waltid-crypto/build.gradle.kts @@ -84,6 +84,7 @@ kotlin { val jvmTest by getting { dependencies { implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0") + implementation("org.junit.jupiter:junit-jupiter-params:5.9.0") } } publishing { diff --git a/waltid-crypto/src/commonMain/kotlin/id/walt/crypto/keys/TSEKey.kt b/waltid-crypto/src/commonMain/kotlin/id/walt/crypto/keys/TSEKey.kt index 2bcc8e484..02dafda38 100644 --- a/waltid-crypto/src/commonMain/kotlin/id/walt/crypto/keys/TSEKey.kt +++ b/waltid-crypto/src/commonMain/kotlin/id/walt/crypto/keys/TSEKey.kt @@ -31,7 +31,7 @@ class TSEKey( //private var publicKey: ByteArray? = null, //override var keyType: KeyType? = null private var _publicKey: ByteArray? = null, private var _keyType: KeyType? = null -) : id.walt.crypto.keys.Key() { +) : Key() { @Transient val retrievedKeyType by lazy { runBlocking { retrieveKeyType() } } @@ -168,7 +168,7 @@ class TSEKey( ?: throwTSEError("No keys/1/public_key in data response") ).value - override suspend fun getPublicKey(): id.walt.crypto.keys.Key { + override suspend fun getPublicKey(): Key { return LocalKey.importRawPublicKey( type = keyType, rawPublicKey = publicKey, @@ -274,4 +274,4 @@ suspend fun main() { println("Verified plaintext: ${verified.getOrNull()!!.decodeToString()}") tseKey.delete() -} +} \ No newline at end of file diff --git a/waltid-crypto/src/commonTest/kotlin/TSEKeyTest.kt b/waltid-crypto/src/commonTest/kotlin/TSEKeyTest.kt index d59e2835a..f65b97a27 100644 --- a/waltid-crypto/src/commonTest/kotlin/TSEKeyTest.kt +++ b/waltid-crypto/src/commonTest/kotlin/TSEKeyTest.kt @@ -7,44 +7,117 @@ import io.ktor.http.* import io.ktor.util.* import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.condition.EnabledIf -import kotlin.test.Test +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.Assumptions.assumeTrue +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.Arguments.arguments +import org.junit.jupiter.params.provider.MethodSource +import java.util.stream.Stream +import kotlin.streams.asStream +import kotlin.test.assertEquals +import kotlin.test.assertTrue class TSEKeyTest { + private val payload = JsonObject( + mapOf( + "sub" to JsonPrimitive("16bb17e0-e733-4622-9384-122bc2fc6290"), + "iss" to JsonPrimitive("http://localhost:3000"), + "aud" to JsonPrimitive("TOKEN"), + ) + ) + + fun getPublicKeyRepresentation() = runTest { - private suspend fun test(key: TSEKey) { - try { - println("TSEKey: $key") - val plaintext = "This is a plaintext for ${key.keyType.name}... 123".encodeToByteArray() - println("Plaintext: ${plaintext.decodeToString()}") - - val signed = key.signRaw(plaintext) as String - println("Signed: $signed") - - val verified = key.verifyRaw(signed.decodeBase64Bytes(), plaintext) - println("Verified signature success: ${verified.isSuccess}") - println("Verified plaintext: ${verified.getOrNull()!!.decodeToString()}") - } finally { - println("Deleting $key...") - key.delete() - } } - @Test - @EnabledIf("hostCondition") - fun testAll() = runTest { - val tseMetadata = TSEKeyMetadata("http://127.0.0.1:8200/v1/transit", "dev-only-token") + @ParameterizedTest + @MethodSource + fun getPublicKey(key: TSEKey?) = runTest { + assumeTrue(hostCondition()) + assumeTrue(key != null) + val publicKey = key!!.getPublicKey() + assertTrue(!publicKey.hasPrivateKey) + //TODO: assert keyId, thumbprint, export + } + + fun getKeyType() = runTest { + + } + + fun getHasPrivateKey() = runTest { + + } + + @ParameterizedTest + @MethodSource + fun signRaw(key: TSEKey?) = runTest { + assumeTrue(hostCondition()) + assumeTrue(key != null) + val signed = key!!.signRaw(payload.toString().encodeToByteArray()) as String + val verificationResult = key.verifyRaw(signed.decodeBase64Bytes(), payload.toString().encodeToByteArray()) + assertTrue(verificationResult.isSuccess) + assertEquals(payload.toString(), String(verificationResult.getOrThrow())) + } + + @ParameterizedTest + @MethodSource + fun signJws(key: TSEKey?) = runTest { + assumeTrue(hostCondition()) + val signed = key!!.signJws(payload.toString().encodeToByteArray()) + val verificationResult = key.verifyJws(signed) + assertTrue(verificationResult.isSuccess) + assertEquals(payload, verificationResult.getOrThrow()) + } + + fun getKeyId() = runTest { + + } + + fun verifyJws() = runTest { + + } + + fun exportJWK() = runTest { + + } + + fun exportJWKObject() = runTest { - listOf( - TSEKey.generate(KeyType.Ed25519, tseMetadata), - TSEKey.generate(KeyType.RSA, tseMetadata), - TSEKey.generate(KeyType.secp256r1, tseMetadata) - ).forEach { - test(it) - } } - private fun hostCondition() = runCatching { - runBlocking { HttpClient().get("http://127.0.0.1:8200") }.status == HttpStatusCode.OK - }.fold(onSuccess = { true }, onFailure = { false }) -} + fun exportPEM() = runTest { + + } + + companion object { + private var keys: List = listOf(null)//ugly way to have test parameterization and condition at once + + @JvmStatic + @BeforeAll + fun initKeys() = runTest { + hostCondition().takeIf { it }?.let { + val tseMetadata = TSEKeyMetadata("http://127.0.0.1:8200/v1/transit", "dev-only-token") + keys = enumValues().map { TSEKey.generate(KeyType.Ed25519, tseMetadata) } + } + } + @JvmStatic + @AfterAll + fun cleanup() = runTest { + keys.forEach { it?.delete() } + } + @JvmStatic + fun getPublicKey(): Stream = keys.map { arguments(it) }.asSequence().asStream() + @JvmStatic + fun signRaw(): Stream = keys.map { arguments(it) }.asSequence().asStream() + @JvmStatic + fun signJws(): Stream = keys.map { arguments(it) }.asSequence().asStream() + + private fun hostCondition() = runCatching { + runBlocking { HttpClient().get("http://127.0.0.1:8200") }.status == HttpStatusCode.OK + }.fold(onSuccess = { it }, onFailure = { false }) + } +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/kotlin/ExportKeyTests.kt b/waltid-crypto/src/jvmTest/kotlin/ExportKeyTests.kt new file mode 100644 index 000000000..a6081a5c2 --- /dev/null +++ b/waltid-crypto/src/jvmTest/kotlin/ExportKeyTests.kt @@ -0,0 +1,92 @@ +import TestUtils.loadJwkLocal +import TestUtils.loadPemLocal +import TestUtils.loadSerializedLocal +import id.walt.crypto.keys.KeySerialization +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.Arguments.arguments +import org.junit.jupiter.params.provider.MethodSource +import java.util.stream.Stream +import kotlin.test.assertEquals + +class ExportKeyTests { + + @ParameterizedTest + @MethodSource + fun `given key, when exporting jwk then the result is a valid jwk string`(keyFile: String, jwkFile: String) = + runTest { + // given + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + // when + val export = key.exportJWK() + // then + assertEquals(jwkFile.replace("\\s".toRegex(), ""), export) + } + + @ParameterizedTest + @MethodSource + fun `given key, when exporting JsonObject then the result is a valid jwk string`(keyFile: String, jwkFile: String) = runTest { + // given + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + // when + val export = key.exportJWKObject() + // then + assertEquals(jwkFile.replace("\\s".toRegex(), ""), export.toString()) + } + + @ParameterizedTest + @MethodSource + @Disabled // not implemented + fun `given key, when exporting pem then the result is a valid pem string`(keyFile: String, pemFile: String) = + runTest { + // given + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + // when + val export = key.exportPEM() + // then + assertEquals(pemFile, export) + } + + companion object { + @JvmStatic + fun `given key, when exporting jwk then the result is a valid jwk string`(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadJwkLocal("ed25519.private.json")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadJwkLocal("secp256k1.private.json")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadJwkLocal("secp256r1.private.json")), + arguments(loadSerializedLocal("rsa.private.json"), loadJwkLocal("rsa.private.json")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadJwkLocal("ed25519.public.json")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadJwkLocal("secp256k1.public.json")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadJwkLocal("secp256r1.public.json")), + arguments(loadSerializedLocal("rsa.public.json"), loadJwkLocal("rsa.public.json")), + ) + + @JvmStatic + fun `given key, when exporting JsonObject then the result is a valid jwk string`(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadJwkLocal("ed25519.private.json")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadJwkLocal("secp256k1.private.json")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadJwkLocal("secp256r1.private.json")), + arguments(loadSerializedLocal("rsa.private.json"), loadJwkLocal("rsa.private.json")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadJwkLocal("ed25519.public.json")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadJwkLocal("secp256k1.public.json")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadJwkLocal("secp256r1.public.json")), + arguments(loadSerializedLocal("rsa.public.json"), loadJwkLocal("rsa.public.json")), + ) + + @JvmStatic + fun `given key, when exporting pem then the result is a valid pem string`(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadPemLocal("ed25519.private.pem")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadPemLocal("secp256k1.private.pem")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadPemLocal("secp256r1.private.pem")), + arguments(loadSerializedLocal("rsa.private.json"), loadPemLocal("rsa.private.pem")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadPemLocal("ed25519.public.pem")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadPemLocal("secp256k1.public.pem")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadPemLocal("secp256r1.public.pem")), + arguments(loadSerializedLocal("rsa.public.json"), loadPemLocal("rsa.public.pem")), + ) + } +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/kotlin/ImportKeyTests.kt b/waltid-crypto/src/jvmTest/kotlin/ImportKeyTests.kt new file mode 100644 index 000000000..026b78c1d --- /dev/null +++ b/waltid-crypto/src/jvmTest/kotlin/ImportKeyTests.kt @@ -0,0 +1,131 @@ +import TestUtils.loadJwkLocal +import TestUtils.loadPemLocal +import TestUtils.loadResourceBytes +import id.walt.crypto.keys.KeyType +import id.walt.crypto.keys.LocalKey +import id.walt.crypto.keys.LocalKeyMetadata +import kotlinx.coroutines.test.runTest +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.Arguments.arguments +import org.junit.jupiter.params.provider.MethodSource +import java.util.stream.Stream +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class ImportKeyTests { + + @ParameterizedTest + @MethodSource + fun `given jwk string, when imported then the import succeeds having the correct key type, key id and hasPrivate values`( + keyString: String, keyType: KeyType, isPrivate: Boolean + ) = runTest { + // Importing + val imported = LocalKey.importJWK(keyString) + // Checking import success + assertTrue { imported.isSuccess } + // Getting key + val key = imported.getOrThrow() + // Checking for private key + assertEquals(isPrivate, key.hasPrivateKey) + // Checking for key type + assertEquals(keyType, key.keyType) + // Checking keyId from thumbprint + assertEquals(key.getThumbprint(), key.getKeyId()) + } + + @ParameterizedTest + @MethodSource + fun `given pem string, when imported then the import succeeds having the correct key type, key id and hasPrivate values`( + keyString: String, keyType: KeyType, isPrivate: Boolean + ) = runTest { + // Importing + val imported = LocalKey.importPEM(keyString) + // Checking import success + assertTrue { imported.isSuccess } + // Getting key + val key = imported.getOrThrow() + // Checking for private key + assertEquals(isPrivate, key.hasPrivateKey) + // Checking for key type + assertEquals(keyType, key.keyType) + // Checking keyId from thumbprint + assertEquals(key.getThumbprint(), key.getKeyId()) + } + + @ParameterizedTest + @MethodSource + fun `given raw string, when imported then the import succeeds having the correct key type, key id and hasPrivate values`( + bytes: ByteArray, keyType: KeyType, isPrivate: Boolean + ) = runTest { + // Importing + val key = LocalKey.importRawPublicKey(keyType, bytes, LocalKeyMetadata()) + // Checking for private key + assertEquals(isPrivate, key.hasPrivateKey) + // Checking for key type + assertEquals(keyType, key.keyType) + // Checking keyId from thumbprint + assertEquals(key.getThumbprint(), key.getKeyId()) + } + + + + companion object { + @JvmStatic + fun `given jwk string, when imported then the import succeeds having the correct key type, key id and hasPrivate values`(): Stream = + Stream.of( + // ed25519 + arguments(loadJwkLocal("ed25519.private.json"), KeyType.Ed25519, true), + // secp256k1 + arguments(loadJwkLocal("secp256k1.private.json"), KeyType.secp256k1, true), + // secp256r1 + arguments(loadJwkLocal("secp256r1.private.json"), KeyType.secp256r1, true), + // rsa + arguments(loadJwkLocal("rsa.private.json"), KeyType.RSA, true), + // public + // ed25519 + arguments(loadJwkLocal("ed25519.public.json"), KeyType.Ed25519, false), + // secp256k1 + arguments(loadJwkLocal("secp256k1.public.json"), KeyType.secp256k1, false), + // secp256r1 + arguments(loadJwkLocal("secp256r1.public.json"), KeyType.secp256r1, false), + // rsa + arguments(loadJwkLocal("rsa.public.json"), KeyType.RSA, false), + ) + + @JvmStatic + fun `given pem string, when imported then the import succeeds having the correct key type, key id and hasPrivate values`(): Stream = + Stream.of( + // ed25519 (not implemented) +// arguments(loadPem("ed25519.private.pem"), KeyType.Ed25519, true), + // secp256k1 + arguments(loadPemLocal("secp256k1.private.pem"), KeyType.secp256k1, true), + // secp256r1 + arguments(loadPemLocal("secp256r1.private.pem"), KeyType.secp256r1, true), + // rsa + arguments(loadPemLocal("rsa.private.pem"), KeyType.RSA, true), + // public + // ed25519 (not implemented) +// arguments(loadPem("ed25519.public.pem"), KeyType.Ed25519, false), + // secp256k1 + arguments(loadPemLocal("secp256k1.public.pem"), KeyType.secp256k1, false), + // secp256r1 + arguments(loadPemLocal("secp256r1.public.pem"), KeyType.secp256r1, false), + // rsa + arguments(loadPemLocal("rsa.public.pem"), KeyType.RSA, false), + ) + + @JvmStatic + fun `given raw string, when imported then the import succeeds having the correct key type, key id and hasPrivate values`(): Stream = + Stream.of( + arguments(loadResourceBytes("public-bytes/ed25519.bin"), KeyType.Ed25519, false), + // secp256r1 (throwing Invalid point encoding 0x30) +// arguments(loadResourceBytes("public-bytes/secp256k1.bin"), KeyType.secp256k1, false), + // secp256r1 (throwing Invalid point encoding 0x30) +// arguments(loadResourceBytes("public-bytes/secp256r1.bin"), KeyType.secp256r1, false), + // rsa (not implemented) +// arguments(loadResourceBytes("public-bytes/rsa.bin"), KeyType.RSA, false), + ) + + } +} diff --git a/waltid-crypto/src/jvmTest/kotlin/ImportTestsJvm.kt b/waltid-crypto/src/jvmTest/kotlin/ImportTestsJvm.kt deleted file mode 100644 index 34bdac6ab..000000000 --- a/waltid-crypto/src/jvmTest/kotlin/ImportTestsJvm.kt +++ /dev/null @@ -1,166 +0,0 @@ -import id.walt.crypto.keys.KeyType -import id.walt.crypto.keys.LocalKey -import kotlinx.coroutines.test.runTest -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.jsonObject -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue - -class ImportTestsJvm { - - private val privateKeyJsonString = """ - { - "kty": "RSA", - "kid": "288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A", - "n": "qV-fGqTo8r6L52sIJpt44bxLkODaF0_wvIL_eYYDL55H-Ap-b1q4pd4YyZb7pARor_1mob6sMRnnAr5htmO1XucmKBEiNY-12zza0q9smjLm3-eNqq-8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr-bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778-ECcxlM21-JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS_ASTy7MO0SqunpkGzj_H7uFbK9Np_dLIOr9ZqrkCSdioA_PgDyk36E8ayuMnN1HDy4ak_Q7yEX4R_C75T0JxuuYio06hugwyREgOQNID-DVUoLw", - "e": "AQAB", - "d": "hndR21ddUYqRi9JfkDcSSzSwUX8R5jwjBaaCqLoKQX3J6VR7eHBv889VooXplheh_UaSeorkLb9Atd7ruF-EmKmuk1S28gr79-hiWa3H7MvIm647vGz0Z9VbhxQpDm9vLVtILbyYh1DVyRzHjOm9n4UyNmQfqolMjzF81_p6DUfpkMcDBJSlsTmRKMWPG0u8mFm8aB9ZftbryPO36QOny7g4_M8SZG1yxGTbypjyDTP9WqMmHpaC-66gLszjyxwEbVh69m-HsDEs7Qg9oMVG2FiwtDSXIApwfLk2v2Yk4-TeAD49rZzw-QcJ0yqPeVdq8cgyFOhwX-cPtQIm8X7AgQ", - "p": "0bNpJzzOOgzpqaWkb-5PuUgY9AedUsnze24AtukXaN9VY7e5BLYcbE11RGeyj8kkhpotvZQ6WrYEfvSkfxBvoVc1q86FXiqlpwmUL-_jO4BbgESOK9eaWP1iWmWNrZpqwdnIeF3VZHfCIoFxRV_Tb_Sp8UNSueFgCH6IVJlfwSE", - "q": "zsTarRYo9lLE8XvzpGzpjtrOHsnLuk2n5GXP6M2X89BL8yc8_5Fp99m_Em9vGAOhZBK9ActZuZEGSVVhfV1ImGw17tLyQZSCAvSzQpZSYpT9EDeZgn_oSorfUgMKppm1X4rl5Yz7lMR1khljdKt_X6gFA6ADL2h_ARK1bBRjr08", - "dp": "lOfqTmN-KXiL39xwdM7rq6zHk1lo3KXtEIOfXEMOTXjxQJrwdaj_a-Rg1g8wm6uAFVicDFeaTFmdvazothWsvwuXYAWJbMGp2YASyytz1wehcea8ceNqhbB_y6L7RQA2uKp2EQrIgcwMfcYe8d1G3eQFXP2qW7XvJHj9Q92ZQiE", - "dq": "E7TDOpfQE5nT10f-8n7Gy6yi1GBbIEhiZewmIoPlpYEGnAfzUlAjj1GbWkBwkBNYgFcg2FjvFjZyKO8QOYh4cL5vbXGBUSq8MVfs9b2p4Gdervr9kGhsVR5jJkfP7gzcMlzkiDoliAopQmFVDzuBCjbTM4M-inglEo8b508SKRU", - "qi": "aJsDBhxQFDbpQr20TjgxImwBslVP9xIauy3ncCmjHix6Fc1l51gL71V1OWGnXaStGfoWy0gKkUnJuU3_X_xA_QwzAXPJYa-juRlD8BxTf7rmR_HC-XiVdyNnkU3afHtK4nShS2EuN2EXOrYDrbQoA13_a6Itk_55vDpJ3jciwS8" - } - """.trimIndent() - - - private val publicKeyJwkString = """ - { - "kty": "RSA", - "kid": "288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A", - "n": "qV-fGqTo8r6L52sIJpt44bxLkODaF0_wvIL_eYYDL55H-Ap-b1q4pd4YyZb7pARor_1mob6sMRnnAr5htmO1XucmKBEiNY-12zza0q9smjLm3-eNqq-8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr-bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778-ECcxlM21-JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS_ASTy7MO0SqunpkGzj_H7uFbK9Np_dLIOr9ZqrkCSdioA_PgDyk36E8ayuMnN1HDy4ak_Q7yEX4R_C75T0JxuuYio06hugwyREgOQNID-DVUoLw", - "e": "AQAB" - } - """.trimIndent() - - private val publicKeyPem = """ - -----BEGIN PUBLIC KEY----- - MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqV+fGqTo8r6L52sIJpt4 - 4bxLkODaF0/wvIL/eYYDL55H+Ap+b1q4pd4YyZb7pARor/1mob6sMRnnAr5htmO1 - XucmKBEiNY+12zza0q9smjLm3+eNqq+8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr+ - bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778+ECcxlM21+JaUjqMD0nQR6wl - 8L6oWGcR7PjcjPQAyuS/ASTy7MO0SqunpkGzj/H7uFbK9Np/dLIOr9ZqrkCSdioA - /PgDyk36E8ayuMnN1HDy4ak/Q7yEX4R/C75T0JxuuYio06hugwyREgOQNID+DVUo - LwIDAQAB - -----END PUBLIC KEY----- - """.trimIndent() - - private val privateKeyPem = """ - -----BEGIN RSA PRIVATE KEY----- - MIIEpAIBAAKCAQEAqV+fGqTo8r6L52sIJpt44bxLkODaF0/wvIL/eYYDL55H+Ap+ - b1q4pd4YyZb7pARor/1mob6sMRnnAr5htmO1XucmKBEiNY+12zza0q9smjLm3+eN - qq+8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr+bADVystQeonSPoRLqSoO78oAtonQ - WLX1MUfS9778+ECcxlM21+JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS/ASTy7MO0 - SqunpkGzj/H7uFbK9Np/dLIOr9ZqrkCSdioA/PgDyk36E8ayuMnN1HDy4ak/Q7yE - X4R/C75T0JxuuYio06hugwyREgOQNID+DVUoLwIDAQABAoIBAQCGd1HbV11RipGL - 0l+QNxJLNLBRfxHmPCMFpoKougpBfcnpVHt4cG/zz1WihemWF6H9RpJ6iuQtv0C1 - 3uu4X4SYqa6TVLbyCvv36GJZrcfsy8ibrju8bPRn1VuHFCkOb28tW0gtvJiHUNXJ - HMeM6b2fhTI2ZB+qiUyPMXzX+noNR+mQxwMElKWxOZEoxY8bS7yYWbxoH1l+1uvI - 87fpA6fLuDj8zxJkbXLEZNvKmPINM/1aoyYeloL7rqAuzOPLHARtWHr2b4ewMSzt - CD2gxUbYWLC0NJcgCnB8uTa/ZiTj5N4APj2tnPD5BwnTKo95V2rxyDIU6HBf5w+1 - AibxfsCBAoGBANGzaSc8zjoM6amlpG/uT7lIGPQHnVLJ83tuALbpF2jfVWO3uQS2 - HGxNdURnso/JJIaaLb2UOlq2BH70pH8Qb6FXNavOhV4qpacJlC/v4zuAW4BEjivX - mlj9Ylplja2aasHZyHhd1WR3wiKBcUVf02/0qfFDUrnhYAh+iFSZX8EhAoGBAM7E - 2q0WKPZSxPF786Rs6Y7azh7Jy7pNp+Rlz+jNl/PQS/MnPP+RaffZvxJvbxgDoWQS - vQHLWbmRBklVYX1dSJhsNe7S8kGUggL0s0KWUmKU/RA3mYJ/6EqK31IDCqaZtV+K - 5eWM+5TEdZIZY3Srf1+oBQOgAy9ofwEStWwUY69PAoGBAJTn6k5jfil4i9/ccHTO - 66usx5NZaNyl7RCDn1xDDk148UCa8HWo/2vkYNYPMJurgBVYnAxXmkxZnb2s6LYV - rL8Ll2AFiWzBqdmAEssrc9cHoXHmvHHjaoWwf8ui+0UANriqdhEKyIHMDH3GHvHd - Rt3kBVz9qlu17yR4/UPdmUIhAoGAE7TDOpfQE5nT10f+8n7Gy6yi1GBbIEhiZewm - IoPlpYEGnAfzUlAjj1GbWkBwkBNYgFcg2FjvFjZyKO8QOYh4cL5vbXGBUSq8MVfs - 9b2p4Gdervr9kGhsVR5jJkfP7gzcMlzkiDoliAopQmFVDzuBCjbTM4M+inglEo8b - 508SKRUCgYBomwMGHFAUNulCvbROODEibAGyVU/3Ehq7LedwKaMeLHoVzWXnWAvv - VXU5YaddpK0Z+hbLSAqRScm5Tf9f/ED9DDMBc8lhr6O5GUPwHFN/uuZH8cL5eJV3 - I2eRTdp8e0ridKFLYS43YRc6tgOttCgDXf9roi2T/nm8OkneNyLBLw== - -----END RSA PRIVATE KEY----- - """.trimIndent() - - @Test - fun importJwk() = runTest { - // Private - println("Importing private JWK...") - val privateKeyResult = LocalKey.importJWK(privateKeyJsonString) - println(" Checking import success...") - assertTrue { privateKeyResult.isSuccess } - println(" Getting private key...") - val privateKey = privateKeyResult.getOrThrow() - - println(" Checking for private key...") - assertTrue { privateKey.hasPrivateKey } - println(" Checking for correct key type...") - assertEquals(KeyType.RSA, privateKey.keyType) - - println(" Checking JWK export matches imported JWK...") - assertEquals( - Json.parseToJsonElement(privateKeyJsonString), - Json.parseToJsonElement(privateKey.exportJWK()) - ) - println(" Checking keyId from thumbprint...") - assertEquals(privateKey.getThumbprint(), privateKey.getKeyId()) - - // Public - println("Importing public JWK...") - val publicKeyResult = LocalKey.importJWK(publicKeyJwkString) - println(" Checking import success...") - assertTrue { publicKeyResult.isSuccess } - println(" Getting public key...") - val publicKey = publicKeyResult.getOrThrow() - - println(" Checking for private key...") - assertFalse { publicKey.hasPrivateKey } - println(" Checking for correct key type...") - assertEquals(KeyType.RSA, publicKey.keyType) - - println(" Checking JWK export matches imported JWK...") - assertEquals( - Json.parseToJsonElement(publicKeyJwkString), - Json.parseToJsonElement(publicKey.exportJWK()) - ) - - println(" Checking keyId from thumbprint...") - assertEquals(publicKey.getThumbprint(), publicKey.getKeyId()) - } - - @Test - fun importPem() = runTest { - // Private - println("Importing private PEM...") - val privateKeyResult = LocalKey.importPEM(privateKeyPem) - println(" Checking import success...") - assertTrue { privateKeyResult.isSuccess } - - println(" Getting private key...") - val privateKey = privateKeyResult.getOrThrow() - println(" Checking for private key...") - assertTrue { privateKey.hasPrivateKey } - println(" Checking for correct key type...") - assertEquals(KeyType.RSA, privateKey.keyType) - - println(" Checking JWK export matches JWK...") - assertEquals( - Json.parseToJsonElement(privateKeyJsonString).jsonObject.filterNot { it.key == "kid" }, - Json.parseToJsonElement(privateKey.exportJWK()).jsonObject - ) - - // Public - println("Importing public PEM...") - val publicKeyResult = LocalKey.importPEM(publicKeyPem) - println(" Checking import success...") - assertTrue { publicKeyResult.isSuccess } - - println(" Getting public key...") - val publicKey = publicKeyResult.getOrThrow() - println(" Checking for private key...") - assertFalse { publicKey.hasPrivateKey } - println(" Checking for correct key type...") - assertEquals(KeyType.RSA, publicKey.keyType) - - println(" Checking JWK export matches JWK...") - assertEquals( - Json.parseToJsonElement(publicKeyJwkString).jsonObject.filterNot { it.key == "kid" }, - Json.parseToJsonElement(publicKey.exportJWK()).jsonObject - ) - } -} diff --git a/waltid-crypto/src/jvmTest/kotlin/JWTTest.kt b/waltid-crypto/src/jvmTest/kotlin/JWTTest.kt deleted file mode 100644 index d20028413..000000000 --- a/waltid-crypto/src/jvmTest/kotlin/JWTTest.kt +++ /dev/null @@ -1,31 +0,0 @@ -import id.walt.crypto.keys.KeyType -import id.walt.crypto.keys.LocalKey -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.runTest -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import kotlin.test.Test - -class JWTTest { - - @Test - fun testJwt() = runTest { - val localKey by lazy { runBlocking { LocalKey.generate(KeyType.Ed25519) } } - - val payload = JsonObject( - mapOf( - "sub" to JsonPrimitive("16bb17e0-e733-4622-9384-122bc2fc6290"), - "iss" to JsonPrimitive("http://localhost:3000"), - "aud" to JsonPrimitive("TOKEN"), - ) - ) - - println("Signing JWS: $payload") - val signed = localKey.signJws(payload.toString().toByteArray()) - println("Signed: $signed") - - println("Verifying signed: $signed") - localKey.verifyJws(signed).also { println("Verified: $it") } - } - -} diff --git a/waltid-crypto/src/jvmTest/kotlin/JvmLocalKeyCreatorTest.kt b/waltid-crypto/src/jvmTest/kotlin/JvmLocalKeyCreatorTest.kt new file mode 100644 index 000000000..69d62a757 --- /dev/null +++ b/waltid-crypto/src/jvmTest/kotlin/JvmLocalKeyCreatorTest.kt @@ -0,0 +1,135 @@ +import TestUtils.loadJwkLocal +import TestUtils.loadPemLocal +import TestUtils.loadResourceBytes +import TestUtils.loadSerializedLocal +import id.walt.crypto.keys.JvmLocalKeyCreator +import id.walt.crypto.keys.KeySerialization +import id.walt.crypto.keys.KeyType +import id.walt.crypto.keys.LocalKeyMetadata +import kotlinx.coroutines.test.runTest +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.Arguments.arguments +import org.junit.jupiter.params.provider.EnumSource +import org.junit.jupiter.params.provider.MethodSource +import java.util.stream.Stream +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class JvmLocalKeyCreatorTest { + + private val sut = JvmLocalKeyCreator + + @ParameterizedTest + @EnumSource(KeyType::class) + fun generate(type: KeyType) = runTest { + val key = sut.generate(type) + assertEquals(type, key.keyType) + } + + @ParameterizedTest + @MethodSource + fun importRawPublicKey( + raw: ByteArray, type: KeyType, publicFile: String, importRawAssertions: importRawAssertions + ) = runTest { + val publicKey = KeySerialization.deserializeKey(publicFile).getOrThrow() + val rawKey = sut.importRawPublicKey(type, raw, LocalKeyMetadata()) + importRawAssertions(publicKey.exportJWKObject(), rawKey.exportJWKObject()) + } + + @ParameterizedTest + @MethodSource + fun importJWK(keyFile: String, type: KeyType, isPrivate: Boolean) = runTest { + val keyResult = sut.importJWK(keyFile) + val key = keyResult.getOrThrow() + assertTrue(keyResult.isSuccess) + assertEquals(type, key.keyType) + assertEquals(isPrivate, key.hasPrivateKey) + assertEquals(key.getThumbprint(), key.getKeyId()) + } + + @ParameterizedTest + @MethodSource + fun importPEM(keyFile: String, type: KeyType, isPrivate: Boolean) = runTest { + val keyResult = sut.importPEM(keyFile) + val key = keyResult.getOrThrow() + assertTrue(keyResult.isSuccess) + assertEquals(type, key.keyType) + assertEquals(isPrivate, key.hasPrivateKey) + assertEquals(key.getThumbprint(), key.getKeyId()) + } + + companion object { + @JvmStatic + fun importRawPublicKey(): Stream = Stream.of( + // ed25519 + arguments(loadResourceBytes("public-bytes/ed25519.bin"), KeyType.Ed25519, loadSerializedLocal("ed25519.public.json"), ed25519RawAssertions), + // secp256k1 (throwing Invalid point encoding 0x30) +// arguments(loadResourceBytes("public-bytes/secp256k1.bin"), KeyType.secp256k1, loadSerializedLocal("secp256k1.public.json")), + // secp256r1 (throwing Invalid point encoding 0x30) +// arguments(loadResourceBytes("public-bytes/secp256r1.bin"), KeyType.secp256r1, loadSerializedLocal("secp256r1.public.json")), + // rsa (not implemented) +// arguments(loadResourceBytes("public-bytes/rsa.bin"), KeyType.RSA, loadSerializedLocal("rsa.public.json")), + ) + @JvmStatic + fun importJWK(): Stream = Stream.of( + // ed25519 + arguments(loadJwkLocal("ed25519.private.json"), KeyType.Ed25519, true), + // secp256k1 + arguments(loadJwkLocal("secp256k1.private.json"), KeyType.secp256k1, true), + // secp256r1 + arguments(loadJwkLocal("secp256r1.private.json"), KeyType.secp256r1, true), + // rsa + arguments(loadJwkLocal("rsa.private.json"), KeyType.RSA, true), + // public + // ed25519 + arguments(loadJwkLocal("ed25519.public.json"), KeyType.Ed25519, false), + // secp256k1 + arguments(loadJwkLocal("secp256k1.public.json"), KeyType.secp256k1, false), + // secp256r1 + arguments(loadJwkLocal("secp256r1.public.json"), KeyType.secp256r1, false), + // rsa + arguments(loadJwkLocal("rsa.public.json"), KeyType.RSA, false), + ) + + @JvmStatic + fun importPEM(): Stream = Stream.of( + // ed25519 (not supported) +// arguments(loadPem("ed25519.private.pem"), KeyType.Ed25519, true), + // secp256k1 + arguments(loadPemLocal("secp256k1.private.pem"), KeyType.secp256k1, true), + // secp256r1 + arguments(loadPemLocal("secp256r1.private.pem"), KeyType.secp256r1, true), + // rsa + arguments(loadPemLocal("rsa.private.pem"), KeyType.RSA, true), + // public + // ed25519 (not supported) +// arguments(loadPem("ed25519.public.pem"), KeyType.Ed25519, false), + // secp256k1 + arguments(loadPemLocal("secp256k1.public.pem"), KeyType.secp256k1, false), + // secp256r1 + arguments(loadPemLocal("secp256r1.public.pem"), KeyType.secp256r1, false), + // rsa + arguments(loadPemLocal("rsa.public.pem"), KeyType.RSA, false), + ) + + private val ed25519RawAssertions: importRawAssertions = { expected, actual -> + assertEquals( + expected.jsonObject["kty"]!!.jsonPrimitive.content, + actual.jsonObject["kty"]!!.jsonPrimitive.content + ) + assertEquals( + expected.jsonObject["crv"]!!.jsonPrimitive.content, + actual.jsonObject["crv"]!!.jsonPrimitive.content + ) + assertEquals( + expected.jsonObject["x"]!!.jsonPrimitive.content, + actual.jsonObject["x"]!!.jsonPrimitive.content + ) + } + } +} +internal typealias importRawAssertions = (expected: JsonObject, actual: JsonObject) -> Unit \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/kotlin/KeySerializationTest.kt b/waltid-crypto/src/jvmTest/kotlin/KeySerializationTest.kt deleted file mode 100644 index 8d183193f..000000000 --- a/waltid-crypto/src/jvmTest/kotlin/KeySerializationTest.kt +++ /dev/null @@ -1,87 +0,0 @@ -import id.walt.crypto.keys.* -import io.ktor.client.* -import io.ktor.client.request.* -import io.ktor.http.* -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.runTest -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.JsonPrimitive -import org.junit.jupiter.api.condition.EnabledIf -import kotlin.reflect.KClass -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotEquals - -class KeySerializationTest { - - @Test - @EnabledIf("hostCondition") - fun test() = runTest { - val localKey = LocalKey.generate(KeyType.Ed25519) - val localKeySerialized = KeySerialization.serializeKey(localKey) - - val jsons = listOf( - localKeySerialized to LocalKey::class, - """{"type":"tse","server":"http://127.0.0.1:8200/v1/transit","accessKey":"dev-only-token","id":"k-307668075","_publicKey":[-41,-105,-126,77,-74,88,-28,123,93,-81,105,-13,-93,-111,27,81,-90,-1,86,59,68,105,-108,118,-68,121,18,-114,71,-69,-106,-109],"_keyType":"Ed25519"}""" to TSEKey::class, - """{"type":"tse","server":"http://127.0.0.1:8200/v1/transit","accessKey":"dev-only-token","id":"k-307668075"}""" to TSEKey::class - ) - - jsons.forEach { - check(it) - } - } - - private val testObj = JsonObject(mapOf("value1" to JsonPrimitive("123456789"))) - - @Test - fun testDeserializedVerify() = runTest { - val testObjJson = Json.encodeToString(testObj) - - val key = LocalKey.generate(KeyType.Ed25519) - val key2 = KeySerialization.deserializeKey(KeySerialization.serializeKey(key)).getOrThrow() - - val jws = key.signJws(testObjJson.toByteArray()) - - val res = key2.verifyJws(jws) - println(res) - assertEquals(testObj, res.getOrThrow()) - } - - - @Test - fun testDeserializedSign() = runTest { - val testObjJson = Json.encodeToString(testObj) - - val keyToUseForVerifying = LocalKey.generate(KeyType.Ed25519) - val keyToUseForSigning = KeySerialization.deserializeKey(KeySerialization.serializeKey(keyToUseForVerifying)).getOrThrow() - - val jws = keyToUseForSigning.signJws(testObjJson.toByteArray()) - - val res = keyToUseForVerifying.verifyJws(jws) - println(res) - assertEquals(testObj, res.getOrThrow()) - } - - private suspend fun check(value: Pair>) { - println("Parsing: ${value.first}") - val key = KeySerialization.deserializeKey(value.first).getOrThrow() - - println("Got key: $key") - println("Of type: " + key::class.simpleName) - - println("Key ID: ${key.getKeyId()}") - println("Key type: ${key.keyType}") - println("Public key: ${key.getPublicKey().exportJWK()}") - - assertEquals(value.second.simpleName, key::class.simpleName) - assertNotEquals("Key", key::class.simpleName) - - println() - } - - private fun hostCondition() = runCatching { - runBlocking { HttpClient().get("http://127.0.0.1:8200") }.status == HttpStatusCode.OK - }.fold(onSuccess = { true }, onFailure = { false }) -} diff --git a/waltid-crypto/src/jvmTest/kotlin/KeySerializationTests.kt b/waltid-crypto/src/jvmTest/kotlin/KeySerializationTests.kt new file mode 100644 index 000000000..e7607ad69 --- /dev/null +++ b/waltid-crypto/src/jvmTest/kotlin/KeySerializationTests.kt @@ -0,0 +1,79 @@ +import TestUtils.loadJwkLocal +import TestUtils.loadSerializedLocal +import TestUtils.loadSerializedTse +import id.walt.crypto.keys.Key +import id.walt.crypto.keys.KeySerialization +import id.walt.crypto.keys.LocalKey +import id.walt.crypto.keys.TSEKey +import kotlinx.coroutines.test.runTest +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.jsonPrimitive +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.Arguments.arguments +import org.junit.jupiter.params.provider.MethodSource +import java.util.stream.Stream +import kotlin.reflect.KClass +import kotlin.test.assertEquals + +class KeySerializationTests { + + @ParameterizedTest + @MethodSource + fun `given key, when serializing it then the serialization result contains the correct type and key-string`( + keyFile: String, type: String + ) = runTest { + // given + val key = LocalKey.importJWK(keyFile).getOrThrow() + // when + val serialized = KeySerialization.serializeKey(key) + val decoded = Json.decodeFromString(serialized) + // then + assertEquals(type, decoded["type"]!!.jsonPrimitive.content) + assertEquals(keyFile.replace("\\s".toRegex(), ""), decoded["jwk"]!!.jsonPrimitive.content) + } + + @ParameterizedTest + @MethodSource + fun `given a serialized key string, when deserializing then the result has the correct class type`(serialized: String, clazz: KClass) = + runTest { + // when + val key = KeySerialization.deserializeKey(serialized).getOrThrow() + // then + assertEquals(clazz.java.simpleName, key::class.java.simpleName) + } + + companion object { + @JvmStatic + fun `given key, when serializing it then the serialization result contains the correct type and key-string`(): Stream = Stream.of( + arguments(loadJwkLocal("ed25519.private.json"), "local"), + arguments(loadJwkLocal("secp256k1.private.json"), "local"), + arguments(loadJwkLocal("secp256r1.private.json"), "local"), + arguments(loadJwkLocal("rsa.private.json"), "local"), + // public + arguments(loadJwkLocal("ed25519.public.json"), "local"), + arguments(loadJwkLocal("secp256k1.public.json"), "local"), + arguments(loadJwkLocal("secp256r1.public.json"), "local"), + arguments(loadJwkLocal("rsa.public.json"), "local"), + ) + + @JvmStatic + fun `given a serialized key string, when deserializing then the result has the correct class type`(): Stream = Stream.of ( + arguments(loadSerializedLocal("ed25519.private.json"), LocalKey::class), + arguments(loadSerializedLocal("secp256k1.private.json"), LocalKey::class), + arguments(loadSerializedLocal("secp256r1.private.json"), LocalKey::class), + arguments(loadSerializedLocal("rsa.private.json"), LocalKey::class), + // public + arguments(loadSerializedLocal("ed25519.public.json"), LocalKey::class), + arguments(loadSerializedLocal("secp256k1.public.json"), LocalKey::class), + arguments(loadSerializedLocal("secp256r1.public.json"), LocalKey::class), + arguments(loadSerializedLocal("rsa.public.json"), LocalKey::class), + //// tse + arguments(loadSerializedTse("ed25519.private.json"), TSEKey::class), + arguments(loadSerializedTse("ed25519.public.json"), TSEKey::class), + ) + } + + +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/kotlin/KeySignTests.kt b/waltid-crypto/src/jvmTest/kotlin/KeySignTests.kt new file mode 100644 index 000000000..56621949e --- /dev/null +++ b/waltid-crypto/src/jvmTest/kotlin/KeySignTests.kt @@ -0,0 +1,50 @@ +import TestUtils.loadSerializedLocal +import id.walt.crypto.keys.KeySerialization +import kotlinx.coroutines.test.runTest +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class KeySignTests { + + private val payload = JsonObject( + mapOf( + "sub" to JsonPrimitive("16bb17e0-e733-4622-9384-122bc2fc6290"), + "iss" to JsonPrimitive("http://localhost:3000"), + "aud" to JsonPrimitive("TOKEN"), + ) + ) + + @ParameterizedTest + @ValueSource(strings = ["ed25519.private.json", "secp256k1.private.json", "secp256r1.private.json", "rsa.private.json"]) + fun `given key and payload, when signing jws then the result is a valid jws signature`( + keyFile: String + ) = runTest { + // given + val key = KeySerialization.deserializeKey(loadSerializedLocal(keyFile)).getOrThrow() + // when + val signature = key.signJws(payload.toString().encodeToByteArray()) + val verificationResult = key.getPublicKey().verifyJws(signature) + // then + assertTrue(verificationResult.isSuccess) + assertEquals(payload, verificationResult.getOrThrow()) + } + + @ParameterizedTest + @ValueSource(strings = ["ed25519.private.json", "secp256k1.private.json", "secp256r1.private.json", "rsa.private.json"]) + @Disabled // not implemented + fun `given key and payload, when signing raw then the result is a valid signature`(keyFile: String) = runTest { + // given + val key = KeySerialization.deserializeKey(loadSerializedLocal(keyFile)).getOrThrow() + // when + val signature = key.signRaw(payload.toString().encodeToByteArray()) + val verificationResult = key.getPublicKey().verifyRaw(signature as ByteArray) + // then + assertTrue(verificationResult.isSuccess) + assertEquals(payload.toString().encodeToByteArray(), verificationResult.getOrThrow()) + } +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/kotlin/LocalKeyTest.kt b/waltid-crypto/src/jvmTest/kotlin/LocalKeyTest.kt new file mode 100644 index 000000000..aa26a174d --- /dev/null +++ b/waltid-crypto/src/jvmTest/kotlin/LocalKeyTest.kt @@ -0,0 +1,234 @@ +import TestUtils.loadJwkLocal +import TestUtils.loadPemLocal +import TestUtils.loadResource +import TestUtils.loadResourceBytes +import TestUtils.loadSerializedLocal +import id.walt.crypto.keys.KeySerialization +import id.walt.crypto.keys.KeyType +import kotlinx.coroutines.test.runTest +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.JsonPrimitive +import org.junit.jupiter.api.Disabled +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.Arguments.arguments +import org.junit.jupiter.params.provider.MethodSource +import org.junit.jupiter.params.provider.ValueSource +import java.util.stream.Stream +import kotlin.test.assertEquals +import kotlin.test.assertTrue + +class LocalKeyTest { + private val payload = JsonObject( + mapOf( + "sub" to JsonPrimitive("16bb17e0-e733-4622-9384-122bc2fc6290"), + "iss" to JsonPrimitive("http://localhost:3000"), + "aud" to JsonPrimitive("TOKEN"), + ) + ) + + @ParameterizedTest + @MethodSource + fun getPublicKeyRepresentation(keyFile: String) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + val publicBytes = key.getPublicKeyRepresentation() + } + + @ParameterizedTest + @MethodSource + fun getPublicKey(keyFile: String, publicFile: String) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + val public = KeySerialization.deserializeKey(publicFile).getOrThrow() + val publicKey = key.getPublicKey() + assertTrue(!publicKey.hasPrivateKey) + assertEquals(public.getKeyId(), publicKey.getKeyId()) + assertEquals(public.getThumbprint(), publicKey.getThumbprint()) + assertEquals(public.exportJWK(), publicKey.exportJWK()) + } + + @ParameterizedTest + @MethodSource + fun getKeyType(keyFile: String, type: KeyType) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + assertEquals(type, key.keyType) + } + + @ParameterizedTest + @MethodSource + fun getHasPrivateKey(keyFile: String, isPrivate: Boolean) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + assertEquals(isPrivate, key.hasPrivateKey) + } + + @ParameterizedTest + @ValueSource(strings = ["ed25519.private.json", "secp256k1.private.json", "secp256r1.private.json", "rsa.private.json"]) + @Disabled // not implemented + fun signRaw(keyFile: String) = runTest { + val key = KeySerialization.deserializeKey(loadSerializedLocal(keyFile)).getOrThrow() + val signature = key.signRaw(payload.toString().encodeToByteArray()) + val verificationResult = key.getPublicKey().verifyRaw(signature as ByteArray) + assertTrue(verificationResult.isSuccess) + assertEquals(payload.toString().encodeToByteArray(), verificationResult.getOrThrow()) + } + + @ParameterizedTest + @ValueSource(strings = ["ed25519.private.json", "secp256k1.private.json", "secp256r1.private.json", "rsa.private.json"]) + fun signJws(keyFile: String) = runTest { + val key = KeySerialization.deserializeKey(loadSerializedLocal(keyFile)).getOrThrow() + val signature = key.signJws(payload.toString().encodeToByteArray()) + val verificationResult = key.getPublicKey().verifyJws(signature) + assertTrue(verificationResult.isSuccess) + assertEquals(payload, verificationResult.getOrThrow()) + } + + @ParameterizedTest + @MethodSource + fun getKeyId(keyFile: String, keyId: String) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + assertEquals(keyId, key.getKeyId()) + } + fun getThumbprint() = runTest {} + fun verifyRaw() = runTest {} + @ParameterizedTest + @MethodSource + fun verifyJws(keyFile: String, signature: String) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + val verificationResult = key.verifyJws(signature) + assertTrue(verificationResult.isSuccess) + assertEquals(payload, verificationResult.getOrThrow()) + } + @ParameterizedTest + @MethodSource + fun exportJWK(keyFile: String, jwkFile: String) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + val export = key.exportJWK() + assertEquals(jwkFile.replace("\\s".toRegex(), ""), export) + } + @ParameterizedTest + @MethodSource + fun exportJWKObject(keyFile: String, jwkFile: String) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + val export = key.exportJWKObject() + assertEquals(jwkFile.replace("\\s".toRegex(), ""), export.toString()) + } + @ParameterizedTest + @MethodSource + @Disabled // not implemented + fun exportPEM(keyFile: String, pemFile: String) = runTest { + val key = KeySerialization.deserializeKey(keyFile).getOrThrow() + val export = key.exportPEM() + assertEquals(pemFile, export) + } + + companion object { + @JvmStatic + fun getPublicKeyRepresentation(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadResourceBytes("public-bytes/ed25519.bin")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadResourceBytes("public-bytes/secp256k1.bin")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadResourceBytes("public-bytes/secp256r1.bin")), + arguments(loadSerializedLocal("rsa.private.json"), loadResourceBytes("public-bytes/rsa.bin")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadResourceBytes("public-bytes/ed25519.bin")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadResourceBytes("public-bytes/secp256k1.bin")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadResourceBytes("public-bytes/secp256r1.bin")), + arguments(loadSerializedLocal("rsa.public.json"), loadResourceBytes("public-bytes/rsa.bin")), + ) + @JvmStatic + fun getPublicKey(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadSerializedLocal("ed25519.public.json")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadSerializedLocal("secp256k1.public.json")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadSerializedLocal("secp256r1.public.json")), + arguments(loadSerializedLocal("rsa.private.json"), loadSerializedLocal("rsa.public.json")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadSerializedLocal("ed25519.public.json")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadSerializedLocal("secp256k1.public.json")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadSerializedLocal("secp256r1.public.json")), + arguments(loadSerializedLocal("rsa.public.json"), loadSerializedLocal("rsa.public.json")), + ) + @JvmStatic + fun getKeyType(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), KeyType.Ed25519), + arguments(loadSerializedLocal("secp256k1.private.json"), KeyType.secp256k1), + arguments(loadSerializedLocal("secp256r1.private.json"), KeyType.secp256r1), + arguments(loadSerializedLocal("rsa.private.json"), KeyType.RSA), + // public + arguments(loadSerializedLocal("ed25519.public.json"), KeyType.Ed25519), + arguments(loadSerializedLocal("secp256k1.public.json"), KeyType.secp256k1), + arguments(loadSerializedLocal("secp256r1.public.json"), KeyType.secp256r1), + arguments(loadSerializedLocal("rsa.public.json"), KeyType.RSA), + ) + + @JvmStatic + fun getHasPrivateKey(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), true), + arguments(loadSerializedLocal("secp256k1.private.json"), true), + arguments(loadSerializedLocal("secp256r1.private.json"), true), + arguments(loadSerializedLocal("rsa.private.json"), true), + // public + arguments(loadSerializedLocal("ed25519.public.json"), false), + arguments(loadSerializedLocal("secp256k1.public.json"), false), + arguments(loadSerializedLocal("secp256r1.public.json"), false), + arguments(loadSerializedLocal("rsa.public.json"), false), + ) + + @JvmStatic + fun getKeyId(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), "DJ-kT9JRDYwlJfYjhmJgNwIcuaU6RcSuR8eHIwbsnHQ"), + arguments(loadSerializedLocal("secp256k1.private.json"), "PIv-EHegS0qL__8D4t36kULI8vzBsH4yBshhmY036yA"), + arguments(loadSerializedLocal("secp256r1.private.json"), "LtObdob_k1-dw59-MwdA7auJUJCsqGQ7x2-ufXcB6gY"), + arguments(loadSerializedLocal("rsa.private.json"), "288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A"), + // public + arguments(loadSerializedLocal("ed25519.public.json"), "DJ-kT9JRDYwlJfYjhmJgNwIcuaU6RcSuR8eHIwbsnHQ"), + arguments(loadSerializedLocal("secp256k1.public.json"), "PIv-EHegS0qL__8D4t36kULI8vzBsH4yBshhmY036yA"), + arguments(loadSerializedLocal("secp256r1.public.json"), "LtObdob_k1-dw59-MwdA7auJUJCsqGQ7x2-ufXcB6gY"), + arguments(loadSerializedLocal("rsa.public.json"), "288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A"), + ) + + @JvmStatic + fun verifyJws(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.public.json"), loadResource("signatures/ed25519.txt")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadResource("signatures/secp256k1.txt")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadResource("signatures/secp256r1.txt")), + arguments(loadSerializedLocal("rsa.public.json"), loadResource("signatures/rsa.txt")), + ) + + @JvmStatic + fun exportJWK(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadJwkLocal("ed25519.private.json")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadJwkLocal("secp256k1.private.json")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadJwkLocal("secp256r1.private.json")), + arguments(loadSerializedLocal("rsa.private.json"), loadJwkLocal("rsa.private.json")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadJwkLocal("ed25519.public.json")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadJwkLocal("secp256k1.public.json")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadJwkLocal("secp256r1.public.json")), + arguments(loadSerializedLocal("rsa.public.json"), loadJwkLocal("rsa.public.json")), + ) + + @JvmStatic + fun exportJWKObject(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadJwkLocal("ed25519.private.json")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadJwkLocal("secp256k1.private.json")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadJwkLocal("secp256r1.private.json")), + arguments(loadSerializedLocal("rsa.private.json"), loadJwkLocal("rsa.private.json")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadJwkLocal("ed25519.public.json")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadJwkLocal("secp256k1.public.json")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadJwkLocal("secp256r1.public.json")), + arguments(loadSerializedLocal("rsa.public.json"), loadJwkLocal("rsa.public.json")), + ) + + @JvmStatic + fun exportPEM(): Stream = Stream.of( + arguments(loadSerializedLocal("ed25519.private.json"), loadPemLocal("ed25519.private.pem")), + arguments(loadSerializedLocal("secp256k1.private.json"), loadPemLocal("secp256k1.private.pem")), + arguments(loadSerializedLocal("secp256r1.private.json"), loadPemLocal("secp256r1.private.pem")), + arguments(loadSerializedLocal("rsa.private.json"), loadPemLocal("rsa.private.pem")), + // public + arguments(loadSerializedLocal("ed25519.public.json"), loadPemLocal("ed25519.public.pem")), + arguments(loadSerializedLocal("secp256k1.public.json"), loadPemLocal("secp256k1.public.pem")), + arguments(loadSerializedLocal("secp256r1.public.json"), loadPemLocal("secp256r1.public.pem")), + arguments(loadSerializedLocal("rsa.public.json"), loadPemLocal("rsa.public.pem")), + ) + } +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/kotlin/TestJvm.kt b/waltid-crypto/src/jvmTest/kotlin/TestJvm.kt index 00413c0a9..e7f862489 100644 --- a/waltid-crypto/src/jvmTest/kotlin/TestJvm.kt +++ b/waltid-crypto/src/jvmTest/kotlin/TestJvm.kt @@ -1,24 +1,102 @@ -import id.walt.crypto.keys.KeyType -import id.walt.crypto.keys.LocalKey -import kotlinx.coroutines.DelicateCoroutinesApi -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch +import id.walt.crypto.keys.* +import io.ktor.client.* +import io.ktor.client.request.* +import io.ktor.http.* +import io.ktor.util.* +import kotlinx.coroutines.* import kotlinx.coroutines.test.runTest import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive +import org.junit.jupiter.api.condition.EnabledIf +import kotlin.reflect.KClass import kotlin.system.measureTimeMillis -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue +import kotlin.test.* import kotlin.time.Duration.Companion.minutes class TestJvm { - suspend fun test(keyType: KeyType) { + @Test + fun apiTestAll() = runTest { + KeyType.entries.forEach { exampleKeyCompleteFlow(it) } + } + + @OptIn(DelicateCoroutinesApi::class) + @Test + fun signatureSpeedTestAll() = runTest(timeout = 5.minutes) { + KeyType.entries.forEach { keyType -> + val key = LocalKey.generate(keyType) + key.signJws("abc".encodeToByteArray()) + + val jobs = ArrayList() + + val n = 10_000 + val dispatchMs = measureTimeMillis { + repeat(n) { + jobs.add(GlobalScope.launch { + key.signJws(byteArrayOf(it.toByte())) + }) + } + } + + val signMs = measureTimeMillis { + jobs.forEach { it.join() } + } + + println("$keyType: Dispatch $dispatchMs ms, Signing: $signMs ms (for $n signatures)") + } + } + + @Test + @EnabledIf("hostCondition") + fun testKeySerialization() = runTest { + val localKey = LocalKey.generate(KeyType.Ed25519) + val localKeySerialized = KeySerialization.serializeKey(localKey) + + val jsons = listOf( + localKeySerialized to LocalKey::class, + """{"type":"tse","server":"http://127.0.0.1:8200/v1/transit","accessKey":"dev-only-token","id":"k-307668075","_publicKey":[-41,-105,-126,77,-74,88,-28,123,93,-81,105,-13,-93,-111,27,81,-90,-1,86,59,68,105,-108,118,-68,121,18,-114,71,-69,-106,-109],"_keyType":"Ed25519"}""" to TSEKey::class, + """{"type":"tse","server":"http://127.0.0.1:8200/v1/transit","accessKey":"dev-only-token","id":"k-307668075"}""" to TSEKey::class + ) + + jsons.forEach { + check(it) + } + } + + private val testObj = JsonObject(mapOf("value1" to JsonPrimitive("123456789"))) + + @Test + fun testDeserializedVerify() = runTest { + val testObjJson = Json.encodeToString(testObj) + + val key = LocalKey.generate(KeyType.Ed25519) + val key2 = KeySerialization.deserializeKey(KeySerialization.serializeKey(key)).getOrThrow() + + val jws = key.signJws(testObjJson.toByteArray()) + + val res = key2.verifyJws(jws) + println(res) + assertEquals(testObj, res.getOrThrow()) + } + + + @Test + fun testDeserializedSign() = runTest { + val testObjJson = Json.encodeToString(testObj) + + val keyToUseForVerifying = LocalKey.generate(KeyType.Ed25519) + val keyToUseForSigning = KeySerialization.deserializeKey(KeySerialization.serializeKey(keyToUseForVerifying)).getOrThrow() + + val jws = keyToUseForSigning.signJws(testObjJson.toByteArray()) + + val res = keyToUseForVerifying.verifyJws(jws) + println(res) + assertEquals(testObj, res.getOrThrow()) + } + + private suspend fun exampleKeyCompleteFlow(keyType: KeyType) { val plaintext = JsonObject( mapOf("id" to JsonPrimitive("abc123-${keyType.name}-JVM")) ) @@ -57,35 +135,62 @@ class TestJvm { println(" Public key: ${check2.getOrNull()}") } - @Test - fun apiTestAll() = runTest { - KeyType.entries.forEach { test(it) } + private suspend fun check(value: Pair>) { + println("Parsing: ${value.first}") + val key = KeySerialization.deserializeKey(value.first).getOrThrow() + + println("Got key: $key") + println("Of type: " + key::class.simpleName) + + println("Key ID: ${key.getKeyId()}") + println("Key type: ${key.keyType}") + println("Public key: ${key.getPublicKey().exportJWK()}") + + assertEquals(value.second.simpleName, key::class.simpleName) + assertNotEquals("Key", key::class.simpleName) + + println() } - @OptIn(DelicateCoroutinesApi::class) - @Test - fun signatureSpeedTestAll() = runTest(timeout = 5.minutes) { - KeyType.entries.forEach { keyType -> - val key = LocalKey.generate(keyType) - key.signJws("abc".encodeToByteArray()) + fun exampleSignJwsLocalKey() = runTest { + val localKey by lazy { runBlocking { LocalKey.generate(KeyType.Ed25519) } } - val jobs = ArrayList() + val payload = JsonObject( + mapOf( + "sub" to JsonPrimitive("16bb17e0-e733-4622-9384-122bc2fc6290"), + "iss" to JsonPrimitive("http://localhost:3000"), + "aud" to JsonPrimitive("TOKEN"), + ) + ) - val n = 10_000 - val dispatchMs = measureTimeMillis { - repeat(n) { - jobs.add(GlobalScope.launch { - key.signJws(byteArrayOf(it.toByte())) - }) - } - } + println("Signing JWS: $payload") + val signed = localKey.signJws(payload.toString().toByteArray()) + println("Signed: $signed") - val signMs = measureTimeMillis { - jobs.forEach { it.join() } - } + println("Verifying signed: $signed") + localKey.verifyJws(signed).also { println("Verified: $it") } + } - println("$keyType: Dispatch $dispatchMs ms, Signing: $signMs ms (for $n signatures)") + private suspend fun exampleSignRawTSEKey(key: TSEKey) { + try { + println("TSEKey: $key") + val plaintext = "This is a plaintext for ${key.keyType.name}... 123".encodeToByteArray() + println("Plaintext: ${plaintext.decodeToString()}") + + val signed = key.signRaw(plaintext) as String + println("Signed: $signed") + + val verified = key.verifyRaw(signed.decodeBase64Bytes(), plaintext) + println("Verified signature success: ${verified.isSuccess}") + println("Verified plaintext: ${verified.getOrNull()!!.decodeToString()}") + } finally { + println("Deleting $key...") + key.delete() } } + private fun hostCondition() = runCatching { + runBlocking { HttpClient().get("http://127.0.0.1:8200") }.status == HttpStatusCode.OK + }.fold(onSuccess = { true }, onFailure = { false }) + } diff --git a/waltid-crypto/src/jvmTest/kotlin/TestUtils.kt b/waltid-crypto/src/jvmTest/kotlin/TestUtils.kt new file mode 100644 index 000000000..afbb2a72a --- /dev/null +++ b/waltid-crypto/src/jvmTest/kotlin/TestUtils.kt @@ -0,0 +1,12 @@ +import java.io.File + +object TestUtils { + fun loadJwkLocal(filename: String): String = loadResource("jwk/$filename") + fun loadPemLocal(filename: String): String = loadResource("pem/$filename") + fun loadSerializedLocal(filename: String): String = loadResource("serialized/local/$filename") + fun loadSerializedTse(filename: String): String = loadResource("serialized/tse/$filename") + fun loadResource(relativePath: String): String = + this::class.java.classLoader.getResource(relativePath)!!.path.let { File(it).readText() } + fun loadResourceBytes(relativePath: String): ByteArray = + this::class.java.classLoader.getResource(relativePath)!!.path.let { File(it).readBytes() } +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/ed25519.private.json b/waltid-crypto/src/jvmTest/resources/jwk/ed25519.private.json new file mode 100644 index 000000000..e6393e2b8 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/ed25519.private.json @@ -0,0 +1,9 @@ +{ + "kty": "OKP", + "d": "H-PBqzXk0Dd2k0pPnFW_4gdqRgZtbmckixYbaZN8-bg", + "use": "sig", + "crv": "Ed25519", + "kid": "DJ-kT9JRDYwlJfYjhmJgNwIcuaU6RcSuR8eHIwbsnHQ", + "x": "51sbDqo0X6YccLaxupF-QCR2Oz853AVGIwbXBOU77rU", + "alg": "EdDSA" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/ed25519.public.json b/waltid-crypto/src/jvmTest/resources/jwk/ed25519.public.json new file mode 100644 index 000000000..5e41767e7 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/ed25519.public.json @@ -0,0 +1,8 @@ +{ + "kty": "OKP", + "use": "sig", + "crv": "Ed25519", + "kid": "DJ-kT9JRDYwlJfYjhmJgNwIcuaU6RcSuR8eHIwbsnHQ", + "x": "51sbDqo0X6YccLaxupF-QCR2Oz853AVGIwbXBOU77rU", + "alg": "EdDSA" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/rsa.private.json b/waltid-crypto/src/jvmTest/resources/jwk/rsa.private.json new file mode 100644 index 000000000..df73799e3 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/rsa.private.json @@ -0,0 +1,12 @@ +{ + "p": "0bNpJzzOOgzpqaWkb-5PuUgY9AedUsnze24AtukXaN9VY7e5BLYcbE11RGeyj8kkhpotvZQ6WrYEfvSkfxBvoVc1q86FXiqlpwmUL-_jO4BbgESOK9eaWP1iWmWNrZpqwdnIeF3VZHfCIoFxRV_Tb_Sp8UNSueFgCH6IVJlfwSE", + "kty": "RSA", + "q": "zsTarRYo9lLE8XvzpGzpjtrOHsnLuk2n5GXP6M2X89BL8yc8_5Fp99m_Em9vGAOhZBK9ActZuZEGSVVhfV1ImGw17tLyQZSCAvSzQpZSYpT9EDeZgn_oSorfUgMKppm1X4rl5Yz7lMR1khljdKt_X6gFA6ADL2h_ARK1bBRjr08", + "d": "hndR21ddUYqRi9JfkDcSSzSwUX8R5jwjBaaCqLoKQX3J6VR7eHBv889VooXplheh_UaSeorkLb9Atd7ruF-EmKmuk1S28gr79-hiWa3H7MvIm647vGz0Z9VbhxQpDm9vLVtILbyYh1DVyRzHjOm9n4UyNmQfqolMjzF81_p6DUfpkMcDBJSlsTmRKMWPG0u8mFm8aB9ZftbryPO36QOny7g4_M8SZG1yxGTbypjyDTP9WqMmHpaC-66gLszjyxwEbVh69m-HsDEs7Qg9oMVG2FiwtDSXIApwfLk2v2Yk4-TeAD49rZzw-QcJ0yqPeVdq8cgyFOhwX-cPtQIm8X7AgQ", + "e": "AQAB", + "kid": "288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A", + "qi": "aJsDBhxQFDbpQr20TjgxImwBslVP9xIauy3ncCmjHix6Fc1l51gL71V1OWGnXaStGfoWy0gKkUnJuU3_X_xA_QwzAXPJYa-juRlD8BxTf7rmR_HC-XiVdyNnkU3afHtK4nShS2EuN2EXOrYDrbQoA13_a6Itk_55vDpJ3jciwS8", + "dp": "lOfqTmN-KXiL39xwdM7rq6zHk1lo3KXtEIOfXEMOTXjxQJrwdaj_a-Rg1g8wm6uAFVicDFeaTFmdvazothWsvwuXYAWJbMGp2YASyytz1wehcea8ceNqhbB_y6L7RQA2uKp2EQrIgcwMfcYe8d1G3eQFXP2qW7XvJHj9Q92ZQiE", + "dq": "E7TDOpfQE5nT10f-8n7Gy6yi1GBbIEhiZewmIoPlpYEGnAfzUlAjj1GbWkBwkBNYgFcg2FjvFjZyKO8QOYh4cL5vbXGBUSq8MVfs9b2p4Gdervr9kGhsVR5jJkfP7gzcMlzkiDoliAopQmFVDzuBCjbTM4M-inglEo8b508SKRU", + "n": "qV-fGqTo8r6L52sIJpt44bxLkODaF0_wvIL_eYYDL55H-Ap-b1q4pd4YyZb7pARor_1mob6sMRnnAr5htmO1XucmKBEiNY-12zza0q9smjLm3-eNqq-8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr-bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778-ECcxlM21-JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS_ASTy7MO0SqunpkGzj_H7uFbK9Np_dLIOr9ZqrkCSdioA_PgDyk36E8ayuMnN1HDy4ak_Q7yEX4R_C75T0JxuuYio06hugwyREgOQNID-DVUoLw" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/rsa.public.json b/waltid-crypto/src/jvmTest/resources/jwk/rsa.public.json new file mode 100644 index 000000000..337b61e97 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/rsa.public.json @@ -0,0 +1,6 @@ +{ + "kty": "RSA", + "e": "AQAB", + "kid": "288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A", + "n": "qV-fGqTo8r6L52sIJpt44bxLkODaF0_wvIL_eYYDL55H-Ap-b1q4pd4YyZb7pARor_1mob6sMRnnAr5htmO1XucmKBEiNY-12zza0q9smjLm3-eNqq-8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr-bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778-ECcxlM21-JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS_ASTy7MO0SqunpkGzj_H7uFbK9Np_dLIOr9ZqrkCSdioA_PgDyk36E8ayuMnN1HDy4ak_Q7yEX4R_C75T0JxuuYio06hugwyREgOQNID-DVUoLw" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/secp256k1.private.json b/waltid-crypto/src/jvmTest/resources/jwk/secp256k1.private.json new file mode 100644 index 000000000..d8b481a49 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/secp256k1.private.json @@ -0,0 +1,10 @@ +{ + "kty": "EC", + "d": "ZVnHT7nY4zWiu5tF8l-ycWCCHB645Lc9MhXxUAQqZU0", + "use": "sig", + "crv": "secp256k1", + "kid": "PIv-EHegS0qL__8D4t36kULI8vzBsH4yBshhmY036yA", + "x": "IjAomwz3PFqdqjHR5e22P6tfd_VPqEjAPZ3d-ydEZAo", + "y": "ckpj6l9glLUqXgfRBrMRe3gzmb9m_WS3TU5ociCK1uM", + "alg": "ES256K" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/secp256k1.public.json b/waltid-crypto/src/jvmTest/resources/jwk/secp256k1.public.json new file mode 100644 index 000000000..d890bc4b2 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/secp256k1.public.json @@ -0,0 +1,9 @@ +{ + "kty": "EC", + "use": "sig", + "crv": "secp256k1", + "kid": "PIv-EHegS0qL__8D4t36kULI8vzBsH4yBshhmY036yA", + "x": "IjAomwz3PFqdqjHR5e22P6tfd_VPqEjAPZ3d-ydEZAo", + "y": "ckpj6l9glLUqXgfRBrMRe3gzmb9m_WS3TU5ociCK1uM", + "alg": "ES256K" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/secp256r1.private.json b/waltid-crypto/src/jvmTest/resources/jwk/secp256r1.private.json new file mode 100644 index 000000000..f48708128 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/secp256r1.private.json @@ -0,0 +1,10 @@ +{ + "kty": "EC", + "d": "1K0LxD5eCTxD0RQADLbSmdBtr4Mu6pA9uAM9iotuKZI", + "use": "sig", + "crv": "P-256", + "kid": "LtObdob_k1-dw59-MwdA7auJUJCsqGQ7x2-ufXcB6gY", + "x": "uo896Ho570UP24xyyNt7dE3U6qHlDNJth0Hc_u_uJ2E", + "y": "9Pu4EciCxyTh9eVExa0FnJiJZ58zQKZTPnfKXpWMCto", + "alg": "ES256" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/jwk/secp256r1.public.json b/waltid-crypto/src/jvmTest/resources/jwk/secp256r1.public.json new file mode 100644 index 000000000..f7cbbf48e --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/jwk/secp256r1.public.json @@ -0,0 +1,9 @@ +{ + "kty": "EC", + "use": "sig", + "crv": "P-256", + "kid": "LtObdob_k1-dw59-MwdA7auJUJCsqGQ7x2-ufXcB6gY", + "x": "uo896Ho570UP24xyyNt7dE3U6qHlDNJth0Hc_u_uJ2E", + "y": "9Pu4EciCxyTh9eVExa0FnJiJZ58zQKZTPnfKXpWMCto", + "alg": "ES256" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/pem/ed25519.private.pem b/waltid-crypto/src/jvmTest/resources/pem/ed25519.private.pem new file mode 100644 index 000000000..42dac5dea --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/ed25519.private.pem @@ -0,0 +1,6 @@ +-----BEGIN PRIVATE KEY----- +MC4CAQAwBQYDK2VwBCIEIJpchqgaS5BrgnM/AfWg9DJp6iE/spWXuQhea3+FIlyH +-----END PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEA51sbDqo0X6YccLaxupF+QCR2Oz853AVGIwbXBOU77rU= +-----END PUBLIC KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/pem/ed25519.public.pem b/waltid-crypto/src/jvmTest/resources/pem/ed25519.public.pem new file mode 100644 index 000000000..f859e806b --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/ed25519.public.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MCowBQYDK2VwAyEA51sbDqo0X6YccLaxupF+QCR2Oz853AVGIwbXBOU77rU= +-----END PUBLIC KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/pem/rsa.private.pem b/waltid-crypto/src/jvmTest/resources/pem/rsa.private.pem new file mode 100644 index 000000000..e9541a0a0 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/rsa.private.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAqV+fGqTo8r6L52sIJpt44bxLkODaF0/wvIL/eYYDL55H+Ap+ +b1q4pd4YyZb7pARor/1mob6sMRnnAr5htmO1XucmKBEiNY+12zza0q9smjLm3+eN +qq+8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr+bADVystQeonSPoRLqSoO78oAtonQ +WLX1MUfS9778+ECcxlM21+JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS/ASTy7MO0 +SqunpkGzj/H7uFbK9Np/dLIOr9ZqrkCSdioA/PgDyk36E8ayuMnN1HDy4ak/Q7yE +X4R/C75T0JxuuYio06hugwyREgOQNID+DVUoLwIDAQABAoIBAQCGd1HbV11RipGL +0l+QNxJLNLBRfxHmPCMFpoKougpBfcnpVHt4cG/zz1WihemWF6H9RpJ6iuQtv0C1 +3uu4X4SYqa6TVLbyCvv36GJZrcfsy8ibrju8bPRn1VuHFCkOb28tW0gtvJiHUNXJ +HMeM6b2fhTI2ZB+qiUyPMXzX+noNR+mQxwMElKWxOZEoxY8bS7yYWbxoH1l+1uvI +87fpA6fLuDj8zxJkbXLEZNvKmPINM/1aoyYeloL7rqAuzOPLHARtWHr2b4ewMSzt +CD2gxUbYWLC0NJcgCnB8uTa/ZiTj5N4APj2tnPD5BwnTKo95V2rxyDIU6HBf5w+1 +AibxfsCBAoGBANGzaSc8zjoM6amlpG/uT7lIGPQHnVLJ83tuALbpF2jfVWO3uQS2 +HGxNdURnso/JJIaaLb2UOlq2BH70pH8Qb6FXNavOhV4qpacJlC/v4zuAW4BEjivX +mlj9Ylplja2aasHZyHhd1WR3wiKBcUVf02/0qfFDUrnhYAh+iFSZX8EhAoGBAM7E +2q0WKPZSxPF786Rs6Y7azh7Jy7pNp+Rlz+jNl/PQS/MnPP+RaffZvxJvbxgDoWQS +vQHLWbmRBklVYX1dSJhsNe7S8kGUggL0s0KWUmKU/RA3mYJ/6EqK31IDCqaZtV+K +5eWM+5TEdZIZY3Srf1+oBQOgAy9ofwEStWwUY69PAoGBAJTn6k5jfil4i9/ccHTO +66usx5NZaNyl7RCDn1xDDk148UCa8HWo/2vkYNYPMJurgBVYnAxXmkxZnb2s6LYV +rL8Ll2AFiWzBqdmAEssrc9cHoXHmvHHjaoWwf8ui+0UANriqdhEKyIHMDH3GHvHd +Rt3kBVz9qlu17yR4/UPdmUIhAoGAE7TDOpfQE5nT10f+8n7Gy6yi1GBbIEhiZewm +IoPlpYEGnAfzUlAjj1GbWkBwkBNYgFcg2FjvFjZyKO8QOYh4cL5vbXGBUSq8MVfs +9b2p4Gdervr9kGhsVR5jJkfP7gzcMlzkiDoliAopQmFVDzuBCjbTM4M+inglEo8b +508SKRUCgYBomwMGHFAUNulCvbROODEibAGyVU/3Ehq7LedwKaMeLHoVzWXnWAvv +VXU5YaddpK0Z+hbLSAqRScm5Tf9f/ED9DDMBc8lhr6O5GUPwHFN/uuZH8cL5eJV3 +I2eRTdp8e0ridKFLYS43YRc6tgOttCgDXf9roi2T/nm8OkneNyLBLw== +-----END RSA PRIVATE KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/pem/rsa.public.pem b/waltid-crypto/src/jvmTest/resources/pem/rsa.public.pem new file mode 100644 index 000000000..bf92d7c66 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/rsa.public.pem @@ -0,0 +1,9 @@ +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqV+fGqTo8r6L52sIJpt4 +4bxLkODaF0/wvIL/eYYDL55H+Ap+b1q4pd4YyZb7pARor/1mob6sMRnnAr5htmO1 +XucmKBEiNY+12zza0q9smjLm3+eNqq+8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr+ +bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778+ECcxlM21+JaUjqMD0nQR6wl +8L6oWGcR7PjcjPQAyuS/ASTy7MO0SqunpkGzj/H7uFbK9Np/dLIOr9ZqrkCSdioA +/PgDyk36E8ayuMnN1HDy4ak/Q7yEX4R/C75T0JxuuYio06hugwyREgOQNID+DVUo +LwIDAQAB +-----END PUBLIC KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/pem/secp256k1.private.pem b/waltid-crypto/src/jvmTest/resources/pem/secp256k1.private.pem new file mode 100644 index 000000000..4421e70b0 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/secp256k1.private.pem @@ -0,0 +1,8 @@ +-----BEGIN PRIVATE KEY----- +MEcCAQAwEAYHKoZIzj0CAQYFK4EEAAoEMDAuAgEBBCDhRhzY9+4kOgOm1G2RpZic +YVT21rrpZiGhMcTLFJ1HRaAHBgUrgQQACg== +-----END PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAErWTFQycS7uhkDiKuOv4RLduQkwsTuuoC +PyEMJwLmBFV5mngn1GEkEJxOi0US0SD+/W/ShHyMPzqlbei99XC4mA== +-----END PUBLIC KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/pem/secp256k1.public.pem b/waltid-crypto/src/jvmTest/resources/pem/secp256k1.public.pem new file mode 100644 index 000000000..d2b4ed63d --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/secp256k1.public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEIjAomwz3PFqdqjHR5e22P6tfd/VPqEjA +PZ3d+ydEZApySmPqX2CUtSpeB9EGsxF7eDOZv2b9ZLdNTmhyIIrW4w== +-----END PUBLIC KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/pem/secp256r1.private.pem b/waltid-crypto/src/jvmTest/resources/pem/secp256r1.private.pem new file mode 100644 index 000000000..16f60d95d --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/secp256r1.private.pem @@ -0,0 +1,10 @@ +-----BEGIN PRIVATE KEY----- +MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg1K0LxD5eCTxD0RQA +DLbSmdBtr4Mu6pA9uAM9iotuKZKgCgYIKoZIzj0DAQehRANCAAS6jz3oejnvRQ/b +jHLI23t0TdTqoeUM0m2HQdz+7+4nYfT7uBHIgsck4fXlRMWtBZyYiWefM0CmUz53 +yl6VjAra +-----END PRIVATE KEY----- +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuo896Ho570UP24xyyNt7dE3U6qHl +DNJth0Hc/u/uJ2H0+7gRyILHJOH15UTFrQWcmIlnnzNAplM+d8pelYwK2g== +-----END PUBLIC KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/pem/secp256r1.public.pem b/waltid-crypto/src/jvmTest/resources/pem/secp256r1.public.pem new file mode 100644 index 000000000..2de7b065c --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/pem/secp256r1.public.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuo896Ho570UP24xyyNt7dE3U6qHl +DNJth0Hc/u/uJ2H0+7gRyILHJOH15UTFrQWcmIlnnzNAplM+d8pelYwK2g== +-----END PUBLIC KEY----- diff --git a/waltid-crypto/src/jvmTest/resources/public-bytes/ed25519.bin b/waltid-crypto/src/jvmTest/resources/public-bytes/ed25519.bin new file mode 100644 index 000000000..d62c7f681 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/public-bytes/ed25519.bin @@ -0,0 +1 @@ +ç[ª4_¦p¶±º‘~@$v;?9ÜF#×å;îµ \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/public-bytes/rsa.bin b/waltid-crypto/src/jvmTest/resources/public-bytes/rsa.bin new file mode 100644 index 0000000000000000000000000000000000000000..17bec83a38683f7f13197e7adb322f70b49d17dd GIT binary patch literal 270 zcmV+p0rCDYf&mHwf&l>lsb8NOr0DX#i|1(0@+T5Ma9s2%k0M*LNPoDDh}_;0Je$HShe*rN7DDc z{P;ke##1)e;#yKVj1NiBN313AzNlDd5$yQfjPwA?tX`?yxh z^xA)PvJS7-YOX+%b}9h;_yfvK`V+>oxXI1baPr})KSR8PUxa@PzEjYgZn=o4)2MEP U43QE8kTih)4OJ*F0s{d60fh;T9RL6T literal 0 HcmV?d00001 diff --git a/waltid-crypto/src/jvmTest/resources/public-bytes/secp256k1.bin b/waltid-crypto/src/jvmTest/resources/public-bytes/secp256k1.bin new file mode 100644 index 0000000000000000000000000000000000000000..392e97f2376b541c338f229e6bf6051d23d0d30c GIT binary patch literal 88 zcmV-e0H^;jRxl6-2P%e0&OHJF1_djD1ON&HLI4CJFesZ0_dHsisxi^!?Y2LwUw8FS us7Sy)o!$E`Ic%tdJ%EPZuU5>70oin2|eZH~7vS7RNQ*l#!xNZReUUVsI literal 0 HcmV?d00001 diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.private.json b/waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.private.json new file mode 100644 index 000000000..d30dff05a --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.private.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"kty\":\"OKP\",\"d\":\"H-PBqzXk0Dd2k0pPnFW_4gdqRgZtbmckixYbaZN8-bg\",\"use\":\"sig\",\"crv\":\"Ed25519\",\"kid\":\"DJ-kT9JRDYwlJfYjhmJgNwIcuaU6RcSuR8eHIwbsnHQ\",\"x\":\"51sbDqo0X6YccLaxupF-QCR2Oz853AVGIwbXBOU77rU\",\"alg\":\"EdDSA\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.public.json b/waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.public.json new file mode 100644 index 000000000..0c83a3ead --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/ed25519.public.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"kty\":\"OKP\",\"use\":\"sig\",\"crv\":\"Ed25519\",\"kid\":\"DJ-kT9JRDYwlJfYjhmJgNwIcuaU6RcSuR8eHIwbsnHQ\",\"x\":\"51sbDqo0X6YccLaxupF-QCR2Oz853AVGIwbXBOU77rU\",\"alg\":\"EdDSA\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/rsa.private.json b/waltid-crypto/src/jvmTest/resources/serialized/local/rsa.private.json new file mode 100644 index 000000000..7cdf14b41 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/rsa.private.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"p\":\"0bNpJzzOOgzpqaWkb-5PuUgY9AedUsnze24AtukXaN9VY7e5BLYcbE11RGeyj8kkhpotvZQ6WrYEfvSkfxBvoVc1q86FXiqlpwmUL-_jO4BbgESOK9eaWP1iWmWNrZpqwdnIeF3VZHfCIoFxRV_Tb_Sp8UNSueFgCH6IVJlfwSE\",\"kty\":\"RSA\",\"q\":\"zsTarRYo9lLE8XvzpGzpjtrOHsnLuk2n5GXP6M2X89BL8yc8_5Fp99m_Em9vGAOhZBK9ActZuZEGSVVhfV1ImGw17tLyQZSCAvSzQpZSYpT9EDeZgn_oSorfUgMKppm1X4rl5Yz7lMR1khljdKt_X6gFA6ADL2h_ARK1bBRjr08\",\"d\":\"hndR21ddUYqRi9JfkDcSSzSwUX8R5jwjBaaCqLoKQX3J6VR7eHBv889VooXplheh_UaSeorkLb9Atd7ruF-EmKmuk1S28gr79-hiWa3H7MvIm647vGz0Z9VbhxQpDm9vLVtILbyYh1DVyRzHjOm9n4UyNmQfqolMjzF81_p6DUfpkMcDBJSlsTmRKMWPG0u8mFm8aB9ZftbryPO36QOny7g4_M8SZG1yxGTbypjyDTP9WqMmHpaC-66gLszjyxwEbVh69m-HsDEs7Qg9oMVG2FiwtDSXIApwfLk2v2Yk4-TeAD49rZzw-QcJ0yqPeVdq8cgyFOhwX-cPtQIm8X7AgQ\",\"e\":\"AQAB\",\"kid\":\"288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A\",\"qi\":\"aJsDBhxQFDbpQr20TjgxImwBslVP9xIauy3ncCmjHix6Fc1l51gL71V1OWGnXaStGfoWy0gKkUnJuU3_X_xA_QwzAXPJYa-juRlD8BxTf7rmR_HC-XiVdyNnkU3afHtK4nShS2EuN2EXOrYDrbQoA13_a6Itk_55vDpJ3jciwS8\",\"dp\":\"lOfqTmN-KXiL39xwdM7rq6zHk1lo3KXtEIOfXEMOTXjxQJrwdaj_a-Rg1g8wm6uAFVicDFeaTFmdvazothWsvwuXYAWJbMGp2YASyytz1wehcea8ceNqhbB_y6L7RQA2uKp2EQrIgcwMfcYe8d1G3eQFXP2qW7XvJHj9Q92ZQiE\",\"dq\":\"E7TDOpfQE5nT10f-8n7Gy6yi1GBbIEhiZewmIoPlpYEGnAfzUlAjj1GbWkBwkBNYgFcg2FjvFjZyKO8QOYh4cL5vbXGBUSq8MVfs9b2p4Gdervr9kGhsVR5jJkfP7gzcMlzkiDoliAopQmFVDzuBCjbTM4M-inglEo8b508SKRU\",\"n\":\"qV-fGqTo8r6L52sIJpt44bxLkODaF0_wvIL_eYYDL55H-Ap-b1q4pd4YyZb7pARor_1mob6sMRnnAr5htmO1XucmKBEiNY-12zza0q9smjLm3-eNqq-8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr-bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778-ECcxlM21-JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS_ASTy7MO0SqunpkGzj_H7uFbK9Np_dLIOr9ZqrkCSdioA_PgDyk36E8ayuMnN1HDy4ak_Q7yEX4R_C75T0JxuuYio06hugwyREgOQNID-DVUoLw\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/rsa.public.json b/waltid-crypto/src/jvmTest/resources/serialized/local/rsa.public.json new file mode 100644 index 000000000..9eae9aa68 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/rsa.public.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"kty\":\"RSA\",\"e\":\"AQAB\",\"kid\":\"288WlRQvku-zrHFmvcAW86jnTF3qsMoEUKEbteI2K4A\",\"n\":\"qV-fGqTo8r6L52sIJpt44bxLkODaF0_wvIL_eYYDL55H-Ap-b1q4pd4YyZb7pARor_1mob6sMRnnAr5htmO1XucmKBEiNY-12zza0q9smjLm3-eNqq-8PgsEqBz4lU1YIBeQzsCR0NTa3J3OHfr-bADVystQeonSPoRLqSoO78oAtonQWLX1MUfS9778-ECcxlM21-JaUjqMD0nQR6wl8L6oWGcR7PjcjPQAyuS_ASTy7MO0SqunpkGzj_H7uFbK9Np_dLIOr9ZqrkCSdioA_PgDyk36E8ayuMnN1HDy4ak_Q7yEX4R_C75T0JxuuYio06hugwyREgOQNID-DVUoLw\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.private.json b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.private.json new file mode 100644 index 000000000..0298c96b9 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.private.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"kty\":\"EC\",\"d\":\"ZVnHT7nY4zWiu5tF8l-ycWCCHB645Lc9MhXxUAQqZU0\",\"use\":\"sig\",\"crv\":\"secp256k1\",\"kid\":\"PIv-EHegS0qL__8D4t36kULI8vzBsH4yBshhmY036yA\",\"x\":\"IjAomwz3PFqdqjHR5e22P6tfd_VPqEjAPZ3d-ydEZAo\",\"y\":\"ckpj6l9glLUqXgfRBrMRe3gzmb9m_WS3TU5ociCK1uM\",\"alg\":\"ES256K\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.public.json b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.public.json new file mode 100644 index 000000000..92cc8180c --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256k1.public.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"kty\":\"EC\",\"use\":\"sig\",\"crv\":\"secp256k1\",\"kid\":\"PIv-EHegS0qL__8D4t36kULI8vzBsH4yBshhmY036yA\",\"x\":\"IjAomwz3PFqdqjHR5e22P6tfd_VPqEjAPZ3d-ydEZAo\",\"y\":\"ckpj6l9glLUqXgfRBrMRe3gzmb9m_WS3TU5ociCK1uM\",\"alg\":\"ES256K\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.private.json b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.private.json new file mode 100644 index 000000000..b908f0610 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.private.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"kty\":\"EC\",\"d\":\"1K0LxD5eCTxD0RQADLbSmdBtr4Mu6pA9uAM9iotuKZI\",\"use\":\"sig\",\"crv\":\"P-256\",\"kid\":\"LtObdob_k1-dw59-MwdA7auJUJCsqGQ7x2-ufXcB6gY\",\"x\":\"uo896Ho570UP24xyyNt7dE3U6qHlDNJth0Hc_u_uJ2E\",\"y\":\"9Pu4EciCxyTh9eVExa0FnJiJZ58zQKZTPnfKXpWMCto\",\"alg\":\"ES256\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.public.json b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.public.json new file mode 100644 index 000000000..9eb3a8ae6 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/local/secp256r1.public.json @@ -0,0 +1,4 @@ +{ + "type": "local", + "jwk": "{\"kty\":\"EC\",\"use\":\"sig\",\"crv\":\"P-256\",\"kid\":\"LtObdob_k1-dw59-MwdA7auJUJCsqGQ7x2-ufXcB6gY\",\"x\":\"uo896Ho570UP24xyyNt7dE3U6qHlDNJth0Hc_u_uJ2E\",\"y\":\"9Pu4EciCxyTh9eVExa0FnJiJZ58zQKZTPnfKXpWMCto\",\"alg\":\"ES256\"}" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.private.json b/waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.private.json new file mode 100644 index 000000000..b199a6569 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.private.json @@ -0,0 +1,6 @@ +{ + "type": "tse", + "server": "http://127.0.0.1:8200/v1/transit", + "accessKey": "dev-only-token", + "id": "k-307668075" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.public.json b/waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.public.json new file mode 100644 index 000000000..e5a708775 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/serialized/tse/ed25519.public.json @@ -0,0 +1,42 @@ +{ + "type": "tse", + "server": "http://127.0.0.1:8200/v1/transit", + "accessKey": "dev-only-token", + "id": "k-307668075", + "_publicKey": + [ + -41, + -105, + -126, + 77, + -74, + 88, + -28, + 123, + 93, + -81, + 105, + -13, + -93, + -111, + 27, + 81, + -90, + -1, + 86, + 59, + 68, + 105, + -108, + 118, + -68, + 121, + 18, + -114, + 71, + -69, + -106, + -109 + ], + "_keyType": "Ed25519" +} \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/signatures/ed25519.txt b/waltid-crypto/src/jvmTest/resources/signatures/ed25519.txt new file mode 100644 index 000000000..66eb4d492 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/signatures/ed25519.txt @@ -0,0 +1 @@ +eyJhbGciOiJFZERTQSJ9.eyJzdWIiOiIxNmJiMTdlMC1lNzMzLTQ2MjItOTM4NC0xMjJiYzJmYzYyOTAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJhdWQiOiJUT0tFTiJ9.XoBxYVkuaYM9W34wOJ_GsRhjdattgYL97KfpPQFuFwuj_lTR_WB_spceTo-Se5ZqFdPK940xV7cGG4Bqvsx8BA \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/signatures/rsa.txt b/waltid-crypto/src/jvmTest/resources/signatures/rsa.txt new file mode 100644 index 000000000..100888e2c --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/signatures/rsa.txt @@ -0,0 +1 @@ +eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIxNmJiMTdlMC1lNzMzLTQ2MjItOTM4NC0xMjJiYzJmYzYyOTAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJhdWQiOiJUT0tFTiJ9.o67b57jwhPaKb3tT-XBz69CqerHqu9h2dM3KE0uiUKDTCWepCsy0yvOuGUnHJLsGtWpxQeARItFYSphV5XDxOe2Bsffqzle3A4YBm7E7cesBf3kfBHwn_axzcdff36d_b8wMwqeVNsvJh8QcOhInD4f49i3Ud_a9NyjFPgE_5yUE5c-sc3LrMdbRFYSbF9T1dXMA6zeCLrWEuogOGEMVynu6_sJYUPrP47YCo_k4PwZgemQNW8aWK7c6mqR_jJw7TrJ1EJLNf9Hb2bbs0hDLrrOKj_-EFYPzbu_aaQM4UBP-26kItRJbOS_GHeTnCEukySWLccFWR-uOf_nIPugB6g \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/signatures/secp256k1.txt b/waltid-crypto/src/jvmTest/resources/signatures/secp256k1.txt new file mode 100644 index 000000000..b7522a042 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/signatures/secp256k1.txt @@ -0,0 +1 @@ +eyJhbGciOiJFUzI1NksifQ.eyJzdWIiOiIxNmJiMTdlMC1lNzMzLTQ2MjItOTM4NC0xMjJiYzJmYzYyOTAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJhdWQiOiJUT0tFTiJ9.KtSuRqWx-P_K_vLlZWEgpF5DzsPVi5jMRozxubBe1UFai7na6IvM9SFwvN3_07MYedb4B-YzgHA19bOsxJMZXQ \ No newline at end of file diff --git a/waltid-crypto/src/jvmTest/resources/signatures/secp256r1.txt b/waltid-crypto/src/jvmTest/resources/signatures/secp256r1.txt new file mode 100644 index 000000000..5990e0a91 --- /dev/null +++ b/waltid-crypto/src/jvmTest/resources/signatures/secp256r1.txt @@ -0,0 +1 @@ +eyJhbGciOiJFUzI1NiJ9.eyJzdWIiOiIxNmJiMTdlMC1lNzMzLTQ2MjItOTM4NC0xMjJiYzJmYzYyOTAiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjMwMDAiLCJhdWQiOiJUT0tFTiJ9.Nj2BSndgMjgsFwsFhaHDmLHhkR1lZyq7FJDd3PanhA8u1JzXTtrhblpLiz8W8kcV3dz-UT862ow4HkZD_Xw2nQ \ No newline at end of file