@@ -161,7 +161,13 @@ namespace jwt {
161
161
no_key_provided,
162
162
invalid_key_size,
163
163
invalid_key,
164
- create_context_failed
164
+ create_context_failed,
165
+ cert_load_failed,
166
+ get_key_failed,
167
+ write_key_failed,
168
+ write_cert_failed,
169
+ convert_to_pem_failed,
170
+
165
171
};
166
172
/* *
167
173
* \brief Error category for ECDSA errors
@@ -181,6 +187,11 @@ namespace jwt {
181
187
case ecdsa_error::invalid_key_size: return " invalid key size" ;
182
188
case ecdsa_error::invalid_key: return " invalid key" ;
183
189
case ecdsa_error::create_context_failed: return " failed to create context" ;
190
+ case ecdsa_error::cert_load_failed: return " error loading cert into memory" ;
191
+ case ecdsa_error::get_key_failed: return " error getting key from certificate" ;
192
+ case ecdsa_error::write_key_failed: return " error writing key data in PEM format" ;
193
+ case ecdsa_error::write_cert_failed: return " error writing cert data in PEM format" ;
194
+ case ecdsa_error::convert_to_pem_failed: return " failed to convert key to pem" ;
184
195
default : return " unknown ECDSA error" ;
185
196
}
186
197
}
@@ -492,39 +503,40 @@ namespace jwt {
492
503
/* *
493
504
* \brief Extract the public key of a pem certificate
494
505
*
495
- * \param certstr String containing the certificate encoded as pem
496
- * \param pw Password used to decrypt certificate (leave empty if not encrypted)
497
- * \param ec error_code for error_detection (gets cleared if no error occurred)
506
+ * \tparam error_category jwt::error enum category to match with the keys being used
507
+ * \param certstr String containing the certificate encoded as pem
508
+ * \param pw Password used to decrypt certificate (leave empty if not encrypted)
509
+ * \param ec error_code for error_detection (gets cleared if no error occurred)
498
510
*/
499
- inline std::string extract_pubkey_from_cert ( const std::string& certstr, const std::string& pw,
500
- std::error_code& ec) {
511
+ template < typename error_category = error::rsa_error>
512
+ std::string extract_pubkey_from_cert ( const std::string& certstr, const std::string& pw, std::error_code& ec) {
501
513
ec.clear ();
502
514
auto certbio = make_mem_buf_bio (certstr);
503
515
auto keybio = make_mem_buf_bio ();
504
516
if (!certbio || !keybio) {
505
- ec = error::rsa_error ::create_mem_bio_failed;
517
+ ec = error_category ::create_mem_bio_failed;
506
518
return {};
507
519
}
508
520
509
521
std::unique_ptr<X509, decltype (&X509_free)> cert (
510
522
PEM_read_bio_X509 (certbio.get (), nullptr , nullptr , const_cast <char *>(pw.c_str ())), X509_free);
511
523
if (!cert) {
512
- ec = error::rsa_error ::cert_load_failed;
524
+ ec = error_category ::cert_load_failed;
513
525
return {};
514
526
}
515
527
std::unique_ptr<EVP_PKEY, decltype (&EVP_PKEY_free)> key (X509_get_pubkey (cert.get ()), EVP_PKEY_free);
516
528
if (!key) {
517
- ec = error::rsa_error ::get_key_failed;
529
+ ec = error_category ::get_key_failed;
518
530
return {};
519
531
}
520
532
if (PEM_write_bio_PUBKEY (keybio.get (), key.get ()) == 0 ) {
521
- ec = error::rsa_error ::write_key_failed;
533
+ ec = error_category ::write_key_failed;
522
534
return {};
523
535
}
524
536
char * ptr = nullptr ;
525
537
auto len = BIO_get_mem_data (keybio.get (), &ptr);
526
538
if (len <= 0 || ptr == nullptr ) {
527
- ec = error::rsa_error ::convert_to_pem_failed;
539
+ ec = error_category ::convert_to_pem_failed;
528
540
return {};
529
541
}
530
542
return {ptr, static_cast <size_t >(len)};
@@ -533,13 +545,15 @@ namespace jwt {
533
545
/* *
534
546
* \brief Extract the public key of a pem certificate
535
547
*
536
- * \param certstr String containing the certificate encoded as pem
537
- * \param pw Password used to decrypt certificate (leave empty if not encrypted)
538
- * \throw rsa_exception if an error occurred
548
+ * \tparam error_category jwt::error enum category to match with the keys being used
549
+ * \param certstr String containing the certificate encoded as pem
550
+ * \param pw Password used to decrypt certificate (leave empty if not encrypted)
551
+ * \throw templated error_category's type exception if an error occurred
539
552
*/
540
- inline std::string extract_pubkey_from_cert (const std::string& certstr, const std::string& pw = " " ) {
553
+ template <typename error_category = error::rsa_error>
554
+ std::string extract_pubkey_from_cert (const std::string& certstr, const std::string& pw = " " ) {
541
555
std::error_code ec;
542
- auto res = extract_pubkey_from_cert (certstr, pw, ec);
556
+ auto res = extract_pubkey_from_cert<error_category> (certstr, pw, ec);
543
557
error::throw_if_error (ec);
544
558
return res;
545
559
}
@@ -674,38 +688,40 @@ namespace jwt {
674
688
*
675
689
* The string should contain a pem encoded certificate or public key
676
690
*
691
+ * \tparam error_category jwt::error enum category to match with the keys being used
677
692
* \param key String containing the certificate encoded as pem
678
693
* \param password Password used to decrypt certificate (leave empty if not encrypted)
679
694
* \param ec error_code for error_detection (gets cleared if no error occurs)
680
695
*/
681
- inline evp_pkey_handle load_public_key_from_string (const std::string& key, const std::string& password,
682
- std::error_code& ec) {
696
+ template <typename error_category = error::rsa_error>
697
+ evp_pkey_handle load_public_key_from_string (const std::string& key, const std::string& password,
698
+ std::error_code& ec) {
683
699
ec.clear ();
684
700
auto pubkey_bio = make_mem_buf_bio ();
685
701
if (!pubkey_bio) {
686
- ec = error::rsa_error ::create_mem_bio_failed;
702
+ ec = error_category ::create_mem_bio_failed;
687
703
return {};
688
704
}
689
705
if (key.substr (0 , 27 ) == " -----BEGIN CERTIFICATE-----" ) {
690
- auto epkey = helper::extract_pubkey_from_cert (key, password, ec);
706
+ auto epkey = helper::extract_pubkey_from_cert<error_category> (key, password, ec);
691
707
if (ec) return {};
692
708
const int len = static_cast <int >(epkey.size ());
693
709
if (BIO_write (pubkey_bio.get (), epkey.data (), len) != len) {
694
- ec = error::rsa_error ::load_key_bio_write;
710
+ ec = error_category ::load_key_bio_write;
695
711
return {};
696
712
}
697
713
} else {
698
714
const int len = static_cast <int >(key.size ());
699
715
if (BIO_write (pubkey_bio.get (), key.data (), len) != len) {
700
- ec = error::rsa_error ::load_key_bio_write;
716
+ ec = error_category ::load_key_bio_write;
701
717
return {};
702
718
}
703
719
}
704
720
705
721
evp_pkey_handle pkey (PEM_read_bio_PUBKEY (
706
722
pubkey_bio.get (), nullptr , nullptr ,
707
723
(void *)password.data ())); // NOLINT(google-readability-casting) requires `const_cast`
708
- if (!pkey) ec = error::rsa_error ::load_key_bio_read;
724
+ if (!pkey) ec = error_category ::load_key_bio_read;
709
725
return pkey;
710
726
}
711
727
@@ -714,52 +730,59 @@ namespace jwt {
714
730
*
715
731
* The string should contain a pem encoded certificate or public key
716
732
*
717
- * \param key String containing the certificate or key encoded as pem
718
- * \param password Password used to decrypt certificate or key (leave empty if not encrypted)
719
- * \throw rsa_exception if an error occurred
733
+ * \tparam error_category jwt::error enum category to match with the keys being used
734
+ * \param key String containing the certificate encoded as pem
735
+ * \param password Password used to decrypt certificate (leave empty if not encrypted)
736
+ * \throw Templated error_category's type exception if an error occurred
720
737
*/
738
+ template <typename error_category = error::rsa_error>
721
739
inline evp_pkey_handle load_public_key_from_string (const std::string& key, const std::string& password = " " ) {
722
740
std::error_code ec;
723
- auto res = load_public_key_from_string (key, password, ec);
741
+ auto res = load_public_key_from_string<error_category> (key, password, ec);
724
742
error::throw_if_error (ec);
725
743
return res;
726
744
}
727
745
728
746
/* *
729
747
* \brief Load a private key from a string.
730
748
*
731
- * \param key String containing a private key as pem
732
- * \param password Password used to decrypt key (leave empty if not encrypted)
733
- * \param ec error_code for error_detection (gets cleared if no error occurs)
749
+ * \tparam error_category jwt::error enum category to match with the keys being used
750
+ * \param key String containing a private key as pem
751
+ * \param password Password used to decrypt key (leave empty if not encrypted)
752
+ * \param ec error_code for error_detection (gets cleared if no error occurs)
734
753
*/
754
+ template <typename error_category = error::rsa_error>
735
755
inline evp_pkey_handle load_private_key_from_string (const std::string& key, const std::string& password,
736
756
std::error_code& ec) {
737
- auto privkey_bio = make_mem_buf_bio ();
738
- if (!privkey_bio) {
739
- ec = error::rsa_error::create_mem_bio_failed;
757
+ ec.clear ();
758
+ auto private_key_bio = make_mem_buf_bio ();
759
+ if (!private_key_bio) {
760
+ ec = error_category::create_mem_bio_failed;
740
761
return {};
741
762
}
742
763
const int len = static_cast <int >(key.size ());
743
- if (BIO_write (privkey_bio .get (), key.data (), len) != len) {
744
- ec = error::rsa_error ::load_key_bio_write;
764
+ if (BIO_write (private_key_bio .get (), key.data (), len) != len) {
765
+ ec = error_category ::load_key_bio_write;
745
766
return {};
746
767
}
747
768
evp_pkey_handle pkey (
748
- PEM_read_bio_PrivateKey (privkey_bio .get (), nullptr , nullptr , const_cast <char *>(password.c_str ())));
749
- if (!pkey) ec = error::rsa_error ::load_key_bio_read;
769
+ PEM_read_bio_PrivateKey (private_key_bio .get (), nullptr , nullptr , const_cast <char *>(password.c_str ())));
770
+ if (!pkey) ec = error_category ::load_key_bio_read;
750
771
return pkey;
751
772
}
752
773
753
774
/* *
754
775
* \brief Load a private key from a string.
755
776
*
756
- * \param key String containing a private key as pem
757
- * \param password Password used to decrypt key (leave empty if not encrypted)
758
- * \throw rsa_exception if an error occurred
777
+ * \tparam error_category jwt::error enum category to match with the keys being used
778
+ * \param key String containing a private key as pem
779
+ * \param password Password used to decrypt key (leave empty if not encrypted)
780
+ * \throw Templated error_category's type exception if an error occurred
759
781
*/
782
+ template <typename error_category = error::rsa_error>
760
783
inline evp_pkey_handle load_private_key_from_string (const std::string& key, const std::string& password = " " ) {
761
784
std::error_code ec;
762
- auto res = load_private_key_from_string (key, password, ec);
785
+ auto res = load_private_key_from_string<error_category> (key, password, ec);
763
786
error::throw_if_error (ec);
764
787
return res;
765
788
}
@@ -768,95 +791,64 @@ namespace jwt {
768
791
* \brief Load a public key from a string.
769
792
*
770
793
* The string should contain a pem encoded certificate or public key
794
+ *
795
+ * \deprecated Use the templated version load_private_key_from_string with error::ecdsa_error
771
796
*
772
797
* \param key String containing the certificate encoded as pem
773
798
* \param password Password used to decrypt certificate (leave empty if not encrypted)
774
799
* \param ec error_code for error_detection (gets cleared if no error occurs)
775
800
*/
776
801
inline evp_pkey_handle load_public_ec_key_from_string (const std::string& key, const std::string& password,
777
802
std::error_code& ec) {
778
- ec.clear ();
779
- auto pubkey_bio = make_mem_buf_bio ();
780
- if (!pubkey_bio) {
781
- ec = error::ecdsa_error::create_mem_bio_failed;
782
- return {};
783
- }
784
- if (key.substr (0 , 27 ) == " -----BEGIN CERTIFICATE-----" ) {
785
- auto epkey = helper::extract_pubkey_from_cert (key, password, ec);
786
- if (ec) return {};
787
- const int len = static_cast <int >(epkey.size ());
788
- if (BIO_write (pubkey_bio.get (), epkey.data (), len) != len) {
789
- ec = error::ecdsa_error::load_key_bio_write;
790
- return {};
791
- }
792
- } else {
793
- const int len = static_cast <int >(key.size ());
794
- if (BIO_write (pubkey_bio.get (), key.data (), len) != len) {
795
- ec = error::ecdsa_error::load_key_bio_write;
796
- return {};
797
- }
798
- }
799
-
800
- evp_pkey_handle pkey (PEM_read_bio_PUBKEY (
801
- pubkey_bio.get (), nullptr , nullptr ,
802
- (void *)password.data ())); // NOLINT(google-readability-casting) requires `const_cast`
803
- if (!pkey) ec = error::ecdsa_error::load_key_bio_read;
804
- return pkey;
803
+ return load_public_key_from_string<error::ecdsa_error>(key, password, ec);
805
804
}
806
805
807
806
/* *
808
807
* \brief Load a public key from a string.
809
808
*
810
809
* The string should contain a pem encoded certificate or public key
811
810
*
811
+ * \deprecated Use the templated version load_private_key_from_string with error::ecdsa_error
812
+ *
812
813
* \param key String containing the certificate or key encoded as pem
813
814
* \param password Password used to decrypt certificate or key (leave empty if not encrypted)
814
815
* \throw ecdsa_exception if an error occurred
815
816
*/
816
817
inline evp_pkey_handle load_public_ec_key_from_string (const std::string& key,
817
818
const std::string& password = " " ) {
818
819
std::error_code ec;
819
- auto res = load_public_ec_key_from_string (key, password, ec);
820
+ auto res = load_public_key_from_string<error::ecdsa_error> (key, password, ec);
820
821
error::throw_if_error (ec);
821
822
return res;
822
823
}
823
824
824
825
/* *
825
826
* \brief Load a private key from a string.
827
+ *
828
+ * \deprecated Use the templated version load_private_key_from_string with error::ecdsa_error
826
829
*
827
830
* \param key String containing a private key as pem
828
831
* \param password Password used to decrypt key (leave empty if not encrypted)
829
832
* \param ec error_code for error_detection (gets cleared if no error occurs)
830
833
*/
831
834
inline evp_pkey_handle load_private_ec_key_from_string (const std::string& key, const std::string& password,
832
835
std::error_code& ec) {
833
- auto privkey_bio = make_mem_buf_bio ();
834
- if (!privkey_bio) {
835
- ec = error::ecdsa_error::create_mem_bio_failed;
836
- return {};
837
- }
838
- const int len = static_cast <int >(key.size ());
839
- if (BIO_write (privkey_bio.get (), key.data (), len) != len) {
840
- ec = error::ecdsa_error::load_key_bio_write;
841
- return {};
842
- }
843
- evp_pkey_handle pkey (
844
- PEM_read_bio_PrivateKey (privkey_bio.get (), nullptr , nullptr , const_cast <char *>(password.c_str ())));
845
- if (!pkey) ec = error::ecdsa_error::load_key_bio_read;
846
- return pkey;
836
+ return load_private_key_from_string<error::ecdsa_error>(key, password, ec);
847
837
}
848
838
849
839
/* *
850
840
* \brief Load a private key from a string.
851
841
*
842
+ * \deprecated Use the templated version load_private_key_from_string with error::ecdsa_error
843
+ *
852
844
* \param key String containing a private key as pem
853
845
* \param password Password used to decrypt key (leave empty if not encrypted)
854
846
* \throw ecdsa_exception if an error occurred
855
847
*/
856
848
inline evp_pkey_handle load_private_ec_key_from_string (const std::string& key,
857
849
const std::string& password = " " ) {
858
850
std::error_code ec;
859
- auto res = load_private_ec_key_from_string (key, password, ec);
851
+ auto res = load_private_key_from_string<error::ecdsa_error> (key, password, ec);
860
852
error::throw_if_error (ec);
861
853
return res;
862
854
}
0 commit comments