Skip to content

Commit a348b43

Browse files
committed
More test improvements.
1 parent f2f77d8 commit a348b43

5 files changed

Lines changed: 55 additions & 76 deletions

File tree

paseto/src/main/kotlin/net/aholbrook/paseto/crypto/Ecdsa.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import net.aholbrook.paseto.exception.ByteArrayLengthException
44
import net.aholbrook.paseto.exception.KeyV3Exception
55
import org.bouncycastle.asn1.ASN1ObjectIdentifier
66
import org.bouncycastle.asn1.ASN1Primitive
7+
import org.bouncycastle.asn1.DERBitString
78
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo
89
import org.bouncycastle.asn1.sec.ECPrivateKey
910
import org.bouncycastle.asn1.sec.SECObjectIdentifiers
@@ -220,8 +221,10 @@ internal fun p384EncodeSkSec1(sk: ByteArray): ByteArray {
220221
throw KeyV3Exception("Invalid P-384 private key")
221222
}
222223

224+
val publicKey = DERBitString(params.g.multiply(d).normalize().getEncoded(false))
225+
223226
@Suppress("MagicNumber")
224-
val secretKey = ECPrivateKey(384, d, null, SECObjectIdentifiers.secp384r1)
227+
val secretKey = ECPrivateKey(384, d, publicKey, SECObjectIdentifiers.secp384r1)
225228
return secretKey.encoded
226229
}
227230

@@ -261,7 +264,7 @@ internal fun p384EncodePkSpki(pk: ByteArray): ByteArray {
261264

262265
return SubjectPublicKeyInfo(
263266
AlgorithmIdentifier(X9ObjectIdentifiers.id_ecPublicKey, SECObjectIdentifiers.secp384r1),
264-
q.getEncoded(true),
267+
q.getEncoded(false), // false only for saving keys
265268
).encoded
266269
}
267270

