Skip to content

Commit 30420c0

Browse files
committed
asn1: Ed25519/Ed448 and X25519/X448 OIDs; accept ABSENT/NULL AlgorithmIdentifier params (RFC 8410); minor DER tolerance; update module ABI
1 parent 1d0f98f commit 30420c0

File tree

6 files changed

+63
-7
lines changed

6 files changed

+63
-7
lines changed

cryptography-serialization/asn1/modules/api/cryptography-serialization-asn1-modules.api

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ public final class dev/whyoleg/cryptography/serialization/asn1/modules/EcdsaSign
133133
public final fun serializer ()Lkotlinx/serialization/KSerializer;
134134
}
135135

136+
public final class dev/whyoleg/cryptography/serialization/asn1/modules/EdwardsOids {
137+
public static final field INSTANCE Ldev/whyoleg/cryptography/serialization/asn1/modules/EdwardsOids;
138+
public final fun getEd25519-STa95mE ()Ljava/lang/String;
139+
public final fun getEd448-STa95mE ()Ljava/lang/String;
140+
}
141+
136142
public abstract interface class dev/whyoleg/cryptography/serialization/asn1/modules/KeyAlgorithmIdentifier : dev/whyoleg/cryptography/serialization/asn1/modules/AlgorithmIdentifier {
137143
public static final field Companion Ldev/whyoleg/cryptography/serialization/asn1/modules/KeyAlgorithmIdentifier$Companion;
138144
}
@@ -141,6 +147,12 @@ public final class dev/whyoleg/cryptography/serialization/asn1/modules/KeyAlgori
141147
public final fun serializer ()Lkotlinx/serialization/KSerializer;
142148
}
143149

150+
public final class dev/whyoleg/cryptography/serialization/asn1/modules/MontgomeryOids {
151+
public static final field INSTANCE Ldev/whyoleg/cryptography/serialization/asn1/modules/MontgomeryOids;
152+
public final fun getX25519-STa95mE ()Ljava/lang/String;
153+
public final fun getX448-STa95mE ()Ljava/lang/String;
154+
}
155+
144156
public final class dev/whyoleg/cryptography/serialization/asn1/modules/PrivateKeyInfo {
145157
public static final field Companion Ldev/whyoleg/cryptography/serialization/asn1/modules/PrivateKeyInfo$Companion;
146158
public fun <init> (ILdev/whyoleg/cryptography/serialization/asn1/modules/KeyAlgorithmIdentifier;[B)V

cryptography-serialization/asn1/modules/api/cryptography-serialization-asn1-modules.klib.api

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,20 @@ final value class dev.whyoleg.cryptography.serialization.asn1.modules/EcPoint {
256256
}
257257
}
258258

259+
final object dev.whyoleg.cryptography.serialization.asn1.modules/EdwardsOids { // dev.whyoleg.cryptography.serialization.asn1.modules/EdwardsOids|null[0]
260+
final val Ed25519 // dev.whyoleg.cryptography.serialization.asn1.modules/EdwardsOids.Ed25519|{}Ed25519[0]
261+
final fun <get-Ed25519>(): dev.whyoleg.cryptography.serialization.asn1/ObjectIdentifier // dev.whyoleg.cryptography.serialization.asn1.modules/EdwardsOids.Ed25519.<get-Ed25519>|<get-Ed25519>(){}[0]
262+
final val Ed448 // dev.whyoleg.cryptography.serialization.asn1.modules/EdwardsOids.Ed448|{}Ed448[0]
263+
final fun <get-Ed448>(): dev.whyoleg.cryptography.serialization.asn1/ObjectIdentifier // dev.whyoleg.cryptography.serialization.asn1.modules/EdwardsOids.Ed448.<get-Ed448>|<get-Ed448>(){}[0]
264+
}
265+
266+
final object dev.whyoleg.cryptography.serialization.asn1.modules/MontgomeryOids { // dev.whyoleg.cryptography.serialization.asn1.modules/MontgomeryOids|null[0]
267+
final val X25519 // dev.whyoleg.cryptography.serialization.asn1.modules/MontgomeryOids.X25519|{}X25519[0]
268+
final fun <get-X25519>(): dev.whyoleg.cryptography.serialization.asn1/ObjectIdentifier // dev.whyoleg.cryptography.serialization.asn1.modules/MontgomeryOids.X25519.<get-X25519>|<get-X25519>(){}[0]
269+
final val X448 // dev.whyoleg.cryptography.serialization.asn1.modules/MontgomeryOids.X448|{}X448[0]
270+
final fun <get-X448>(): dev.whyoleg.cryptography.serialization.asn1/ObjectIdentifier // dev.whyoleg.cryptography.serialization.asn1.modules/MontgomeryOids.X448.<get-X448>|<get-X448>(){}[0]
271+
}
272+
259273
final object dev.whyoleg.cryptography.serialization.asn1.modules/RsaKeyAlgorithmIdentifier : dev.whyoleg.cryptography.serialization.asn1.modules/KeyAlgorithmIdentifier { // dev.whyoleg.cryptography.serialization.asn1.modules/RsaKeyAlgorithmIdentifier|null[0]
260274
final val algorithm // dev.whyoleg.cryptography.serialization.asn1.modules/RsaKeyAlgorithmIdentifier.algorithm|{}algorithm[0]
261275
final fun <get-algorithm>(): dev.whyoleg.cryptography.serialization.asn1/ObjectIdentifier // dev.whyoleg.cryptography.serialization.asn1.modules/RsaKeyAlgorithmIdentifier.algorithm.<get-algorithm>|<get-algorithm>(){}[0]

cryptography-serialization/asn1/modules/src/commonMain/kotlin/AlgorithmIdentifierSerializer.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,18 @@ public abstract class AlgorithmIdentifierSerializer<AI : AlgorithmIdentifier> :
4545
index = 0,
4646
deserializer = ObjectIdentifier.serializer()
4747
)
48-
check(decodeElementIndex(descriptor) == 1)
49-
val parameters = decodeParameters(algorithm)
50-
check(decodeElementIndex(descriptor) == CompositeDecoder.DECODE_DONE)
51-
parameters
48+
when (val idx = decodeElementIndex(descriptor)) {
49+
1 -> {
50+
val parameters = decodeParameters(algorithm)
51+
check(decodeElementIndex(descriptor) == CompositeDecoder.DECODE_DONE)
52+
parameters
53+
}
54+
CompositeDecoder.DECODE_DONE -> {
55+
// Some algorithms (e.g., Ed25519/Ed448/X25519/X448 per RFC 8410) omit parameters.
56+
// Delegate to subclass to construct an identifier without consuming parameters from the stream.
57+
decodeParameters(algorithm)
58+
}
59+
else -> error("Unexpected element index: $idx")
60+
}
5261
}
53-
}
62+
}

