1
1
using System ;
2
2
using System . Security . Cryptography ;
3
3
using System . Security . Cryptography . X509Certificates ;
4
-
5
4
using Fido2NetLib . Cbor ;
6
-
7
5
using NSec . Cryptography ;
8
6
9
7
namespace Fido2NetLib . Objects ;
@@ -13,6 +11,9 @@ public sealed class CredentialPublicKey
13
11
internal readonly COSE . KeyType _type ;
14
12
internal readonly COSE . Algorithm _alg ;
15
13
internal readonly CborMap _cpk ;
14
+ internal readonly ECDsa ? _ecdsa ;
15
+ internal readonly RSA ? _rsa ;
16
+ internal readonly NSec . Cryptography . PublicKey ? _eddsa ;
16
17
17
18
public CredentialPublicKey ( byte [ ] cpk )
18
19
: this ( ( CborMap ) CborObject . Decode ( cpk ) ) { }
@@ -22,6 +23,25 @@ public CredentialPublicKey(CborMap cpk)
22
23
_cpk = cpk ;
23
24
_type = ( COSE . KeyType ) ( int ) cpk [ COSE . KeyCommonParameter . KeyType ] ;
24
25
_alg = ( COSE . Algorithm ) ( int ) cpk [ COSE . KeyCommonParameter . Alg ] ;
26
+ switch ( _type )
27
+ {
28
+ case COSE . KeyType . EC2 :
29
+ {
30
+ _ecdsa = CreateECDsa ( ) ;
31
+ return ;
32
+ }
33
+ case COSE . KeyType . RSA :
34
+ {
35
+ _rsa = CreateRSA ( ) ;
36
+ return ;
37
+ }
38
+ case COSE . KeyType . OKP :
39
+ {
40
+ _eddsa = CreateEdDSA ( ) ;
41
+ return ;
42
+ }
43
+ }
44
+ throw new InvalidOperationException ( $ "Missing or unknown kty { _type } ") ;
25
45
}
26
46
27
47
public CredentialPublicKey ( ECDsa ecdsaPublicKey , COSE . Algorithm alg )
@@ -39,6 +59,7 @@ public CredentialPublicKey(ECDsa ecdsaPublicKey, COSE.Algorithm alg)
39
59
{ COSE . KeyTypeParameter . X , keyParams . Q . X ! } ,
40
60
{ COSE . KeyTypeParameter . Y , keyParams . Q . Y ! }
41
61
} ;
62
+ _ecdsa = CreateECDsa ( ) ;
42
63
}
43
64
44
65
public CredentialPublicKey ( X509Certificate2 cert , COSE . Algorithm alg )
@@ -51,21 +72,36 @@ public CredentialPublicKey(X509Certificate2 cert, COSE.Algorithm alg)
51
72
{ COSE . KeyCommonParameter . KeyType , _type } ,
52
73
{ COSE . KeyCommonParameter . Alg , _alg }
53
74
} ;
54
-
55
- if ( _type is COSE . KeyType . RSA )
56
- {
57
- var keyParams = cert . GetRSAPublicKey ( ) ! . ExportParameters ( false ) ;
58
- _cpk . Add ( COSE . KeyTypeParameter . N , keyParams . Modulus ! ) ;
59
- _cpk . Add ( COSE . KeyTypeParameter . E , keyParams . Exponent ! ) ;
60
- }
61
- else if ( _type is COSE . KeyType . EC2 )
75
+ switch ( _type )
62
76
{
63
- var ecDsaPubKey = cert . GetECDsaPublicKey ( ) ! ;
64
- var keyParams = ecDsaPubKey . ExportParameters ( false ) ;
65
-
66
- _cpk . Add ( COSE . KeyTypeParameter . Crv , keyParams . Curve . ToCoseCurve ( ) ) ;
67
- _cpk . Add ( COSE . KeyTypeParameter . X , keyParams . Q . X ! ) ;
68
- _cpk . Add ( COSE . KeyTypeParameter . Y , keyParams . Q . Y ! ) ;
77
+ case COSE . KeyType . RSA :
78
+ {
79
+ var keyParams = cert . GetRSAPublicKey ( ) ! . ExportParameters ( false ) ;
80
+ _cpk . Add ( COSE . KeyTypeParameter . N , keyParams . Modulus ! ) ;
81
+ _cpk . Add ( COSE . KeyTypeParameter . E , keyParams . Exponent ! ) ;
82
+ _rsa = CreateRSA ( ) ;
83
+ break ;
84
+ }
85
+ case COSE . KeyType . EC2 :
86
+ {
87
+ var ecDsaPubKey = cert . GetECDsaPublicKey ( ) ! ;
88
+ var keyParams = ecDsaPubKey . ExportParameters ( false ) ;
89
+
90
+ _cpk . Add ( COSE . KeyTypeParameter . Crv , keyParams . Curve . ToCoseCurve ( ) ) ;
91
+ _cpk . Add ( COSE . KeyTypeParameter . X , keyParams . Q . X ! ) ;
92
+ _cpk . Add ( COSE . KeyTypeParameter . Y , keyParams . Q . Y ! ) ;
93
+ _ecdsa = CreateECDsa ( ) ;
94
+ break ;
95
+ }
96
+ case COSE . KeyType . OKP :
97
+ {
98
+ _cpk . Add ( COSE . KeyTypeParameter . Crv , COSE . EllipticCurve . Ed25519 ) ;
99
+ _cpk . Add ( COSE . KeyTypeParameter . X , cert . PublicKey . EncodedKeyValue . RawData ) ;
100
+ _eddsa = CreateEdDSA ( ) ;
101
+ break ;
102
+ }
103
+ default :
104
+ throw new InvalidOperationException ( $ "Missing or unknown kty { _type } ") ;
69
105
}
70
106
}
71
107
@@ -74,20 +110,14 @@ public bool Verify(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature)
74
110
switch ( _type )
75
111
{
76
112
case COSE . KeyType . EC2 :
77
- using ( ECDsa ecdsa = CreateECDsa ( ) )
78
- {
79
- var ecsig = CryptoUtils . SigFromEcDsaSig ( signature . ToArray ( ) , ecdsa . KeySize ) ;
80
- return ecdsa . VerifyData ( data , ecsig , CryptoUtils . HashAlgFromCOSEAlg ( _alg ) ) ;
81
- }
113
+ var ecsig = CryptoUtils . SigFromEcDsaSig ( signature . ToArray ( ) , _ecdsa ! . KeySize ) ;
114
+ return _ecdsa ! . VerifyData ( data , ecsig , CryptoUtils . HashAlgFromCOSEAlg ( _alg ) ) ;
82
115
83
116
case COSE . KeyType . RSA :
84
- using ( RSA rsa = CreateRSA ( ) )
85
- {
86
- return rsa . VerifyData ( data , signature , CryptoUtils . HashAlgFromCOSEAlg ( _alg ) , Padding ) ;
87
- }
117
+ return _rsa ! . VerifyData ( data , signature , CryptoUtils . HashAlgFromCOSEAlg ( _alg ) , Padding ) ;
88
118
89
119
case COSE . KeyType . OKP :
90
- return SignatureAlgorithm . Ed25519 . Verify ( EdDSAPublicKey , data , signature ) ;
120
+ return SignatureAlgorithm . Ed25519 . Verify ( _eddsa ! , data , signature ) ;
91
121
}
92
122
throw new InvalidOperationException ( $ "Missing or unknown kty { _type } ") ;
93
123
}
@@ -182,32 +212,29 @@ internal RSASignaturePadding Padding
182
212
}
183
213
}
184
214
185
- internal NSec . Cryptography . PublicKey EdDSAPublicKey
215
+ internal NSec . Cryptography . PublicKey CreateEdDSA ( )
186
216
{
187
- get
217
+ if ( _type != COSE . KeyType . OKP )
188
218
{
189
- if ( _type != COSE . KeyType . OKP )
190
- {
191
- throw new InvalidOperationException ( $ "Must be a OKP key. Was { _type } ") ;
192
- }
219
+ throw new InvalidOperationException ( $ "Must be a OKP key. Was { _type } ") ;
220
+ }
193
221
194
- switch ( _alg ) // https://www.iana.org/assignments/cose/cose.xhtml#algorithms
195
- {
196
- case COSE . Algorithm . EdDSA :
197
- var crv = ( COSE . EllipticCurve ) ( int ) _cpk [ COSE . KeyTypeParameter . Crv ] ;
198
-
199
- // https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
200
- if ( crv is COSE . EllipticCurve . Ed25519 )
201
- {
202
- return NSec . Cryptography . PublicKey . Import ( SignatureAlgorithm . Ed25519 , ( byte [ ] ) _cpk [ COSE . KeyTypeParameter . X ] , KeyBlobFormat . RawPublicKey ) ;
203
- }
204
- else
205
- {
206
- throw new InvalidOperationException ( $ "Missing or unknown crv { crv } ") ;
207
- }
208
- default :
209
- throw new InvalidOperationException ( $ "Missing or unknown alg { _alg } ") ;
210
- }
222
+ switch ( _alg ) // https://www.iana.org/assignments/cose/cose.xhtml#algorithms
223
+ {
224
+ case COSE . Algorithm . EdDSA :
225
+ var crv = ( COSE . EllipticCurve ) ( int ) _cpk [ COSE . KeyTypeParameter . Crv ] ;
226
+
227
+ // https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
228
+ if ( crv is COSE . EllipticCurve . Ed25519 )
229
+ {
230
+ return NSec . Cryptography . PublicKey . Import ( SignatureAlgorithm . Ed25519 , ( byte [ ] ) _cpk [ COSE . KeyTypeParameter . X ] , KeyBlobFormat . RawPublicKey ) ;
231
+ }
232
+ else
233
+ {
234
+ throw new InvalidOperationException ( $ "Missing or unknown crv { crv } ") ;
235
+ }
236
+ default :
237
+ throw new InvalidOperationException ( $ "Missing or unknown alg { _alg } ") ;
211
238
}
212
239
}
213
240
0 commit comments