paseto/src/main/kotlin/net/aholbrook/paseto/protocol/Key.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,10 @@ class AsymmetricPublicKey private constructor(private val material: ByteArray, v
7474

7575
Version.V3 -> p384EncodePkSpki(material)
7676

77-
Version.V2, Version.V4 -> Ed25519PublicKeyParameters(material, 0).let {
77+
Version.V2, Version.V4 -> Ed25519PublicKeyParameters(
78+
material.copyOfRange(0, ED25519_SECRETKEYBYTES - ED25519_PUBLICKEYBYTES),
79+
0
80+
).let {
7881
SubjectPublicKeyInfo(
7982
AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519),
8083
it.encoded,
@@ -174,7 +177,7 @@ class AsymmetricPublicKey private constructor(private val material: ByteArray, v
174177
)
175178

176179
Version.V3 -> ofRawBytes(
177-
p384SkToPk(secretKey.getKeyMaterialFor(Version.V1, Purpose.PUBLIC)),
180+
p384SkToPk(secretKey.getKeyMaterialFor(Version.V3, Purpose.PUBLIC)),
178181
Version.V3,
179182
)
180183

@@ -214,26 +217,31 @@ class AsymmetricSecretKey private constructor(private val material: ByteArray, v
214217
fun toHex(): String = Hex.toHexString(material)
215218
fun toBase64Url(): String = Base64.UrlSafe.encode(material)
216219
fun toPem(): String {
217-
val der = when (version) {
218-
Version.V1 -> material
220+
val (der, type) = when (version) {
221+
Version.V1 -> Pair(material, "PRIVATE KEY")
219222

220-
Version.V3 -> p384EncodeSkSec1(material)
223+
Version.V3 -> Pair(p384EncodeSkSec1(material), "EC PRIVATE KEY")
221224

222225
Version.V2, Version.V4 -> {
223226
val rawKey = if (material.size == ED25519_SECRETKEYBYTES) {
224227
material.copyOfRange(0, ED25519_PUBLICKEYBYTES)
225228
} else {
226229
material
227230
}
228-
PrivateKeyInfo(
229-
AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519),
230-
DEROctetString(rawKey),
231-
).encoded
231+
232+
Pair(
233+
PrivateKeyInfo(
234+
AlgorithmIdentifier(EdECObjectIdentifiers.id_Ed25519),
235+
DEROctetString(rawKey),
236+
).encoded,
237+
"PRIVATE KEY"
238+
)
232239
}
233240
}
241+
234242
return StringWriter().also { sw ->
235243
PemWriter(sw).use { pw ->
236-
pw.writeObject(PemObject("PRIVATE KEY", der))
244+
pw.writeObject(PemObject(type, der))
237245
}
238246
}.toString()
239247
}

paseto/src/test/kotlin/net/aholbrook/paseto/crypto/EcdsaTests.kt

Lines changed: 17 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import org.junit.jupiter.api.Test
3131
import org.junit.jupiter.params.ParameterizedTest
3232
import org.junit.jupiter.params.provider.ValueSource
3333
import java.math.BigInteger
34+
import kotlin.io.encoding.Base64
3435

3536
private val secretKey = p384Generate().first
3637
private val publicKey = p384SkToPk(secretKey)
@@ -405,18 +406,11 @@ class EcdsaTests {
405406

406407
@Test
407408
fun `p384EncodeSkPkcs8 works correctly`() {
408-
val sk = byteArrayOf(
409-
10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48, -91, -94, 12, -6, -121,
410-
89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123, -38, 33, 83, -112, -61,
411-
85, -54,
412-
)
409+
val sk = Base64.Pem.decode("Cmkv/SheuJd0qmqoN3/0yFLQpaIM+odZcM10CjA3eZxErnMEJqTRw4XaIVOQw1XK")
413410

414411
val encoded = p384EncodeSkPkcs8(sk)
415-
encoded shouldBe byteArrayOf(
416-
48, 87, 2, 1, 0, 48, 16, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 5, 43, -127, 4, 0, 34, 4, 64, 48, 62, 2, 1,
417-
1, 4, 48, 10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48, -91, -94, 12,
418-
-6, -121, 89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123, -38, 33, 83,
419-
-112, -61, 85, -54, -96, 7, 6, 5, 43, -127, 4, 0, 34,
412+
encoded shouldBe Base64.Pem.decode(
413+
"MFcCAQAwEAYHKoZIzj0CAQYFK4EEACIEQDA+AgEBBDAKaS/9KF64l3Sqaqg3f/TIUtClogz6h1lwzXQKMDd5nESucwQmpNHDhdohU5DDVcqgBwYFK4EEACI=",
420414
)
421415
}
422416

@@ -453,19 +447,12 @@ class EcdsaTests {
453447

454448
@Test
455449
fun `p384DecodeSkPkcs8 works correctly`() {
456-
val encoded = byteArrayOf(
457-
48, 87, 2, 1, 0, 48, 16, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 5, 43, -127, 4, 0, 34, 4, 64, 48, 62, 2, 1,
458-
1, 4, 48, 10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48, -91, -94, 12,
459-
-6, -121, 89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123, -38, 33, 83,
460-
-112, -61, 85, -54, -96, 7, 6, 5, 43, -127, 4, 0, 34,
450+
val encoded = Base64.Pem.decode(
451+
"MFcCAQAwEAYHKoZIzj0CAQYFK4EEACIEQDA+AgEBBDAKaS/9KF64l3Sqaqg3f/TIUtClogz6h1lwzXQKMDd5nESucwQmpNHDhdohU5DDVcqgBwYFK4EEACI=",
461452
)
462453

463454
val sk = p384DecodeSkPkcs8(encoded)
464-
sk shouldBe byteArrayOf(
465-
10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48, -91, -94, 12, -6, -121,
466-
89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123, -38, 33, 83, -112, -61,
467-
85, -54,
468-
)
455+
sk shouldBe Base64.Pem.decode("Cmkv/SheuJd0qmqoN3/0yFLQpaIM+odZcM10CjA3eZxErnMEJqTRw4XaIVOQw1XK")
469456
}
470457

471458
@Test
@@ -574,17 +561,11 @@ class EcdsaTests {
574561

575562
@Test
576563
fun `p384EncodeSkSec1 works correctly`() {
577-
val sk = byteArrayOf(
578-
10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48, -91, -94, 12, -6, -121,
579-
89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123, -38, 33, 83, -112, -61,
580-
85, -54,
581-
)
564+
val sk = Base64.Pem.decode("Cmkv/SheuJd0qmqoN3/0yFLQpaIM+odZcM10CjA3eZxErnMEJqTRw4XaIVOQw1XK")
582565

583566
val encoded = p384EncodeSkSec1(sk)
584-
encoded shouldBe byteArrayOf(
585-
48, 62, 2, 1, 1, 4, 48, 10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48,
586-
-91, -94, 12, -6, -121, 89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123,
587-
-38, 33, 83, -112, -61, 85, -54, -96, 7, 6, 5, 43, -127, 4, 0, 34,
567+
encoded shouldBe Base64.Pem.decode(
568+
"MIGkAgEBBDAKaS/9KF64l3Sqaqg3f/TIUtClogz6h1lwzXQKMDd5nESucwQmpNHDhdohU5DDVcqgBwYFK4EEACKhZANiAAQg6yyTeUvTOgcNWvv/q69vIHTi3qX5P7pJzaRtMkKXuW/vWRzzfGGszn52GbqO9ZUvvfwE35divaZY5MJ5e55HR9XdWS1ty+AKgq0BUopX1NLYgppngincGmpPFI4YEjU=",
588569
)
589570
}
590571

@@ -621,18 +602,10 @@ class EcdsaTests {
621602

622603
@Test
623604
fun `p384DecodeSkSec1 works correctly`() {
624-
val encoded = byteArrayOf(
625-
48, 62, 2, 1, 1, 4, 48, 10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48,
626-
-91, -94, 12, -6, -121, 89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123,
627-
-38, 33, 83, -112, -61, 85, -54, -96, 7, 6, 5, 43, -127, 4, 0, 34,
628-
)
605+
val encoded = Base64.Pem.decode("MD4CAQEEMAppL/0oXriXdKpqqDd/9MhS0KWiDPqHWXDNdAowN3mcRK5zBCak0cOF2iFTkMNVyqAHBgUrgQQAIg==")
629606

630607
val sk = p384DecodeSkSec1(encoded)
631-
sk shouldBe byteArrayOf(
632-
10, 105, 47, -3, 40, 94, -72, -105, 116, -86, 106, -88, 55, 127, -12, -56, 82, -48, -91, -94, 12, -6, -121,
633-
89, 112, -51, 116, 10, 48, 55, 121, -100, 68, -82, 115, 4, 38, -92, -47, -61, -123, -38, 33, 83, -112, -61,
634-
85, -54,
635-
)
608+
sk shouldBe Base64.Pem.decode("Cmkv/SheuJd0qmqoN3/0yFLQpaIM+odZcM10CjA3eZxErnMEJqTRw4XaIVOQw1XK")
636609
}
637610

638611
@Test
@@ -716,34 +689,20 @@ class EcdsaTests {
716689

717690
@Test
718691
fun `p384EncodePkSpki works correctly`() {
719-
val pk = byteArrayOf(
720-
3, -46, 91, 61, -87, 49, -70, 0, -50, 92, -48, 21, 98, 64, -113, -5, -17, 46, -6, -83, 20, 95, -26, -2,
721-
-119, 84, 1, -14, -13, -64, 11, -3, 71, 110, 102, 102, 53, 100, -15, 105, 61, -87, 8, -70, -122, 86, -116,
722-
-4, -125,
723-
)
692+
val pk = Base64.Pem.decode("A9JbPakxugDOXNAVYkCP++8u+q0UX+b+iVQB8vPAC/1HbmZmNWTxaT2pCLqGVoz8gw==")
724693

725694
val encoded = p384EncodePkSpki(pk)
726-
encoded shouldBe byteArrayOf(
727-
48, 70, 48, 16, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 5, 43, -127, 4, 0, 34, 3, 50, 0, 3, -46, 91, 61, -87,
728-
49, -70, 0, -50, 92, -48, 21, 98, 64, -113, -5, -17, 46, -6, -83, 20, 95, -26, -2, -119, 84, 1, -14, -13,
729-
-64, 11, -3, 71, 110, 102, 102, 53, 100, -15, 105, 61, -87, 8, -70, -122, 86, -116, -4, -125,
695+
encoded shouldBe Base64.Pem.decode(
696+
"MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE0ls9qTG6AM5c0BViQI/77y76rRRf5v6JVAHy88AL/UduZmY1ZPFpPakIuoZWjPyDezBTtokEMtobGzLAHPkKdZF09L+BOcN0zFANkDm2TUkF+sRKbjcAiD0JqFSHYdeD",
730697
)
731698
}
732699

733700
@Test
734701
fun `p384DecodePkSpki works correctly`() {
735-
val encoded = byteArrayOf(
736-
48, 70, 48, 16, 6, 7, 42, -122, 72, -50, 61, 2, 1, 6, 5, 43, -127, 4, 0, 34, 3, 50, 0, 3, -46, 91, 61, -87,
737-
49, -70, 0, -50, 92, -48, 21, 98, 64, -113, -5, -17, 46, -6, -83, 20, 95, -26, -2, -119, 84, 1, -14, -13,
738-
-64, 11, -3, 71, 110, 102, 102, 53, 100, -15, 105, 61, -87, 8, -70, -122, 86, -116, -4, -125,
739-
)
702+
val encoded = Base64.Pem.decode("MEYwEAYHKoZIzj0CAQYFK4EEACIDMgAD0ls9qTG6AM5c0BViQI/77y76rRRf5v6JVAHy88AL/UduZmY1ZPFpPakIuoZWjPyD")
740703

741704
val pk = p384DecodePkSpki(encoded)
742-
pk shouldBe byteArrayOf(
743-
3, -46, 91, 61, -87, 49, -70, 0, -50, 92, -48, 21, 98, 64, -113, -5, -17, 46, -6, -83, 20, 95, -26, -2,
744-
-119, 84, 1, -14, -13, -64, 11, -3, 71, 110, 102, 102, 53, 100, -15, 105, 61, -87, 8, -70, -122, 86, -116,
745-
-4, -125,
746-
)
705+
pk shouldBe Base64.Pem.decode("A9JbPakxugDOXNAVYkCP++8u+q0UX+b+iVQB8vPAC/1HbmZmNWTxaT2pCLqGVoz8gw==")
747706
}
748707

749708
@Test

paseto/src/test/kotlin/net/aholbrook/paseto/protocol/KeyTests.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import net.aholbrook.paseto.exception.KeyVersionException
1717
import net.aholbrook.paseto.exception.Pkcs12LoadException
1818
import net.aholbrook.paseto.keyV1Public
1919
import net.aholbrook.paseto.keyV2Public
20+
import net.aholbrook.paseto.keyV3Public
2021
import net.aholbrook.paseto.keyV4Local
2122
import net.aholbrook.paseto.keyV4Public
2223
import net.aholbrook.paseto.protocol.KeyPair.Companion.pkcs12Load
@@ -41,10 +42,14 @@ import kotlin.io.encoding.Base64
4142
class KeyTests {
4243
companion object {
4344
@JvmStatic
44-
fun keyPairsAllVersions(): Stream<Arguments> = listOf(keyV1Public, keyV2Public, keyV4Public).map { Arguments.of(it) }.stream()
45+
fun keyPairsAllVersions(): Stream<Arguments> = listOf(
46+
keyV1Public, keyV2Public, keyV3Public, keyV4Public
47+
).map { Arguments.of(it) }.stream()
4548

4649
@JvmStatic
47-
fun allVersions(): Stream<Arguments> = listOf(Version.V1, Version.V2, Version.V4).map { Arguments.of(it) }.stream()
50+
fun allVersions(): Stream<Arguments> = listOf(
51+
Version.V1, Version.V2, Version.V3, Version.V4
52+
).map { Arguments.of(it) }.stream()
4853
}
4954

5055
@ParameterizedTest

paseto/src/test/kotlin/net/aholbrook/paseto/protocol/TestVectors.kt

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,20 @@ class TestVectorsTests {
8484
}
8585

8686
companion object {
87-
private fun testPemLoadingPublicKey(paseto: Paseto, vector: TestVector) {
87+
private fun testPemPublicKey(paseto: Paseto, vector: TestVector) {
8888
val pemKey = AsymmetricPublicKey.ofPem(vector.publicKeyPem!!, paseto.version)
8989
val hexKey = AsymmetricPublicKey.ofHex(vector.publicKey!!, paseto.version)
9090
pemKey shouldBe hexKey
91+
92+
hexKey.toPem().trim() shouldBe vector.publicKeyPem.trim()
9193
}
9294

93-
private fun testPemLoadingSecretKey(paseto: Paseto, vector: TestVector) {
95+
private fun testPemSecretKey(paseto: Paseto, vector: TestVector) {
9496
val pemKey = AsymmetricSecretKey.ofPem(vector.secretKeyPem!!, paseto.version)
9597
val hexKey = AsymmetricSecretKey.ofHex(vector.secretKey!!, paseto.version)
9698
pemKey shouldBe hexKey
99+
100+
hexKey.toPem().trim() shouldBe vector.secretKeyPem.trim()
97101
}
98102

99103
private fun testEncrypt(paseto: Paseto, vector: TestVector) {
@@ -176,15 +180,15 @@ class TestVectorsTests {
176180
"${vectors.name} - ${vector.name}: pem loading public key",
177181
version,
178182
vector,
179-
::testPemLoadingPublicKey,
183+
::testPemPublicKey,
180184
).takeIf { !vector.expectFail && vector.publicKeyPem != null && vector.publicKey != null },
181185

182186
// protocol
183187
Arguments.of(
184188
"${vectors.name} - ${vector.name}: pem loading secret key",
185189
version,
186190
vector,
187-
::testPemLoadingSecretKey,
191+
::testPemSecretKey,
188192
).takeIf { !vector.expectFail && vector.secretKeyPem != null && vector.secretKey != null },
189193

190194
Arguments.of(

0 commit comments

Comments
 (0)