@@ -490,13 +490,15 @@ pub fn gen_saml_assertion_id() -> String {
490
490
enum SigAlg {
491
491
Unimplemented ,
492
492
RsaSha256 ,
493
+ EcdsaSha256 ,
493
494
}
494
495
495
496
impl FromStr for SigAlg {
496
497
type Err = Box < dyn std:: error:: Error > ;
497
498
fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
498
499
match s {
499
500
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" => Ok ( SigAlg :: RsaSha256 ) ,
501
+ "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256" => Ok ( SigAlg :: EcdsaSha256 ) ,
500
502
_ => Ok ( SigAlg :: Unimplemented ) ,
501
503
}
502
504
}
@@ -509,33 +511,45 @@ pub enum UrlVerifierError {
509
511
}
510
512
511
513
pub struct UrlVerifier {
512
- keypair : openssl:: pkey:: PKey < openssl:: pkey:: Public > ,
514
+ public_key : openssl:: pkey:: PKey < openssl:: pkey:: Public > ,
513
515
}
514
516
515
517
impl UrlVerifier {
516
518
pub fn from_rsa_pem ( public_key_pem : & [ u8 ] ) -> Result < Self , Box < dyn std:: error:: Error > > {
517
519
let public = openssl:: rsa:: Rsa :: public_key_from_pem ( public_key_pem) ?;
518
- let keypair = openssl:: pkey:: PKey :: from_rsa ( public) ?;
519
- Ok ( Self { keypair } )
520
+ let public_key = openssl:: pkey:: PKey :: from_rsa ( public) ?;
521
+ Ok ( Self { public_key } )
520
522
}
521
523
522
524
pub fn from_rsa_der ( public_key_der : & [ u8 ] ) -> Result < Self , Box < dyn std:: error:: Error > > {
523
525
let public = openssl:: rsa:: Rsa :: public_key_from_der ( public_key_der) ?;
524
- let keypair = openssl:: pkey:: PKey :: from_rsa ( public) ?;
525
- Ok ( Self { keypair } )
526
+ let public_key = openssl:: pkey:: PKey :: from_rsa ( public) ?;
527
+ Ok ( Self { public_key } )
528
+ }
529
+
530
+ pub fn from_ec_pem ( public_key_pem : & [ u8 ] ) -> Result < Self , Box < dyn std:: error:: Error > > {
531
+ let public = openssl:: ec:: EcKey :: public_key_from_pem ( public_key_pem) ?;
532
+ let public_key = openssl:: pkey:: PKey :: from_ec_key ( public) ?;
533
+ Ok ( Self { public_key } )
534
+ }
535
+
536
+ pub fn from_ec_der ( public_key_der : & [ u8 ] ) -> Result < Self , Box < dyn std:: error:: Error > > {
537
+ let public = openssl:: ec:: EcKey :: public_key_from_der ( public_key_der) ?;
538
+ let public_key = openssl:: pkey:: PKey :: from_ec_key ( public) ?;
539
+ Ok ( Self { public_key } )
526
540
}
527
541
528
542
pub fn from_x509_cert_pem ( public_cert_pem : & str ) -> Result < Self , Box < dyn std:: error:: Error > > {
529
543
let x509 = openssl:: x509:: X509 :: from_pem ( public_cert_pem. as_bytes ( ) ) ?;
530
- let keypair = x509. public_key ( ) ?;
531
- Ok ( Self { keypair } )
544
+ let public_key = x509. public_key ( ) ?;
545
+ Ok ( Self { public_key } )
532
546
}
533
547
534
548
pub fn from_x509 (
535
549
public_cert : & openssl:: x509:: X509 ,
536
550
) -> Result < Self , Box < dyn std:: error:: Error > > {
537
- let keypair = public_cert. public_key ( ) ?;
538
- Ok ( Self { keypair } )
551
+ let public_key = public_cert. public_key ( ) ?;
552
+ Ok ( Self { public_key } )
539
553
}
540
554
541
555
// Signed url should look like:
@@ -660,9 +674,10 @@ impl UrlVerifier {
660
674
let mut verifier = openssl:: sign:: Verifier :: new (
661
675
match sig_alg {
662
676
SigAlg :: RsaSha256 => openssl:: hash:: MessageDigest :: sha256 ( ) ,
677
+ SigAlg :: EcdsaSha256 => openssl:: hash:: MessageDigest :: sha256 ( ) ,
663
678
_ => panic ! ( "sig_alg is bad!" ) ,
664
679
} ,
665
- & self . keypair ,
680
+ & self . public_key ,
666
681
) ?;
667
682
668
683
verifier. update ( data) ?;
@@ -704,6 +719,61 @@ mod test {
704
719
. make_authentication_request ( "http://dummy.fake/saml" )
705
720
. unwrap ( ) ;
706
721
722
+ let private_key = openssl:: rsa:: Rsa :: private_key_from_der ( private_key) . unwrap ( ) ;
723
+ let private_key = openssl:: pkey:: PKey :: from_rsa ( private_key) . unwrap ( ) ;
724
+
725
+ let signed_request_url = authn_request
726
+ . signed_redirect ( "" , private_key)
727
+ . unwrap ( )
728
+ . unwrap ( ) ;
729
+
730
+ // percent encoeded URL:
731
+ // http://dummy.fake/saml?SAMLRequest=..&SigAlg=..&Signature=..
732
+ //
733
+ // percent encoded URI:
734
+ // /saml?SAMLRequest=..&SigAlg=..&Signature=..
735
+ //
736
+ let uri_string: & String = & signed_request_url[ url:: Position :: BeforePath ..] . to_string ( ) ;
737
+ assert ! ( uri_string. starts_with( "/saml?SAMLRequest=" ) ) ;
738
+
739
+ let url_verifier =
740
+ UrlVerifier :: from_x509 ( & sp. idp_signing_certs ( ) . unwrap ( ) . unwrap ( ) [ 0 ] ) . unwrap ( ) ;
741
+
742
+ assert ! ( url_verifier
743
+ . verify_percent_encoded_request_uri_string( uri_string)
744
+ . unwrap( ) , ) ;
745
+ }
746
+
747
+ #[ test]
748
+ fn test_verify_uri_ec ( ) {
749
+ let private_key = include_bytes ! ( concat!(
750
+ env!( "CARGO_MANIFEST_DIR" ) ,
751
+ "/test_vectors/ec_private.pem"
752
+ ) ) ;
753
+
754
+ let idp_metadata_xml = include_str ! ( concat!(
755
+ env!( "CARGO_MANIFEST_DIR" ) ,
756
+ "/test_vectors/idp_ecdsa_metadata.xml"
757
+ ) ) ;
758
+
759
+ let response_instant = "2014-07-17T01:01:48Z" . parse :: < DateTime < Utc > > ( ) . unwrap ( ) ;
760
+ let max_issue_delay = Utc :: now ( ) - response_instant + chrono:: Duration :: seconds ( 60 ) ;
761
+
762
+ let sp = ServiceProvider {
763
+ metadata_url : Some ( "http://test_accept_signed_with_correct_key.test" . into ( ) ) ,
764
+ acs_url : Some ( "http://sp.example.com/demo1/index.php?acs" . into ( ) ) ,
765
+ idp_metadata : idp_metadata_xml. parse ( ) . unwrap ( ) ,
766
+ max_issue_delay,
767
+ ..Default :: default ( )
768
+ } ;
769
+
770
+ let authn_request = sp
771
+ . make_authentication_request ( "http://dummy.fake/saml" )
772
+ . unwrap ( ) ;
773
+
774
+ let private_key = openssl:: ec:: EcKey :: private_key_from_pem ( private_key) . unwrap ( ) ;
775
+ let private_key = openssl:: pkey:: PKey :: from_ec_key ( private_key) . unwrap ( ) ;
776
+
707
777
let signed_request_url = authn_request
708
778
. signed_redirect ( "" , private_key)
709
779
. unwrap ( )
0 commit comments