Skip to content

Commit 86b345d

Browse files
committed
Add tests for signatures
1 parent c6ec89e commit 86b345d

File tree

6 files changed

+155
-4
lines changed

6 files changed

+155
-4
lines changed

cryptography-providers-tests-api/src/commonMain/kotlin/utils.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import dev.whyoleg.cryptography.*
88
import dev.whyoleg.cryptography.algorithms.*
99

1010
import dev.whyoleg.cryptography.materials.key.*
11+
import kotlinx.io.*
1112
import kotlinx.io.bytestring.*
1213
import kotlin.io.encoding.*
1314
import kotlin.test.*
@@ -64,6 +65,8 @@ fun digest(name: String): CryptographyAlgorithmId<Digest> = when (name) {
6465
else -> error("Unknown digest: $name")
6566
}
6667

68+
fun Buffer(bytes: ByteString): Buffer = Buffer().apply { write(bytes) }
69+
6770
expect fun disableJsConsoleDebug()
6871

6972
// Wasm tests on browser cannot be filtered: https://youtrack.jetbrains.com/issue/KT-58291

cryptography-providers-tests/src/commonMain/kotlin/default/EcdsaTest.kt

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,12 @@ import dev.whyoleg.cryptography.*
88
import dev.whyoleg.cryptography.algorithms.*
99
import dev.whyoleg.cryptography.providers.tests.api.*
1010
import dev.whyoleg.cryptography.random.*
11+
import kotlinx.io.bytestring.*
1112
import kotlin.io.encoding.*
1213
import kotlin.math.*
1314
import kotlin.test.*
1415

15-
abstract class EcdsaTest(provider: CryptographyProvider) : ProviderTest(provider) {
16+
abstract class EcdsaTest(provider: CryptographyProvider) : ProviderTest(provider), SignatureTest {
1617

1718
//all sizes are in bytes
1819
// `privateKeySizes` contains three sizes.
@@ -83,4 +84,35 @@ abstract class EcdsaTest(provider: CryptographyProvider) : ProviderTest(provider
8384
}
8485
}
8586
}
87+
88+
@Test
89+
fun testFunctions() = testAlgorithm(ECDSA) {
90+
if (!supportsFunctions()) return@testAlgorithm
91+
92+
listOf(
93+
EC.Curve.P256,
94+
EC.Curve.P384,
95+
EC.Curve.P521,
96+
EC.Curve("secp256k1"),
97+
).forEach { curve ->
98+
if (!supportsCurve(curve)) return@forEach
99+
100+
val keyPair = algorithm.keyPairGenerator(curve).generateKey()
101+
102+
generateDigests { digest, _ ->
103+
if (!supportsDigest(digest)) return@generateDigests
104+
105+
ECDSA.SignatureFormat.entries.forEach { format ->
106+
val signatureGenerator = keyPair.privateKey.signatureGenerator(digest, format)
107+
val signatureVerifier = keyPair.publicKey.signatureVerifier(digest, format)
108+
109+
repeat(10) {
110+
val size = CryptographyRandom.nextInt(20000)
111+
val data = ByteString(CryptographyRandom.nextBytes(size))
112+
assertSignaturesViaFunction(signatureGenerator, signatureVerifier, data)
113+
}
114+
}
115+
}
116+
}
117+
}
86118
}

cryptography-providers-tests/src/commonMain/kotlin/default/HmacTest.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import dev.whyoleg.cryptography.*
88
import dev.whyoleg.cryptography.algorithms.*
99
import dev.whyoleg.cryptography.providers.tests.api.*
1010
import dev.whyoleg.cryptography.random.*
11+
import kotlinx.io.bytestring.*
1112
import kotlin.math.*
1213
import kotlin.test.*
1314

