@@ -20,33 +20,61 @@ namespace Yubico.YubiKey.Cryptography;
20
20
21
21
public class Curve25519PrivateKeyParameters : IPrivateKeyParameters
22
22
{
23
- private KeyDefinition _keyDefinition { get ; }
24
23
private readonly Memory < byte > _privateKey ;
24
+
25
+ public KeyDefinition KeyDefinition { get ; }
26
+ public KeyType KeyType => KeyDefinition . KeyType ;
27
+ public ReadOnlyMemory < byte > PrivateKey => _privateKey ;
28
+
25
29
private Curve25519PrivateKeyParameters (
26
30
ReadOnlyMemory < byte > privateKey ,
27
- KeyDefinition keyDefinition )
31
+ KeyType keyType )
28
32
{
33
+ var keyDefinition = keyType . GetKeyDefinition ( ) ;
29
34
if ( keyDefinition . AlgorithmOid == KeyDefinitions . CryptoOids . X25519 )
30
35
{
31
36
AsnUtilities . VerifyX25519PrivateKey ( privateKey . Span ) ;
32
37
}
33
38
34
39
_privateKey = new byte [ privateKey . Length ] ;
35
- _keyDefinition = keyDefinition ;
40
+ KeyDefinition = keyDefinition ;
36
41
37
42
privateKey . CopyTo ( _privateKey ) ;
38
43
}
39
44
45
+ /// <summary>
46
+ /// Exports the private key in PKCS#8 DER encoded format.
47
+ /// </summary>
48
+ /// <returns>The DER encoded private key.</returns>
40
49
public byte [ ] ExportPkcs8PrivateKey ( ) => AsnPrivateKeyWriter . EncodeToPkcs8 ( _privateKey , KeyType ) ;
41
- public KeyDefinition KeyDefinition => _keyDefinition ;
42
- public KeyType KeyType => _keyDefinition . KeyType ;
43
- public ReadOnlyMemory < byte > PrivateKey => _privateKey ;
50
+
51
+ /// <summary>
52
+ /// Clears the private key.
53
+ /// </summary>
54
+ /// <remarks>
55
+ /// This method securely zeroes out the private key data.
56
+ /// </remarks>
44
57
public void Clear ( ) => CryptographicOperations . ZeroMemory ( _privateKey . Span ) ;
45
58
59
+ /// <summary>
60
+ /// Creates an instance of <see cref="Curve25519PrivateKeyParameters"/> from a PKCS#8
61
+ /// DER-encoded private key.
62
+ /// </summary>
63
+ /// <param name="encodedKey">
64
+ /// The DER-encoded private key.
65
+ /// </param>
66
+ /// <returns>
67
+ /// A new instance of <see cref="Curve25519PrivateKeyParameters"/>.
68
+ /// </returns>
69
+ /// <exception cref="ArgumentException">
70
+ /// Thrown if the algorithm OID is not X25519 or Ed25519.
71
+ /// </exception>
72
+ /// <exception cref="CryptographicException">
73
+ /// Thrown if the private key is invalid.
74
+ /// </exception>
46
75
public static Curve25519PrivateKeyParameters CreateFromPkcs8 ( ReadOnlyMemory < byte > encodedKey )
47
76
{
48
77
var reader = new AsnReader ( encodedKey , AsnEncodingRules . DER ) ;
49
-
50
78
var seqPrivateKeyInfo = reader . ReadSequence ( ) ;
51
79
var version = seqPrivateKeyInfo . ReadInteger ( ) ;
52
80
if ( version != 0 )
@@ -55,16 +83,17 @@ public static Curve25519PrivateKeyParameters CreateFromPkcs8(ReadOnlyMemory<byte
55
83
}
56
84
57
85
var seqAlgorithmIdentifier = seqPrivateKeyInfo . ReadSequence ( ) ;
58
- string oidAlgorithm = seqAlgorithmIdentifier . ReadObjectIdentifier ( ) ;
59
- if ( oidAlgorithm != KeyDefinitions . CryptoOids . X25519 &&
60
- oidAlgorithm != KeyDefinitions . CryptoOids . Ed25519 )
86
+ string algorithmOid = seqAlgorithmIdentifier . ReadObjectIdentifier ( ) ;
87
+ if ( algorithmOid != KeyDefinitions . CryptoOids . X25519 &&
88
+ algorithmOid != KeyDefinitions . CryptoOids . Ed25519 )
61
89
{
62
90
throw new ArgumentException (
63
91
"Invalid curve OID. Must be: " + KeyDefinitions . CryptoOids . X25519 + " or " +
64
92
KeyDefinitions . CryptoOids . Ed25519 ) ;
65
93
}
66
94
67
- var seqPrivateKey = new AsnReader ( seqPrivateKeyInfo . ReadOctetString ( ) , AsnEncodingRules . DER ) ;
95
+ using var privateKeyDataHandle = new ZeroingMemoryHandle ( seqPrivateKeyInfo . ReadOctetString ( ) ) ;
96
+ var seqPrivateKey = new AsnReader ( privateKeyDataHandle . Data , AsnEncodingRules . DER ) ;
68
97
var tag = seqPrivateKey . PeekTag ( ) ;
69
98
if ( tag . TagValue != 4 || tag . TagClass != TagClass . Universal )
70
99
{
@@ -78,13 +107,17 @@ public static Curve25519PrivateKeyParameters CreateFromPkcs8(ReadOnlyMemory<byte
78
107
throw new CryptographicException ( "Invalid Curve25519 private key: incorrect length" ) ;
79
108
}
80
109
81
- var keyDefinition = KeyDefinitions . GetByOid ( oidAlgorithm ) ;
82
- return new Curve25519PrivateKeyParameters ( privateKeyHandle . Data , keyDefinition ) ;
110
+ var keyDefinition = KeyDefinitions . GetByOid ( algorithmOid ) ;
111
+ return new Curve25519PrivateKeyParameters ( privateKeyHandle . Data , keyDefinition . KeyType ) ;
83
112
84
113
}
85
- public static Curve25519PrivateKeyParameters CreateFromValue ( ReadOnlyMemory < byte > privateKey , KeyType keyType )
86
- {
87
- var keyDefinition = KeyDefinitions . GetByKeyType ( keyType ) ;
88
- return new Curve25519PrivateKeyParameters ( privateKey , keyDefinition ) ;
89
- }
114
+
115
+ /// <summary>
116
+ /// Creates an instance of <see cref="Curve25519PrivateKeyParameters"/> from the given
117
+ /// <paramref name="privateKey"/> and <paramref name="keyType"/>.
118
+ /// </summary>
119
+ /// <param name="privateKey">The raw private key data.</param>
120
+ /// <param name="keyType">The type of key this is.</param>
121
+ /// <returns>An instance of <see cref="Curve25519PrivateKeyParameters"/>.</returns>
122
+ public static Curve25519PrivateKeyParameters CreateFromValue ( ReadOnlyMemory < byte > privateKey , KeyType keyType ) => new ( privateKey , keyType ) ;
90
123
}
0 commit comments