Skip to content

Commit 33684a9

Browse files
committed
misc: address PR feedback
add documentation rename parameters rename Oids add extensions to KeyType
1 parent 55b67db commit 33684a9

File tree

116 files changed

+2097
-1718
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+2097
-1718
lines changed

Yubico.Core/src/Yubico/Core/Tlv/TlvObject.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,9 @@ public static TlvObject Parse(ReadOnlySpan<byte> data)
116116
}
117117

118118
/// <inheritdoc cref="TlvObject.Parse(ReadOnlySpan{byte})"/>
119-
// public static TlvObject Parse(ReadOnlyMemory<byte> data) => Parse(data.Span);
120-
121119
public static bool TryParse(ReadOnlySpan<byte> data, [NotNullWhen(true)] out TlvObject? tlvObject)
122120
{
121+
// Poor man's TryParse
123122
tlvObject = null;
124123
try
125124
{

Yubico.NET.SDK.sln

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "contributordocs", "contribu
251251
contributordocs\allowed-dotnet-things-and-versions.md = contributordocs\allowed-dotnet-things-and-versions.md
252252
contributordocs\code-flow-and-pull-requests.md = contributordocs\code-flow-and-pull-requests.md
253253
contributordocs\getting-started.md = contributordocs\getting-started.md
254-
contributordocs\polyfills.md = contributordocs\polyfills.md
255254
contributordocs\README.md = contributordocs\README.md
256255
contributordocs\testing.md = contributordocs\testing.md
257256
contributordocs\useful-links.md = contributordocs\useful-links.md

Yubico.YubiKey/src/Yubico/YubiKey/Cryptography/AsnPrivateKeyReader.cs

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ namespace Yubico.YubiKey.Cryptography;
2222

2323
internal class AsnPrivateKeyReader
2424
{
25-
public static IPrivateKeyParameters CreateKeyParameters(ReadOnlyMemory<byte> pkcs8EncodedKey)
25+
public static IPrivateKey CreateKey(ReadOnlyMemory<byte> pkcs8EncodedKey)
2626
{
2727
var reader = new AsnReader(pkcs8EncodedKey, AsnEncodingRules.DER);
2828
var seqPrivateKeyInfo = reader.ReadSequence();
@@ -38,7 +38,7 @@ public static IPrivateKeyParameters CreateKeyParameters(ReadOnlyMemory<byte> pkc
3838
string oidAlgorithm = seqAlgorithmIdentifier.ReadObjectIdentifier();
3939
switch (oidAlgorithm)
4040
{
41-
case KeyDefinitions.Oids.RSA:
41+
case Oids.RSA:
4242
{
4343
if (seqAlgorithmIdentifier.HasData)
4444
{
@@ -47,17 +47,17 @@ public static IPrivateKeyParameters CreateKeyParameters(ReadOnlyMemory<byte> pkc
4747
}
4848

4949
var rsaParameters = CreateRSAParameters(pkcs8EncodedKey);
50-
return RSAPrivateKeyParameters.CreateFromParameters(rsaParameters);
50+
return RSAPrivateKey.CreateFromParameters(rsaParameters);
5151
}
52-
case KeyDefinitions.Oids.ECDSA:
52+
case Oids.ECDSA:
5353
{
5454
var ecParams = CreateECParameters(pkcs8EncodedKey);
55-
return ECPrivateKeyParameters.CreateFromParameters(ecParams);
55+
return ECPrivateKey.CreateFromParameters(ecParams);
5656
}
57-
case KeyDefinitions.Oids.X25519:
58-
case KeyDefinitions.Oids.Ed25519:
57+
case Oids.X25519:
58+
case Oids.Ed25519:
5959
{
60-
return Curve25519PrivateKeyParameters.CreateFromPkcs8(pkcs8EncodedKey);
60+
return Curve25519PrivateKey.CreateFromPkcs8(pkcs8EncodedKey);
6161
}
6262
}
6363

@@ -67,9 +67,47 @@ public static IPrivateKeyParameters CreateKeyParameters(ReadOnlyMemory<byte> pkc
6767
ExceptionMessages.UnsupportedAlgorithm));
6868
}
6969

70-
public static Curve25519PrivateKeyParameters CreateCurve25519Parameters(ReadOnlyMemory<byte> pkcs8EncodedKey) =>
71-
Curve25519PrivateKeyParameters.CreateFromPkcs8(pkcs8EncodedKey);
70+
public static Curve25519PrivateKey CreateCurve25519Key(ReadOnlyMemory<byte> pkcs8EncodedKey) =>
71+
Curve25519PrivateKey.CreateFromPkcs8(pkcs8EncodedKey);
7272

73+
public static (byte[], KeyType) GetCurve25519PrivateKeyData(ReadOnlyMemory<byte> pkcs8EncodedKey)
74+
{
75+
var reader = new AsnReader(pkcs8EncodedKey, AsnEncodingRules.DER);
76+
var seqPrivateKeyInfo = reader.ReadSequence();
77+
var version = seqPrivateKeyInfo.ReadInteger();
78+
if (version != 0)
79+
{
80+
throw new CryptographicException("Invalid PKCS#8 private key format: unexpected version");
81+
}
82+
83+
var seqAlgorithmIdentifier = seqPrivateKeyInfo.ReadSequence();
84+
string algorithmOid = seqAlgorithmIdentifier.ReadObjectIdentifier();
85+
if (!Oids.IsCurve25519Algorithm(algorithmOid))
86+
{
87+
throw new ArgumentException(
88+
"Invalid curve OID. Must be: " + Oids.X25519 + " or " +
89+
Oids.Ed25519);
90+
}
91+
92+
using var privateKeyDataHandle = new ZeroingMemoryHandle(seqPrivateKeyInfo.ReadOctetString());
93+
var seqPrivateKey = new AsnReader(privateKeyDataHandle.Data, AsnEncodingRules.DER);
94+
var tag = seqPrivateKey.PeekTag();
95+
if (tag.TagValue != 4 || tag.TagClass != TagClass.Universal)
96+
{
97+
throw new CryptographicException("Invalid Curve25519 private key");
98+
}
99+
100+
byte[] privateKey = seqPrivateKey.ReadOctetString();
101+
if (privateKey.Length != 32)
102+
{
103+
throw new CryptographicException("Invalid Curve25519 private key: incorrect length");
104+
}
105+
seqPrivateKeyInfo.ThrowIfNotEmpty();
106+
107+
108+
var keyDefinition = KeyDefinitions.GetByOid(algorithmOid);
109+
return (privateKey, keyDefinition.KeyType);
110+
}
73111
public static ECParameters CreateECParameters(ReadOnlyMemory<byte> pkcs8EncodedKey)
74112
{
75113
var reader = new AsnReader(pkcs8EncodedKey, AsnEncodingRules.DER);
@@ -84,7 +122,7 @@ public static ECParameters CreateECParameters(ReadOnlyMemory<byte> pkcs8EncodedK
84122

85123
var seqAlgorithmIdentifier = seqPrivateKeyInfo.ReadSequence();
86124
string oidAlgorithm = seqAlgorithmIdentifier.ReadObjectIdentifier();
87-
if (oidAlgorithm != KeyDefinitions.Oids.ECDSA)
125+
if (oidAlgorithm != Oids.ECDSA)
88126
{
89127
throw new InvalidOperationException(
90128
string.Format(
@@ -94,9 +132,9 @@ public static ECParameters CreateECParameters(ReadOnlyMemory<byte> pkcs8EncodedK
94132

95133
string curveOid = seqAlgorithmIdentifier.ReadObjectIdentifier();
96134
if (curveOid is not (
97-
KeyDefinitions.Oids.P256 or
98-
KeyDefinitions.Oids.P384 or
99-
KeyDefinitions.Oids.P521))
135+
Oids.ECP256 or
136+
Oids.ECP384 or
137+
Oids.ECP521))
100138
{
101139
throw new InvalidOperationException(
102140
string.Format(
@@ -160,16 +198,12 @@ KeyDefinitions.Oids.P384 or
160198
}
161199
}
162200

163-
var curve = ECCurve.CreateFromValue(curveOid);
164-
byte[] privateKey = privateKeyHandle.Data.ToArray();
165-
var ecParams = new ECParameters
201+
return new ECParameters
166202
{
167-
Curve = curve,
168-
D = privateKey,
203+
Curve = ECCurve.CreateFromValue(curveOid),
204+
D = privateKeyHandle.Data.ToArray(),
169205
Q = point
170206
};
171-
172-
return ecParams;
173207
}
174208

175209
public static RSAParameters CreateRSAParameters(ReadOnlyMemory<byte> pkcs8EncodedKey)
@@ -186,7 +220,7 @@ public static RSAParameters CreateRSAParameters(ReadOnlyMemory<byte> pkcs8Encode
186220

187221
var seqAlgorithmIdentifier = seqPrivateKeyInfo.ReadSequence();
188222
string oidAlgorithm = seqAlgorithmIdentifier.ReadObjectIdentifier();
189-
if (oidAlgorithm != KeyDefinitions.Oids.RSA)
223+
if (oidAlgorithm != Oids.RSA)
190224
{
191225
throw new InvalidOperationException(
192226
string.Format(

Yubico.YubiKey/src/Yubico/YubiKey/Cryptography/AsnPrivateKeyWriter.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ public static byte[] EncodeToPkcs8(
3737
{
3838
return keyType switch
3939
{
40-
KeyType.P256 => EncodeECKey(privateKey, KeyDefinitions.Oids.P256, publicPoint),
41-
KeyType.P384 => EncodeECKey(privateKey, KeyDefinitions.Oids.P384, publicPoint),
42-
KeyType.P521 => EncodeECKey(privateKey, KeyDefinitions.Oids.P521, publicPoint),
43-
KeyType.X25519 => EncodeCurve25519Key(privateKey.Span, KeyDefinitions.Oids.X25519),
44-
KeyType.Ed25519 => EncodeCurve25519Key(privateKey.Span, KeyDefinitions.Oids.Ed25519),
40+
KeyType.ECP256 => EncodeECKey(privateKey, Oids.ECP256, publicPoint),
41+
KeyType.ECP384 => EncodeECKey(privateKey, Oids.ECP384, publicPoint),
42+
KeyType.ECP521 => EncodeECKey(privateKey, Oids.ECP521, publicPoint),
43+
KeyType.X25519 => EncodeCurve25519Key(privateKey.Span, Oids.X25519),
44+
KeyType.Ed25519 => EncodeCurve25519Key(privateKey.Span, Oids.Ed25519),
4545
_ => throw new NotSupportedException($"Key type {keyType} is not supported for encoding.")
4646
};
4747
}
@@ -100,7 +100,7 @@ public static byte[] EncodeToPkcs8(RSAParameters parameters)
100100
writer.WriteInteger(0);
101101

102102
_ = writer.PushSequence();
103-
writer.WriteObjectIdentifier(KeyDefinitions.Oids.RSA);
103+
writer.WriteObjectIdentifier(Oids.RSA);
104104
writer.WriteNull();
105105
writer.PopSequence();
106106

@@ -116,9 +116,9 @@ public static byte[] EncodeToPkcs8(RSAParameters parameters)
116116
/// </summary>
117117
/// <param name="parameters">The EC parameters including private key value.</param>
118118
/// <returns>A byte array containing the ASN.1 DER encoded private key in PKCS#8 format.</returns>
119+
/// <exception cref="ArgumentException">Thrown when the private key parameter D is null.</exception>
119120
public static byte[] EncodeToPkcs8(ECParameters parameters)
120121
{
121-
// Ensure parameters include private key part
122122
if (parameters.D == null)
123123
{
124124
throw new ArgumentException("Private key parameter D must be provided.");
@@ -185,7 +185,7 @@ private static byte[] EncodeECKey(
185185

186186
// Algorithm Identifier SEQUENCE
187187
_ = writer.PushSequence();
188-
writer.WriteObjectIdentifier(KeyDefinitions.Oids.ECDSA);
188+
writer.WriteObjectIdentifier(Oids.ECDSA);
189189
writer.WriteObjectIdentifier(curveOid);
190190
writer.PopSequence();
191191

@@ -196,24 +196,24 @@ private static byte[] EncodeECKey(
196196
return writer.Encode();
197197
}
198198

199-
private static byte[] EncodeCurve25519Key(ReadOnlySpan<byte> privateKey, string curveOid)
199+
private static byte[] EncodeCurve25519Key(ReadOnlySpan<byte> privateKey, string algorithmOid)
200200
{
201201
if (privateKey.Length != 32)
202202
{
203203
throw new ArgumentException("Curve25519 key must be 32 bytes.");
204204
}
205205

206-
if (curveOid == null)
206+
if (algorithmOid == null)
207207
{
208208
throw new ArgumentException("Curve OID is null.");
209209
}
210210

211-
if (curveOid is not (KeyDefinitions.Oids.X25519 or KeyDefinitions.Oids.Ed25519))
211+
if (!Oids.IsCurve25519Algorithm(algorithmOid))
212212
{
213-
throw new ArgumentException("Curve OID is not supported.", nameof(curveOid));
213+
throw new ArgumentException("Algorithm OID is not supported.", nameof(algorithmOid));
214214
}
215215

216-
if (curveOid == KeyDefinitions.Oids.X25519)
216+
if (algorithmOid == Oids.X25519)
217217
{
218218
AsnUtilities.VerifyX25519PrivateKey(privateKey);
219219
}
@@ -229,14 +229,15 @@ private static byte[] EncodeCurve25519Key(ReadOnlySpan<byte> privateKey, string
229229

230230
// Algorithm Identifier SEQUENCE
231231
_ = writer.PushSequence();
232-
writer.WriteObjectIdentifier(curveOid);
232+
writer.WriteObjectIdentifier(algorithmOid);
233233
writer.PopSequence();
234234

235235
// PrivateKey as OCTET STRING
236236
var privateKeyWriter = new AsnWriter(AsnEncodingRules.DER);
237237
privateKeyWriter.WriteOctetString(privateKey);
238-
ReadOnlySpan<byte> privateKeySpan = privateKeyWriter.Encode();
239-
writer.WriteOctetString(privateKeySpan);
238+
239+
using var privateKeyBytesHandle = new ZeroingMemoryHandle(privateKeyWriter.Encode());
240+
writer.WriteOctetString(privateKeyBytesHandle.Data);
240241

241242
// End PrivateKeyInfo SEQUENCE
242243
writer.PopSequence();

Yubico.YubiKey/src/Yubico/YubiKey/Cryptography/AsnPublicKeyReader.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace Yubico.YubiKey.Cryptography;
2121

2222
internal class AsnPublicKeyReader
2323
{
24-
public static IPublicKeyParameters CreateKeyParameters(ReadOnlyMemory<byte> pkcs8EncodedKey)
24+
public static IPublicKey CreateKey(ReadOnlyMemory<byte> pkcs8EncodedKey)
2525
{
2626
var reader = new AsnReader(pkcs8EncodedKey, AsnEncodingRules.DER);
2727
var seqSubjectPublicKeyInfo = reader.ReadSequence();
@@ -36,28 +36,28 @@ public static IPublicKeyParameters CreateKeyParameters(ReadOnlyMemory<byte> pkcs
3636

3737
switch (oidAlgorithm)
3838
{
39-
case KeyDefinitions.Oids.RSA:
39+
case Oids.RSA:
4040
{
4141
if (seqAlgorithmIdentifier.HasData)
4242
{
4343
seqAlgorithmIdentifier.ReadNull();
4444
seqAlgorithmIdentifier.ThrowIfNotEmpty();
4545
}
4646

47-
return CreateRSAPublicKeyParameters(subjectPublicKey);
47+
return CreateRSAPublicKey(subjectPublicKey);
4848
}
49-
case KeyDefinitions.Oids.ECDSA:
49+
case Oids.ECDSA:
5050
{
5151
string oidCurve = seqAlgorithmIdentifier.ReadObjectIdentifier();
52-
return CreateECPublicKeyParameters(oidCurve, subjectPublicKey);
52+
return CreateECPublicKey(oidCurve, subjectPublicKey);
5353
}
54-
case KeyDefinitions.Oids.X25519:
54+
case Oids.X25519:
5555
{
56-
return Curve25519PublicKeyParameters.CreateFromValue(subjectPublicKey, KeyType.X25519);
56+
return Curve25519PublicKey.CreateFromValue(subjectPublicKey, KeyType.X25519);
5757
}
58-
case KeyDefinitions.Oids.Ed25519:
58+
case Oids.Ed25519:
5959
{
60-
return Curve25519PublicKeyParameters.CreateFromValue(subjectPublicKey, KeyType.Ed25519);
60+
return Curve25519PublicKey.CreateFromValue(subjectPublicKey, KeyType.Ed25519);
6161
}
6262
}
6363

@@ -67,7 +67,7 @@ public static IPublicKeyParameters CreateKeyParameters(ReadOnlyMemory<byte> pkcs
6767
ExceptionMessages.UnsupportedAlgorithm));
6868
}
6969

70-
private static RSAPublicKeyParameters CreateRSAPublicKeyParameters(byte[] subjectPublicKey)
70+
private static RSAPublicKey CreateRSAPublicKey(byte[] subjectPublicKey)
7171
{
7272
var subjectPublicKeyReader = new AsnReader(subjectPublicKey, AsnEncodingRules.DER);
7373
var seqSubjectPublicKey = subjectPublicKeyReader.ReadSequence();
@@ -84,13 +84,12 @@ private static RSAPublicKeyParameters CreateRSAPublicKeyParameters(byte[] subjec
8484
Exponent = exponent.ToArray()
8585
};
8686

87-
return RSAPublicKeyParameters.CreateFromParameters(rsaParameters);
87+
return RSAPublicKey.CreateFromParameters(rsaParameters);
8888
}
8989

90-
private static ECPublicKeyParameters CreateECPublicKeyParameters(string curveOid, byte[] subjectPublicKey)
90+
private static ECPublicKey CreateECPublicKey(string curveOid, byte[] subjectPublicKey)
9191
{
92-
if (curveOid is not (KeyDefinitions.Oids.P256 or KeyDefinitions.Oids.P384
93-
or KeyDefinitions.Oids.P521))
92+
if (!Oids.IsECDsaCurve(curveOid))
9493
{
9594
throw new NotSupportedException(
9695
string.Format(
@@ -106,6 +105,10 @@ private static ECPublicKeyParameters CreateECPublicKeyParameters(string curveOid
106105
}
107106

108107
int coordinateSize = AsnUtilities.GetCoordinateSizeFromCurve(curveOid);
108+
if (subjectPublicKey.Length != 1 + (2 * coordinateSize))
109+
{
110+
throw new CryptographicException("Invalid EC public key encoding");
111+
}
109112
byte[] xCoordinate = new byte[coordinateSize];
110113
byte[] yCoordinate = new byte[coordinateSize];
111114

@@ -124,6 +127,6 @@ private static ECPublicKeyParameters CreateECPublicKeyParameters(string curveOid
124127
}
125128
};
126129

127-
return ECPublicKeyParameters.CreateFromParameters(ecParams);
130+
return ECPublicKey.CreateFromParameters(ecParams);
128131
}
129132
}

0 commit comments

Comments
 (0)