@@ -161,7 +161,13 @@ namespace jwt {
161161 no_key_provided,
162162 invalid_key_size,
163163 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+
165171 };
166172 /* *
167173 * \brief Error category for ECDSA errors
@@ -181,6 +187,11 @@ namespace jwt {
181187 case ecdsa_error::invalid_key_size: return " invalid key size" ;
182188 case ecdsa_error::invalid_key: return " invalid key" ;
183189 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" ;
184195 default : return " unknown ECDSA error" ;
185196 }
186197 }
@@ -492,39 +503,40 @@ namespace jwt {
492503 /* *
493504 * \brief Extract the public key of a pem certificate
494505 *
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)
498510 */
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) {
501513 ec.clear ();
502514 auto certbio = make_mem_buf_bio (certstr);
503515 auto keybio = make_mem_buf_bio ();
504516 if (!certbio || !keybio) {
505- ec = error::rsa_error ::create_mem_bio_failed;
517+ ec = error_category ::create_mem_bio_failed;
506518 return {};
507519 }
508520
509521 std::unique_ptr<X509, decltype (&X509_free)> cert (
510522 PEM_read_bio_X509 (certbio.get (), nullptr , nullptr , const_cast <char *>(pw.c_str ())), X509_free);
511523 if (!cert) {
512- ec = error::rsa_error ::cert_load_failed;
524+ ec = error_category ::cert_load_failed;
513525 return {};
514526 }
515527 std::unique_ptr<EVP_PKEY, decltype (&EVP_PKEY_free)> key (X509_get_pubkey (cert.get ()), EVP_PKEY_free);
516528 if (!key) {
517- ec = error::rsa_error ::get_key_failed;
529+ ec = error_category ::get_key_failed;
518530 return {};
519531 }
520532 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;
522534 return {};
523535 }
524536 char * ptr = nullptr ;
525537 auto len = BIO_get_mem_data (keybio.get (), &ptr);
526538 if (len <= 0 || ptr == nullptr ) {
527- ec = error::rsa_error ::convert_to_pem_failed;
539+ ec = error_category ::convert_to_pem_failed;
528540 return {};
529541 }
530542 return {ptr, static_cast <size_t >(len)};
@@ -533,13 +545,15 @@ namespace jwt {
533545 /* *
534546 * \brief Extract the public key of a pem certificate
535547 *
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
539552 */
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 = " " ) {
541555 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);
543557 error::throw_if_error (ec);
544558 return res;
545559 }
@@ -674,38 +688,40 @@ namespace jwt {
674688 *
675689 * The string should contain a pem encoded certificate or public key
676690 *
691+ * \tparam error_category jwt::error enum category to match with the keys being used
677692 * \param key String containing the certificate encoded as pem
678693 * \param password Password used to decrypt certificate (leave empty if not encrypted)
679694 * \param ec error_code for error_detection (gets cleared if no error occurs)
680695 */
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) {
683699 ec.clear ();
684700 auto pubkey_bio = make_mem_buf_bio ();
685701 if (!pubkey_bio) {
686- ec = error::rsa_error ::create_mem_bio_failed;
702+ ec = error_category ::create_mem_bio_failed;
687703 return {};
688704 }
689705 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);
691707 if (ec) return {};
692708 const int len = static_cast <int >(epkey.size ());
693709 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;
695711 return {};
696712 }
697713 } else {
698714 const int len = static_cast <int >(key.size ());
699715 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;
701717 return {};
702718 }
703719 }
704720
705721 evp_pkey_handle pkey (PEM_read_bio_PUBKEY (
706722 pubkey_bio.get (), nullptr , nullptr ,
707723 (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;
709725 return pkey;
710726 }
711727
@@ -714,52 +730,59 @@ namespace jwt {
714730 *
715731 * The string should contain a pem encoded certificate or public key
716732 *
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
720737 */
738+ template <typename error_category = error::rsa_error>
721739 inline evp_pkey_handle load_public_key_from_string (const std::string& key, const std::string& password = " " ) {
722740 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);
724742 error::throw_if_error (ec);
725743 return res;
726744 }
727745
728746 /* *
729747 * \brief Load a private key from a string.
730748 *
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)
734753 */
754+ template <typename error_category = error::rsa_error>
735755 inline evp_pkey_handle load_private_key_from_string (const std::string& key, const std::string& password,
736756 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;
740761 return {};
741762 }
742763 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;
745766 return {};
746767 }
747768 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;
750771 return pkey;
751772 }
752773
753774 /* *
754775 * \brief Load a private key from a string.
755776 *
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
759781 */
782+ template <typename error_category = error::rsa_error>
760783 inline evp_pkey_handle load_private_key_from_string (const std::string& key, const std::string& password = " " ) {
761784 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);
763786 error::throw_if_error (ec);
764787 return res;
765788 }
@@ -768,95 +791,64 @@ namespace jwt {
768791 * \brief Load a public key from a string.
769792 *
770793 * 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
771796 *
772797 * \param key String containing the certificate encoded as pem
773798 * \param password Password used to decrypt certificate (leave empty if not encrypted)
774799 * \param ec error_code for error_detection (gets cleared if no error occurs)
775800 */
776801 inline evp_pkey_handle load_public_ec_key_from_string (const std::string& key, const std::string& password,
777802 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);
805804 }
806805
807806 /* *
808807 * \brief Load a public key from a string.
809808 *
810809 * The string should contain a pem encoded certificate or public key
811810 *
811+ * \deprecated Use the templated version load_private_key_from_string with error::ecdsa_error
812+ *
812813 * \param key String containing the certificate or key encoded as pem
813814 * \param password Password used to decrypt certificate or key (leave empty if not encrypted)
814815 * \throw ecdsa_exception if an error occurred
815816 */
816817 inline evp_pkey_handle load_public_ec_key_from_string (const std::string& key,
817818 const std::string& password = " " ) {
818819 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);
820821 error::throw_if_error (ec);
821822 return res;
822823 }
823824
824825 /* *
825826 * \brief Load a private key from a string.
827+ *
828+ * \deprecated Use the templated version load_private_key_from_string with error::ecdsa_error
826829 *
827830 * \param key String containing a private key as pem
828831 * \param password Password used to decrypt key (leave empty if not encrypted)
829832 * \param ec error_code for error_detection (gets cleared if no error occurs)
830833 */
831834 inline evp_pkey_handle load_private_ec_key_from_string (const std::string& key, const std::string& password,
832835 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);
847837 }
848838
849839 /* *
850840 * \brief Load a private key from a string.
851841 *
842+ * \deprecated Use the templated version load_private_key_from_string with error::ecdsa_error
843+ *
852844 * \param key String containing a private key as pem
853845 * \param password Password used to decrypt key (leave empty if not encrypted)
854846 * \throw ecdsa_exception if an error occurred
855847 */
856848 inline evp_pkey_handle load_private_ec_key_from_string (const std::string& key,
857849 const std::string& password = " " ) {
858850 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);
860852 error::throw_if_error (ec);
861853 return res;
862854 }
0 commit comments