cryptography-serialization/asn1/modules/src/commonMain/kotlin/KeyAlgorithmIdentifierSerializer.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ internal object KeyAlgorithmIdentifierSerializer : AlgorithmIdentifierSerializer
2626
}
2727
ObjectIdentifier.EC -> EcKeyAlgorithmIdentifier(decodeParameters(EcParameters.serializer()))
2828
else -> {
29-
// TODO: somehow we should ignore parameters here
29+
// For algorithms like Ed25519/Ed448/X25519/X448 (RFC 8410), parameters are absent.
30+
// Accept both ABSENT and explicit NULL: attempt to read optional parameters and ignore the value.
31+
decodeParameters<Nothing>(NothingSerializer())
3032
UnknownKeyAlgorithmIdentifier(algorithm)
3133
}
3234
}
33-
}
35+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* Copyright (c) 2025 Oleg Yukhnevich. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package dev.whyoleg.cryptography.serialization.asn1.modules
6+
7+
import dev.whyoleg.cryptography.serialization.asn1.ObjectIdentifier
8+
9+
public object EdwardsOids {
10+
public val Ed25519: ObjectIdentifier = ObjectIdentifier("1.3.101.112")
11+
public val Ed448: ObjectIdentifier = ObjectIdentifier("1.3.101.113")
12+
}
13+
14+
public object MontgomeryOids {
15+
public val X25519: ObjectIdentifier = ObjectIdentifier("1.3.101.110")
16+
public val X448: ObjectIdentifier = ObjectIdentifier("1.3.101.111")
17+
}
18+

cryptography-serialization/asn1/src/commonMain/kotlin/internal/DerDecoder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ internal class DerDecoder(
3636

3737
while (true) {
3838
val index = currentIndex
39+
if (index >= descriptor.elementsCount) return CompositeDecoder.DECODE_DONE
3940
tagOverride = descriptor.getElementContextSpecificTag(index)
4041

4142
if (descriptor.isElementOptional(index)) {

0 commit comments

Comments
 (0)