@@ -373,20 +373,36 @@ pub fn op_node_sign(
373
373
374
374
let oid;
375
375
let pkey = match format {
376
- "pem" => {
377
- if label == "PRIVATE KEY" {
376
+ "pem" => match label {
377
+ "PRIVATE KEY" => {
378
378
let pk_info = pkcs8:: PrivateKeyInfo :: try_from ( doc. as_bytes ( ) ) ?;
379
379
oid = pk_info. algorithm . oid ;
380
380
pk_info. private_key
381
- } else if label == "RSA PRIVATE KEY" {
381
+ }
382
+ "RSA PRIVATE KEY" => {
382
383
oid = RSA_ENCRYPTION_OID ;
383
384
doc. as_bytes ( )
384
- } else {
385
- return Err ( type_error ( "Invalid PEM label" ) ) ;
386
385
}
387
- }
386
+ "EC PRIVATE KEY" => {
387
+ let ec_pk = sec1:: EcPrivateKey :: from_der ( doc. as_bytes ( ) ) ?;
388
+ match ec_pk. parameters {
389
+ Some ( sec1:: EcParameters :: NamedCurve ( o) ) => {
390
+ oid = o;
391
+ ec_pk. private_key
392
+ }
393
+ // https://datatracker.ietf.org/doc/html/rfc5915#section-3
394
+ //
395
+ // Though the ASN.1 indicates that
396
+ // the parameters field is OPTIONAL, implementations that conform to
397
+ // this document MUST always include the parameters field.
398
+ _ => return Err ( type_error ( "invalid ECPrivateKey params" ) ) ,
399
+ }
400
+ }
401
+ _ => return Err ( type_error ( "Invalid PEM label" ) ) ,
402
+ } ,
388
403
_ => return Err ( type_error ( "Unsupported key format" ) ) ,
389
404
} ;
405
+
390
406
match oid {
391
407
RSA_ENCRYPTION_OID => {
392
408
use rsa:: pkcs1v15:: SigningKey ;
@@ -419,6 +435,25 @@ pub fn op_node_sign(
419
435
. into ( ) ,
420
436
)
421
437
}
438
+ // signature structure encoding is DER by default for DSA and ECDSA.
439
+ //
440
+ // TODO(@littledivy): Validate public_key if present
441
+ ID_SECP256R1_OID => {
442
+ let key = p256:: ecdsa:: SigningKey :: from_slice ( pkey) ?;
443
+ Ok (
444
+ key
445
+ . sign_prehash ( digest)
446
+ . map ( |sig : p256:: ecdsa:: Signature | sig. to_der ( ) . to_vec ( ) . into ( ) ) ?,
447
+ )
448
+ }
449
+ ID_SECP384R1_OID => {
450
+ let key = p384:: ecdsa:: SigningKey :: from_slice ( pkey) ?;
451
+ Ok (
452
+ key
453
+ . sign_prehash ( digest)
454
+ . map ( |sig : p384:: ecdsa:: Signature | sig. to_der ( ) . to_vec ( ) . into ( ) ) ?,
455
+ )
456
+ }
422
457
_ => Err ( type_error ( "Unsupported signing key" ) ) ,
423
458
}
424
459
}
@@ -704,30 +739,32 @@ pub async fn op_node_dsa_generate_async(
704
739
fn ec_generate (
705
740
named_curve : & str ,
706
741
) -> Result < ( ToJsBuffer , ToJsBuffer ) , AnyError > {
707
- use ring:: signature:: EcdsaKeyPair ;
708
- use ring:: signature:: KeyPair ;
742
+ use elliptic_curve:: sec1:: ToEncodedPoint ;
709
743
710
- let curve = match named_curve {
744
+ let mut rng = rand:: thread_rng ( ) ;
745
+ // TODO(@littledivy): Support public key point encoding.
746
+ // Default is uncompressed.
747
+ match named_curve {
711
748
"P-256" | "prime256v1" | "secp256r1" => {
712
- & ring:: signature:: ECDSA_P256_SHA256_FIXED_SIGNING
749
+ let key = p256:: SecretKey :: random ( & mut rng) ;
750
+ let public_key = key. public_key ( ) ;
751
+
752
+ Ok ( (
753
+ key. to_bytes ( ) . to_vec ( ) . into ( ) ,
754
+ public_key. to_encoded_point ( false ) . as_ref ( ) . to_vec ( ) . into ( ) ,
755
+ ) )
713
756
}
714
757
"P-384" | "prime384v1" | "secp384r1" => {
715
- & ring:: signature:: ECDSA_P384_SHA384_FIXED_SIGNING
716
- }
717
- _ => return Err ( type_error ( "Unsupported named curve" ) ) ,
718
- } ;
719
-
720
- let rng = ring:: rand:: SystemRandom :: new ( ) ;
758
+ let key = p384:: SecretKey :: random ( & mut rng) ;
759
+ let public_key = key. public_key ( ) ;
721
760
722
- let pkcs8 = EcdsaKeyPair :: generate_pkcs8 ( curve, & rng)
723
- . map_err ( |_| type_error ( "Failed to generate EC key" ) ) ?;
724
-
725
- let public_key = EcdsaKeyPair :: from_pkcs8 ( curve, pkcs8. as_ref ( ) , & rng)
726
- . map_err ( |_| type_error ( "Failed to generate EC key" ) ) ?
727
- . public_key ( )
728
- . as_ref ( )
729
- . to_vec ( ) ;
730
- Ok ( ( pkcs8. as_ref ( ) . to_vec ( ) . into ( ) , public_key. into ( ) ) )
761
+ Ok ( (
762
+ key. to_bytes ( ) . to_vec ( ) . into ( ) ,
763
+ public_key. to_encoded_point ( false ) . as_ref ( ) . to_vec ( ) . into ( ) ,
764
+ ) )
765
+ }
766
+ _ => Err ( type_error ( "Unsupported named curve" ) ) ,
767
+ }
731
768
}
732
769
733
770
#[ op2]
@@ -1363,11 +1400,8 @@ fn parse_private_key(
1363
1400
) -> Result < pkcs8:: SecretDocument , AnyError > {
1364
1401
match format {
1365
1402
"pem" => {
1366
- let ( label , doc) =
1403
+ let ( _ , doc) =
1367
1404
pkcs8:: SecretDocument :: from_pem ( std:: str:: from_utf8 ( key) . unwrap ( ) ) ?;
1368
- if label != "PRIVATE KEY" {
1369
- return Err ( type_error ( "Invalid PEM label" ) ) ;
1370
- }
1371
1405
Ok ( doc)
1372
1406
}
1373
1407
"der" => {
0 commit comments