@@ -630,6 +630,111 @@ namespace jwt {
630
630
return res;
631
631
}
632
632
633
+ /* *
634
+ * \brief Load a public key from a string.
635
+ *
636
+ * The string should contain a pem encoded certificate or public key
637
+ *
638
+ * \param certstr String containing the certificate encoded as pem
639
+ * \param pw Password used to decrypt certificate (leave empty if not encrypted)
640
+ * \param ec error_code for error_detection (gets cleared if no error occures)
641
+ */
642
+ inline std::shared_ptr<EVP_PKEY>
643
+ load_public_ec_key_from_string (const std::string& key, const std::string& password, std::error_code& ec) {
644
+ ec.clear ();
645
+ std::unique_ptr<BIO, decltype (&BIO_free_all)> pubkey_bio (BIO_new (BIO_s_mem ()), BIO_free_all);
646
+ if (!pubkey_bio) {
647
+ ec = error::ecdsa_error::create_mem_bio_failed;
648
+ return nullptr ;
649
+ }
650
+ if (key.substr (0 , 27 ) == " -----BEGIN CERTIFICATE-----" ) {
651
+ auto epkey = helper::extract_pubkey_from_cert (key, password, ec);
652
+ if (ec) return nullptr ;
653
+ const int len = static_cast <int >(epkey.size ());
654
+ if (BIO_write (pubkey_bio.get (), epkey.data (), len) != len) {
655
+ ec = error::ecdsa_error::load_key_bio_write;
656
+ return nullptr ;
657
+ }
658
+ } else {
659
+ const int len = static_cast <int >(key.size ());
660
+ if (BIO_write (pubkey_bio.get (), key.data (), len) != len) {
661
+ ec = error::ecdsa_error::load_key_bio_write;
662
+ return nullptr ;
663
+ }
664
+ }
665
+
666
+ std::shared_ptr<EVP_PKEY> pkey (
667
+ PEM_read_bio_PUBKEY (pubkey_bio.get (), nullptr , nullptr ,
668
+ (void *)password.data ()), // NOLINT(google-readability-casting) requires `const_cast`
669
+ EVP_PKEY_free);
670
+ if (!pkey) {
671
+ ec = error::ecdsa_error::load_key_bio_read;
672
+ return nullptr ;
673
+ }
674
+ return pkey;
675
+ }
676
+
677
+ /* *
678
+ * \brief Load a public key from a string.
679
+ *
680
+ * The string should contain a pem encoded certificate or public key
681
+ *
682
+ * \param certstr String containing the certificate or key encoded as pem
683
+ * \param pw Password used to decrypt certificate or key (leave empty if not encrypted)
684
+ * \throw ecdsa_exception if an error occurred
685
+ */
686
+ inline std::shared_ptr<EVP_PKEY> load_public_ec_key_from_string (const std::string& key,
687
+ const std::string& password = " " ) {
688
+ std::error_code ec;
689
+ auto res = load_public_ec_key_from_string (key, password, ec);
690
+ error::throw_if_error (ec);
691
+ return res;
692
+ }
693
+
694
+ /* *
695
+ * \brief Load a private key from a string.
696
+ *
697
+ * \param key String containing a private key as pem
698
+ * \param pw Password used to decrypt key (leave empty if not encrypted)
699
+ * \param ec error_code for error_detection (gets cleared if no error occures)
700
+ */
701
+ inline std::shared_ptr<EVP_PKEY>
702
+ load_private_ec_key_from_string (const std::string& key, const std::string& password, std::error_code& ec) {
703
+ std::unique_ptr<BIO, decltype (&BIO_free_all)> privkey_bio (BIO_new (BIO_s_mem ()), BIO_free_all);
704
+ if (!privkey_bio) {
705
+ ec = error::ecdsa_error::create_mem_bio_failed;
706
+ return nullptr ;
707
+ }
708
+ const int len = static_cast <int >(key.size ());
709
+ if (BIO_write (privkey_bio.get (), key.data (), len) != len) {
710
+ ec = error::ecdsa_error::load_key_bio_write;
711
+ return nullptr ;
712
+ }
713
+ std::shared_ptr<EVP_PKEY> pkey (
714
+ PEM_read_bio_PrivateKey (privkey_bio.get (), nullptr , nullptr , const_cast <char *>(password.c_str ())),
715
+ EVP_PKEY_free);
716
+ if (!pkey) {
717
+ ec = error::ecdsa_error::load_key_bio_read;
718
+ return nullptr ;
719
+ }
720
+ return pkey;
721
+ }
722
+
723
+ /* *
724
+ * \brief Load a private key from a string.
725
+ *
726
+ * \param key String containing a private key as pem
727
+ * \param pw Password used to decrypt key (leave empty if not encrypted)
728
+ * \throw ecdsa_exception if an error occurred
729
+ */
730
+ inline std::shared_ptr<EVP_PKEY> load_private_ec_key_from_string (const std::string& key,
731
+ const std::string& password = " " ) {
732
+ std::error_code ec;
733
+ auto res = load_private_ec_key_from_string (key, password, ec);
734
+ error::throw_if_error (ec);
735
+ return res;
736
+ }
737
+
633
738
/* *
634
739
* Convert a OpenSSL BIGNUM to a std::string
635
740
* \param bn BIGNUM to convert
@@ -883,46 +988,19 @@ namespace jwt {
883
988
ecdsa (const std::string& public_key, const std::string& private_key, const std::string& public_key_password,
884
989
const std::string& private_key_password, const EVP_MD* (*md)(), std::string name, size_t siglen)
885
990
: md(md), alg_name(std::move(name)), signature_length(siglen) {
886
- if (!public_key.empty ()) {
887
- std::unique_ptr<BIO, decltype (&BIO_free_all)> pubkey_bio (BIO_new (BIO_s_mem ()), BIO_free_all);
888
- if (!pubkey_bio) throw ecdsa_exception (error::ecdsa_error::create_mem_bio_failed);
889
- if (public_key.substr (0 , 27 ) == " -----BEGIN CERTIFICATE-----" ) {
890
- auto epkey = helper::extract_pubkey_from_cert (public_key, public_key_password);
891
- const int len = static_cast <int >(epkey.size ());
892
- if (BIO_write (pubkey_bio.get (), epkey.data (), len) != len)
893
- throw ecdsa_exception (error::ecdsa_error::load_key_bio_write);
894
- } else {
895
- const int len = static_cast <int >(public_key.size ());
896
- if (BIO_write (pubkey_bio.get (), public_key.data (), len) != len)
897
- throw ecdsa_exception (error::ecdsa_error::load_key_bio_write);
898
- }
899
-
900
- pkey.reset (PEM_read_bio_EC_PUBKEY (
901
- pubkey_bio.get (), nullptr , nullptr ,
902
- (void *)public_key_password
903
- .c_str ()), // NOLINT(google-readability-casting) requires `const_cast`
904
- EC_KEY_free);
905
- if (!pkey) throw ecdsa_exception (error::ecdsa_error::load_key_bio_read);
906
- size_t keysize = EC_GROUP_get_degree (EC_KEY_get0_group (pkey.get ()));
907
- if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521 ))
908
- throw ecdsa_exception (error::ecdsa_error::invalid_key_size);
909
- }
910
-
911
991
if (!private_key.empty ()) {
912
- std::unique_ptr<BIO, decltype (&BIO_free_all)> privkey_bio (BIO_new (BIO_s_mem ()), BIO_free_all);
913
- if (!privkey_bio) throw ecdsa_exception (error::ecdsa_error::create_mem_bio_failed);
914
- const int len = static_cast <int >(private_key.size ());
915
- if (BIO_write (privkey_bio.get (), private_key.data (), len) != len)
916
- throw ecdsa_exception (error::ecdsa_error::load_key_bio_write);
917
- pkey.reset (PEM_read_bio_ECPrivateKey (privkey_bio.get (), nullptr , nullptr ,
918
- const_cast <char *>(private_key_password.c_str ())),
919
- EC_KEY_free);
920
- if (!pkey) throw ecdsa_exception (error::ecdsa_error::load_key_bio_read);
921
- size_t keysize = EC_GROUP_get_degree (EC_KEY_get0_group (pkey.get ()));
922
- if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521 ))
923
- throw ecdsa_exception (error::ecdsa_error::invalid_key_size);
992
+ auto epkey = helper::load_private_ec_key_from_string (private_key, private_key_password);
993
+ pkey.reset (EVP_PKEY_get1_EC_KEY (epkey.get ()), EC_KEY_free);
994
+ } else if (!public_key.empty ()) {
995
+ auto epkey = helper::load_public_ec_key_from_string (public_key, public_key_password);
996
+ pkey.reset (EVP_PKEY_get1_EC_KEY (epkey.get ()), EC_KEY_free);
997
+ } else {
998
+ throw ecdsa_exception (error::ecdsa_error::no_key_provided);
924
999
}
925
- if (!pkey) throw ecdsa_exception (error::ecdsa_error::no_key_provided);
1000
+ if (!pkey) throw ecdsa_exception (error::ecdsa_error::invalid_key);
1001
+ size_t keysize = EC_GROUP_get_degree (EC_KEY_get0_group (pkey.get ()));
1002
+ if (keysize != signature_length * 4 && (signature_length != 132 || keysize != 521 ))
1003
+ throw ecdsa_exception (error::ecdsa_error::invalid_key_size);
926
1004
927
1005
if (EC_KEY_check_key (pkey.get ()) == 0 ) throw ecdsa_exception (error::ecdsa_error::invalid_key);
928
1006
}
0 commit comments