14-
abstract class HmacTest(provider: CryptographyProvider) : ProviderTest(provider) {
15+
abstract class HmacTest(provider: CryptographyProvider) : ProviderTest(provider), SignatureTest {
1516

1617
private class HmacTestScope(
1718
logger: TestLogger,
@@ -81,4 +82,19 @@ abstract class HmacTest(provider: CryptographyProvider) : ProviderTest(provider)
8182
val signature = key.signatureGenerator().generateSignature(data)
8283
assertFalse(wrongKey.signatureVerifier().tryVerifySignature(data, signature))
8384
}
85+
86+
@Test
87+
fun testFunctions() = runTestForEachDigest {
88+
if (!supportsFunctions()) return@runTestForEachDigest
89+
90+
val key = algorithm.keyGenerator(digest).generateKey()
91+
val signatureGenerator = key.signatureGenerator()
92+
val signatureVerifier = key.signatureVerifier()
93+
94+
repeat(10) {
95+
val size = CryptographyRandom.nextInt(20000)
96+
val data = ByteString(CryptographyRandom.nextBytes(size))
97+
assertSignaturesViaFunction(signatureGenerator, signatureVerifier, data)
98+
}
99+
}
84100
}

cryptography-providers-tests/src/commonMain/kotlin/default/RsaPkcs1Test.kt

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ import dev.whyoleg.cryptography.*
88
import dev.whyoleg.cryptography.algorithms.*
99
import dev.whyoleg.cryptography.providers.tests.api.*
1010
import dev.whyoleg.cryptography.random.*
11+
import kotlinx.io.bytestring.*
1112
import kotlin.math.*
1213
import kotlin.test.*
1314

14-
abstract class RsaPkcs1Test(provider: CryptographyProvider) : ProviderTest(provider) {
15+
abstract class RsaPkcs1Test(provider: CryptographyProvider) : ProviderTest(provider), SignatureTest {
1516

1617
@Test
1718
fun testSizes() = testAlgorithm(RSA.PKCS1) {
@@ -69,4 +70,24 @@ abstract class RsaPkcs1Test(provider: CryptographyProvider) : ProviderTest(provi
6970
assertContentEquals(plaintext, decryptor.decrypt(ciphertext))
7071
}
7172

73+
@Test
74+
fun testSignatureFunctions() = testAlgorithm(RSA.PKCS1) {
75+
if (!supportsFunctions()) return@testAlgorithm
76+
77+
generateRsaKeySizes { keySize ->
78+
generateDigests { digest, _ ->
79+
if (!supportsDigest(digest)) return@generateDigests
80+
81+
val keyPair = algorithm.keyPairGenerator(keySize, digest).generateKey()
82+
val signatureGenerator = keyPair.privateKey.signatureGenerator()
83+
val signatureVerifier = keyPair.publicKey.signatureVerifier()
84+
85+
repeat(5) {
86+
val size = CryptographyRandom.nextInt(20000)
87+
val data = ByteString(CryptographyRandom.nextBytes(size))
88+
assertSignaturesViaFunction(signatureGenerator, signatureVerifier, data)
89+
}
90+
}
91+
}
92+
}
7293
}

cryptography-providers-tests/src/commonMain/kotlin/default/RsaPssTest.kt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import dev.whyoleg.cryptography.BinarySize.Companion.bytes
99
import dev.whyoleg.cryptography.algorithms.*
1010
import dev.whyoleg.cryptography.providers.tests.api.*
1111
import dev.whyoleg.cryptography.random.*
12+
import kotlinx.io.bytestring.*
1213
import kotlin.math.*
1314
import kotlin.test.*
1415

15-
abstract class RsaPssTest(provider: CryptographyProvider) : ProviderTest(provider) {
16+
abstract class RsaPssTest(provider: CryptographyProvider) : ProviderTest(provider), SignatureTest {
1617

1718
@Test
1819
fun testSizes() = testAlgorithm(RSA.PSS) {
@@ -53,4 +54,25 @@ abstract class RsaPssTest(provider: CryptographyProvider) : ProviderTest(provide
5354
}
5455
}
5556
}
57+
58+
@Test
59+
fun testFunctions() = testAlgorithm(RSA.PSS) {
60+
if (!supportsFunctions()) return@testAlgorithm
61+
62+
generateRsaKeySizes { keySize ->
63+
generateDigests { digest, _ ->
64+
if (!supportsDigest(digest)) return@generateDigests
65+
66+
val keyPair = algorithm.keyPairGenerator(keySize, digest).generateKey()
67+
val signatureGenerator = keyPair.privateKey.signatureGenerator()
68+
val signatureVerifier = keyPair.publicKey.signatureVerifier()
69+
70+
repeat(5) {
71+
val size = CryptographyRandom.nextInt(20000)
72+
val data = ByteString(CryptographyRandom.nextBytes(size))
73+
assertSignaturesViaFunction(signatureGenerator, signatureVerifier, data)
74+
}
75+
}
76+
}
77+
}
5678
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Copyright (c) 2024 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.whyoleg.cryptography.providers.tests.default
6+
7+
import dev.whyoleg.cryptography.operations.*
8+
import dev.whyoleg.cryptography.providers.tests.api.*
9+
import kotlinx.io.*
10+
import kotlinx.io.bytestring.*
11+
import kotlin.test.*
12+
13+
interface SignatureTest {
14+
suspend fun AlgorithmTestScope<*>.assertSignaturesViaFunction(
15+
signatureGenerator: SignatureGenerator,
16+
signatureVerifier: SignatureVerifier,
17+
data: ByteString,
18+
) {
19+
val chunked: UpdateFunction. () -> Unit = {
20+
val steps = 10
21+
val step = data.size / steps
22+
var start = 0
23+
while (start < data.size) {
24+
update(data, start, minOf(data.size, start + step))
25+
start += step
26+
}
27+
}
28+
val viaSource: UpdateFunction. () -> Unit = {
29+
update((Buffer(data) as RawSource).buffered())
30+
}
31+
val viaSink: UpdateFunction. () -> Unit = {
32+
updatingSink(discardingSink()).buffered().use { it.write(data) }
33+
}
34+
35+
fun signature(block: UpdateFunction. () -> Unit) = signatureGenerator.createSignFunction().use {
36+
it.block()
37+
it.sign()
38+
}
39+
40+
fun tryVerify(signature: ByteString, block: UpdateFunction. () -> Unit) = signatureVerifier.createVerifyFunction().use {
41+
it.block()
42+
it.tryVerify(signature)
43+
}
44+
45+
listOf(
46+
signatureGenerator.generateSignature(data),
47+
signature(chunked),
48+
signature(viaSource),
49+
signature(viaSink),
50+
).forEach { signature ->
51+
assertTrue(signatureVerifier.tryVerifySignature(data, signature))
52+
assertTrue(tryVerify(signature, chunked))
53+
assertTrue(tryVerify(signature, viaSource))
54+
assertTrue(tryVerify(signature, viaSink))
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)