7
7
using System . Security . Cryptography ;
8
8
using System . Text ;
9
9
10
+ using Org . BouncyCastle . Asn1 ;
11
+ using Org . BouncyCastle . Asn1 . Sec ;
12
+ using Org . BouncyCastle . Crypto ;
13
+ using Org . BouncyCastle . Crypto . Digests ;
14
+ using Org . BouncyCastle . Crypto . Parameters ;
15
+
10
16
using Renci . SshNet . Common ;
11
17
using Renci . SshNet . Security . Cryptography ;
12
18
@@ -23,6 +29,7 @@ public class EcdsaKey : Key, IDisposable
23
29
private const string ECDSA_P521_OID_VALUE = "1.3.132.0.35" ; // Also called nistP521or secP521r1
24
30
#pragma warning restore SA1310 // Field names should not contain underscore
25
31
32
+ private int _keySize ;
26
33
private EcdsaDigitalSignature _digitalSignature ;
27
34
private bool _isDisposed ;
28
35
@@ -68,6 +75,27 @@ public override string ToString()
68
75
return string . Format ( "ecdsa-sha2-nistp{0}" , KeyLength ) ;
69
76
}
70
77
78
+ /// <summary>
79
+ /// Gets the Digest to use.
80
+ /// </summary>
81
+ public IDigest Digest
82
+ {
83
+ get
84
+ {
85
+ switch ( KeyLength )
86
+ {
87
+ case 256 :
88
+ return new Sha256Digest ( ) ;
89
+ case 384 :
90
+ return new Sha384Digest ( ) ;
91
+ case 521 :
92
+ return new Sha512Digest ( ) ;
93
+ default :
94
+ throw new SshException ( "Unknown KeySize: " + KeyLength . ToString ( ) ) ;
95
+ }
96
+ }
97
+ }
98
+
71
99
#if NETFRAMEWORK
72
100
/// <summary>
73
101
/// Gets the HashAlgorithm to use.
@@ -122,7 +150,7 @@ public override int KeyLength
122
150
{
123
151
get
124
152
{
125
- return Ecdsa . KeySize ;
153
+ return _keySize ;
126
154
}
127
155
}
128
156
@@ -153,56 +181,81 @@ public override BigInteger[] Public
153
181
byte [ ] curve ;
154
182
byte [ ] qx ;
155
183
byte [ ] qy ;
156
- #if NETFRAMEWORK
157
- var blob = _key . Export ( CngKeyBlobFormat . EccPublicBlob ) ;
158
184
159
- KeyBlobMagicNumber magic ;
160
- using ( var br = new BinaryReader ( new MemoryStream ( blob ) ) )
185
+ if ( PublicKeyParameters != null )
161
186
{
162
- magic = ( KeyBlobMagicNumber ) br . ReadInt32 ( ) ;
163
- var cbKey = br . ReadInt32 ( ) ;
164
- qx = br . ReadBytes ( cbKey ) ;
165
- qy = br . ReadBytes ( cbKey ) ;
187
+ var oid = PublicKeyParameters . PublicKeyParamSet . GetID ( ) ;
188
+ switch ( oid )
189
+ {
190
+ case ECDSA_P256_OID_VALUE :
191
+ curve = Encoding . ASCII . GetBytes ( "nistp256" ) ;
192
+ break ;
193
+ case ECDSA_P384_OID_VALUE :
194
+ curve = Encoding . ASCII . GetBytes ( "nistp384" ) ;
195
+ break ;
196
+ case ECDSA_P521_OID_VALUE :
197
+ curve = Encoding . ASCII . GetBytes ( "nistp521" ) ;
198
+ break ;
199
+ default :
200
+ throw new SshException ( "Unexpected OID: " + oid ) ;
201
+ }
202
+
203
+ qx = PublicKeyParameters . Q . XCoord . GetEncoded ( ) ;
204
+ qy = PublicKeyParameters . Q . YCoord . GetEncoded ( ) ;
166
205
}
206
+ else
207
+ {
208
+ #if NETFRAMEWORK
209
+ var blob = _key . Export ( CngKeyBlobFormat . EccPublicBlob ) ;
210
+
211
+ KeyBlobMagicNumber magic ;
212
+ using ( var br = new BinaryReader ( new MemoryStream ( blob ) ) )
213
+ {
214
+ magic = ( KeyBlobMagicNumber ) br . ReadInt32 ( ) ;
215
+ var cbKey = br . ReadInt32 ( ) ;
216
+ qx = br . ReadBytes ( cbKey ) ;
217
+ qy = br . ReadBytes ( cbKey ) ;
218
+ }
167
219
168
220
#pragma warning disable IDE0010 // Add missing cases
169
- switch ( magic )
170
- {
171
- case KeyBlobMagicNumber . BCRYPT_ECDSA_PUBLIC_P256_MAGIC :
172
- curve = Encoding . ASCII . GetBytes ( "nistp256" ) ;
173
- break ;
174
- case KeyBlobMagicNumber . BCRYPT_ECDSA_PUBLIC_P384_MAGIC :
175
- curve = Encoding . ASCII . GetBytes ( "nistp384" ) ;
176
- break ;
177
- case KeyBlobMagicNumber . BCRYPT_ECDSA_PUBLIC_P521_MAGIC :
178
- curve = Encoding . ASCII . GetBytes ( "nistp521" ) ;
179
- break ;
180
- default :
181
- throw new SshException ( "Unexpected Curve Magic: " + magic ) ;
182
- }
221
+ switch ( magic )
222
+ {
223
+ case KeyBlobMagicNumber . BCRYPT_ECDSA_PUBLIC_P256_MAGIC :
224
+ curve = Encoding . ASCII . GetBytes ( "nistp256" ) ;
225
+ break ;
226
+ case KeyBlobMagicNumber . BCRYPT_ECDSA_PUBLIC_P384_MAGIC :
227
+ curve = Encoding . ASCII . GetBytes ( "nistp384" ) ;
228
+ break ;
229
+ case KeyBlobMagicNumber . BCRYPT_ECDSA_PUBLIC_P521_MAGIC :
230
+ curve = Encoding . ASCII . GetBytes ( "nistp521" ) ;
231
+ break ;
232
+ default :
233
+ throw new SshException ( "Unexpected Curve Magic: " + magic ) ;
234
+ }
183
235
#pragma warning restore IDE0010 // Add missing cases
184
236
#else
185
- var parameter = Ecdsa . ExportParameters ( includePrivateParameters : false ) ;
186
- qx = parameter . Q . X ;
187
- qy = parameter . Q . Y ;
188
- switch ( parameter . Curve . Oid . FriendlyName )
189
- {
190
- case "ECDSA_P256" :
191
- case "nistP256" :
192
- curve = Encoding . ASCII . GetBytes ( "nistp256" ) ;
193
- break ;
194
- case "ECDSA_P384" :
195
- case "nistP384" :
196
- curve = Encoding . ASCII . GetBytes ( "nistp384" ) ;
197
- break ;
198
- case "ECDSA_P521" :
199
- case "nistP521" :
200
- curve = Encoding . ASCII . GetBytes ( "nistp521" ) ;
201
- break ;
202
- default :
203
- throw new SshException ( "Unexpected Curve Name: " + parameter . Curve . Oid . FriendlyName ) ;
204
- }
237
+ var parameter = Ecdsa . ExportParameters ( includePrivateParameters : false ) ;
238
+ qx = parameter . Q . X ;
239
+ qy = parameter . Q . Y ;
240
+ switch ( parameter . Curve . Oid . FriendlyName )
241
+ {
242
+ case "ECDSA_P256" :
243
+ case "nistP256" :
244
+ curve = Encoding . ASCII . GetBytes ( "nistp256" ) ;
245
+ break ;
246
+ case "ECDSA_P384" :
247
+ case "nistP384" :
248
+ curve = Encoding . ASCII . GetBytes ( "nistp384" ) ;
249
+ break ;
250
+ case "ECDSA_P521" :
251
+ case "nistP521" :
252
+ curve = Encoding . ASCII . GetBytes ( "nistp521" ) ;
253
+ break ;
254
+ default :
255
+ throw new SshException ( "Unexpected Curve Name: " + parameter . Curve . Oid . FriendlyName ) ;
256
+ }
205
257
#endif
258
+ }
206
259
207
260
// Make ECPoint from x and y
208
261
// Prepend 04 (uncompressed format) + qx-bytes + qy-bytes
@@ -216,6 +269,18 @@ public override BigInteger[] Public
216
269
}
217
270
}
218
271
272
+ internal ECPrivateKeyParameters PrivateKeyParameters
273
+ {
274
+ get ;
275
+ private set ;
276
+ }
277
+
278
+ internal ECPublicKeyParameters PublicKeyParameters
279
+ {
280
+ get ;
281
+ private set ;
282
+ }
283
+
219
284
/// <summary>
220
285
/// Gets the PrivateKey Bytes.
221
286
/// </summary>
@@ -322,6 +387,65 @@ public EcdsaKey(byte[] data)
322
387
323
388
private void Import ( string curve_oid , byte [ ] publickey , byte [ ] privatekey )
324
389
{
390
+ // ECPoint as BigInteger(2)
391
+ var cord_size = ( publickey . Length - 1 ) / 2 ;
392
+ var qx = new byte [ cord_size ] ;
393
+ Buffer . BlockCopy ( publickey , 1 , qx , 0 , qx . Length ) ;
394
+
395
+ var qy = new byte [ cord_size ] ;
396
+ Buffer . BlockCopy ( publickey , cord_size + 1 , qy , 0 , qy . Length ) ;
397
+
398
+ var isMono = Type . GetType ( "Mono.Runtime" ) == null ;
399
+
400
+ if ( isMono )
401
+ {
402
+ DerObjectIdentifier oid ;
403
+ switch ( curve_oid )
404
+ {
405
+ case ECDSA_P256_OID_VALUE :
406
+ oid = SecObjectIdentifiers . SecP256r1 ;
407
+ _keySize = 256 ;
408
+ break ;
409
+ case ECDSA_P384_OID_VALUE :
410
+ oid = SecObjectIdentifiers . SecP384r1 ;
411
+ _keySize = 384 ;
412
+ break ;
413
+ case ECDSA_P521_OID_VALUE :
414
+ oid = SecObjectIdentifiers . SecP521r1 ;
415
+ _keySize = 521 ;
416
+ break ;
417
+ default :
418
+ throw new SshException ( "Unexpected OID: " + curve_oid ) ;
419
+ }
420
+
421
+ var x9ECParameters = SecNamedCurves . GetByOid ( oid ) ;
422
+ var domainParameter = new ECNamedDomainParameters ( oid , x9ECParameters ) ;
423
+
424
+ if ( privatekey != null )
425
+ {
426
+ privatekey = privatekey . TrimLeadingZeros ( ) . Pad ( cord_size ) ;
427
+ PrivateKey = privatekey ;
428
+
429
+ PrivateKeyParameters = new ECPrivateKeyParameters (
430
+ new Org . BouncyCastle . Math . BigInteger ( 1 , privatekey ) ,
431
+ domainParameter ) ;
432
+
433
+ PublicKeyParameters = new ECPublicKeyParameters (
434
+ domainParameter . G . Multiply ( PrivateKeyParameters . D ) . Normalize ( ) ,
435
+ domainParameter ) ;
436
+ }
437
+ else
438
+ {
439
+ PublicKeyParameters = new ECPublicKeyParameters (
440
+ x9ECParameters . Curve . CreatePoint (
441
+ new Org . BouncyCastle . Math . BigInteger ( 1 , qx ) ,
442
+ new Org . BouncyCastle . Math . BigInteger ( 1 , qy ) ) ,
443
+ domainParameter ) ;
444
+ }
445
+
446
+ return ;
447
+ }
448
+
325
449
#if NETFRAMEWORK
326
450
KeyBlobMagicNumber curve_magic ;
327
451
@@ -364,14 +488,6 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey)
364
488
throw new SshException ( "Unknown: " + curve_oid ) ;
365
489
}
366
490
367
- // ECPoint as BigInteger(2)
368
- var cord_size = ( publickey . Length - 1 ) / 2 ;
369
- var qx = new byte [ cord_size ] ;
370
- Buffer . BlockCopy ( publickey , 1 , qx , 0 , qx . Length ) ;
371
-
372
- var qy = new byte [ cord_size ] ;
373
- Buffer . BlockCopy ( publickey , cord_size + 1 , qy , 0 , qy . Length ) ;
374
-
375
491
if ( privatekey != null )
376
492
{
377
493
privatekey = privatekey . Pad ( cord_size ) ;
@@ -401,21 +517,14 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey)
401
517
_key = CngKey . Import ( blob , privatekey is null ? CngKeyBlobFormat . EccPublicBlob : CngKeyBlobFormat . EccPrivateBlob ) ;
402
518
403
519
Ecdsa = new ECDsaCng ( _key ) ;
520
+ _keySize = Ecdsa . KeySize ;
404
521
#else
405
522
var curve = ECCurve . CreateFromValue ( curve_oid ) ;
406
523
var parameter = new ECParameters
407
524
{
408
525
Curve = curve
409
526
} ;
410
527
411
- // ECPoint as BigInteger(2)
412
- var cord_size = ( publickey . Length - 1 ) / 2 ;
413
- var qx = new byte [ cord_size ] ;
414
- Buffer . BlockCopy ( publickey , 1 , qx , 0 , qx . Length ) ;
415
-
416
- var qy = new byte [ cord_size ] ;
417
- Buffer . BlockCopy ( publickey , cord_size + 1 , qy , 0 , qy . Length ) ;
418
-
419
528
parameter . Q . X = qx ;
420
529
parameter . Q . Y = qy ;
421
530
@@ -426,6 +535,7 @@ private void Import(string curve_oid, byte[] publickey, byte[] privatekey)
426
535
}
427
536
428
537
Ecdsa = ECDsa . Create ( parameter ) ;
538
+ _keySize = Ecdsa . KeySize ;
429
539
#endif
430
540
}
431
541
0 commit comments