diff options
author | lloyd <[email protected]> | 2009-10-09 22:28:02 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2009-10-09 22:28:02 +0000 |
commit | 9db719642349bc37126dee4b2837d3bba022d734 (patch) | |
tree | d77b7f94dbba6b7852da7c3e075bcd548b74caaf | |
parent | d970d9feb203e497f72f1e9b4dc095b1d7ca308f (diff) |
Reasonably functional RSA support; keygen, import/export, encrypt/decrypt, sign/verify
-rw-r--r-- | src/pubkey/rsa/rsa.h | 8 | ||||
-rw-r--r-- | src/wrap/python/core.cpp | 30 | ||||
-rw-r--r-- | src/wrap/python/pk.cpp | 125 | ||||
-rw-r--r-- | src/wrap/python/python_botan.h | 30 | ||||
-rw-r--r-- | src/wrap/python/rsa.cpp | 194 |
5 files changed, 231 insertions, 156 deletions
diff --git a/src/pubkey/rsa/rsa.h b/src/pubkey/rsa/rsa.h index f07533a4f..0580fe8eb 100644 --- a/src/pubkey/rsa/rsa.h +++ b/src/pubkey/rsa/rsa.h @@ -28,7 +28,13 @@ class BOTAN_DLL RSA_PublicKey : public PK_Encrypting_Key, SecureVector<byte> verify(const byte[], u32bit) const; RSA_PublicKey() {} - RSA_PublicKey(const BigInt&, const BigInt&); + + /** + * Create a RSA_PublicKey + * @arg n the modulus + * @arg e the exponent + */ + RSA_PublicKey(const BigInt& n, const BigInt& e); protected: BigInt public_op(const BigInt&) const; }; diff --git a/src/wrap/python/core.cpp b/src/wrap/python/core.cpp index 59df863de..40af71ecf 100644 --- a/src/wrap/python/core.cpp +++ b/src/wrap/python/core.cpp @@ -11,34 +11,6 @@ using namespace Botan; #include "python_botan.h" -class Python_RandomNumberGenerator - { - public: - Python_RandomNumberGenerator() - { rng = RandomNumberGenerator::make_rng(); } - ~Python_RandomNumberGenerator() { delete rng; } - - std::string name() const { return rng->name(); } - - void reseed() { rng->reseed(192); } - - int gen_random_byte() { return rng->next_byte(); } - - std::string gen_random(int n) - { - std::string s(n, 0); - rng->randomize(reinterpret_cast<byte*>(&s[0]), n); - return s; - } - - void add_entropy(const std::string& in) - { rng->add_entropy(reinterpret_cast<const byte*>(in.c_str()), in.length()); } - - RandomNumberGenerator& get_underlying_rng() { return *rng; } - private: - RandomNumberGenerator* rng; - }; - class Py_Cipher { public: @@ -222,6 +194,6 @@ BOOST_PYTHON_MODULE(_botan) python::def("cryptobox_decrypt", cryptobox_decrypt); export_filters(); - export_pk(); + export_rsa(); export_x509(); } diff --git a/src/wrap/python/pk.cpp b/src/wrap/python/pk.cpp deleted file mode 100644 index 72d3294b8..000000000 --- a/src/wrap/python/pk.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/************************************************* -* Boost.Python module definition * -* (C) 1999-2007 Jack Lloyd * -*************************************************/ - -#include <botan/rsa.h> -#include <botan/dsa.h> -#include <botan/dh.h> -#include <botan/look_pk.h> -using namespace Botan; - -#include <boost/python.hpp> -namespace python = boost::python; - -std::string encode_pub(const Public_Key* key, - const std::string& type) - { - if(type == "DER") - { - Pipe pipe; - pipe.start_msg(); - X509::encode(*key, pipe, RAW_BER); - pipe.end_msg(); - return pipe.read_all_as_string(); - } - else if(type == "PEM") - return X509::PEM_encode(*key); - else - throw Encoding_Error("Unknown key encoding method " + type); - } - -std::string encode_priv(const Private_Key* key, - const std::string& type) - { - if(type == "DER") - { - Pipe pipe; - PKCS8::encode(*key, pipe, RAW_BER); - return pipe.read_all_as_string(); - } - else if(type == "PEM") - return PKCS8::PEM_encode(*key); - else - throw Encoding_Error("Unknown key encoding method " + type); - } - -/* -Private_Key* load_priv(const std::string& file, const std::string& pass) - { - return PKCS8::load_key(file, pass); - } - -Public_Key* load_public(const std::string& file) - { - return X509::load_key(file); - } -*/ - -/* -std::string encrypt_string(const PK_Encryptor* enc, const std::string& in) - { - SecureVector<byte> cipher = enc->encrypt((const byte*)in.data(), in.length()); - return std::string((const char*)cipher.begin(), cipher.size()); - } - -std::string decrypt_string(const PK_Decryptor* dec, const std::string& in) - { - SecureVector<byte> plain = dec->decrypt((const byte*)in.data(), in.length()); - return std::string((const char*)plain.begin(), plain.size()); - } -*/ - -void export_pk() - { - /* - python::def("private_key", load_priv, - python::return_value_policy<python::manage_new_object>()); - python::def("public_key", load_public, - python::return_value_policy<python::manage_new_object>()); - */ - - python::class_<Public_Key, boost::noncopyable> - ("Public_Key", python::no_init) - .add_property("name", &Public_Key::algo_name) - .add_property("max_input_bits", &Public_Key::max_input_bits) - .def("public_key", encode_pub); - - python::class_<PK_Encrypting_Key, python::bases<Public_Key>, boost::noncopyable> - ("PK_Encrypting_Key", python::no_init); - - python::class_<Private_Key, python::bases<Public_Key>, boost::noncopyable> - ("Private_Key", python::no_init) - .def("private_key", encode_priv); - - python::class_<PK_Decrypting_Key, python::bases<Private_Key>, boost::noncopyable> - ("PK_Decrypting_Key", python::no_init); - - python::class_<RSA_PublicKey, python::bases<PK_Encrypting_Key> > - ("RSA_PublicKey", python::no_init); - - python::class_<DSA_PublicKey, python::bases<Public_Key> > - ("DSA_PublicKey", python::no_init); - - /* - python::class_<RSA_PrivateKey, python::bases<RSA_PublicKey, PK_Decrypting_Key> > - ("RSA_PrivateKey", python::init<u32bit>()); - */ - - /* - python::class_<PK_Encryptor, boost::noncopyable> - ("PK_Encryptor", python::no_init) - .def("__init__", - python::make_constructor(get_pk_encryptor, - python::with_custodian_and_ward_postcall<0, 1>())) - .def("max_input", &PK_Encryptor::maximum_input_size) - .def("encrypt", encrypt_string); - */ - - /* - python::class_<PK_Decryptor, boost::noncopyable> - ("PK_Decryptor", python::no_init) - .def("__init__", python::make_constructor(get_pk_decryptor)) - .def("decrypt", decrypt_string); - */ - } diff --git a/src/wrap/python/python_botan.h b/src/wrap/python/python_botan.h index 18c51dbb1..646c2e2c1 100644 --- a/src/wrap/python/python_botan.h +++ b/src/wrap/python/python_botan.h @@ -11,7 +11,7 @@ using namespace Botan; namespace python = boost::python; extern void export_filters(); -extern void export_pk(); +extern void export_rsa(); extern void export_x509(); class Bad_Size : public Exception @@ -48,4 +48,32 @@ inline python::object get_owner(T* me) python::borrowed(python::detail::wrapper_base_::get_owner(*me)))); } +class Python_RandomNumberGenerator + { + public: + Python_RandomNumberGenerator() + { rng = RandomNumberGenerator::make_rng(); } + ~Python_RandomNumberGenerator() { delete rng; } + + std::string name() const { return rng->name(); } + + void reseed() { rng->reseed(192); } + + int gen_random_byte() { return rng->next_byte(); } + + std::string gen_random(int n) + { + std::string s(n, 0); + rng->randomize(reinterpret_cast<byte*>(&s[0]), n); + return s; + } + + void add_entropy(const std::string& in) + { rng->add_entropy(reinterpret_cast<const byte*>(in.c_str()), in.length()); } + + RandomNumberGenerator& get_underlying_rng() { return *rng; } + private: + RandomNumberGenerator* rng; + }; + #endif diff --git a/src/wrap/python/rsa.cpp b/src/wrap/python/rsa.cpp new file mode 100644 index 000000000..895725384 --- /dev/null +++ b/src/wrap/python/rsa.cpp @@ -0,0 +1,194 @@ +/* +* Boost.Python module definition +* (C) 1999-2007 Jack Lloyd +* +* Distributed under the terms of the Botan license +*/ + +#include <botan/rsa.h> +#include <botan/look_pk.h> +#include <botan/pubkey.h> +#include <botan/x509_key.h> +using namespace Botan; + +#include "python_botan.h" +#include <sstream> + +std::string bigint2str(const BigInt& n) + { + std::ostringstream out; + out << n; + return out.str(); + } + +std::string secvec2str(const MemoryRegion<byte>& vec) + { + std::string str(vec.size(), 0); + memcpy(&str[0], vec.begin(), vec.size()); + return str; + } + +class Py_RSA_PrivateKey + { + public: + Py_RSA_PrivateKey(std::string pem_str, + Python_RandomNumberGenerator& rng, + std::string pass); + + Py_RSA_PrivateKey(u32bit bits, Python_RandomNumberGenerator& rng); + ~Py_RSA_PrivateKey() { delete rsa_key; } + + std::string to_string() const + { + return PKCS8::PEM_encode(*rsa_key); + } + + std::string get_N() const { return bigint2str(get_bigint_N()); } + std::string get_E() const { return bigint2str(get_bigint_E()); } + + const BigInt& get_bigint_N() const { return rsa_key->get_n(); } + const BigInt& get_bigint_E() const { return rsa_key->get_e(); } + + std::string decrypt(const std::string& in, + const std::string& padding); + + std::string sign(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng); + private: + RSA_PrivateKey* rsa_key; + }; + +std::string Py_RSA_PrivateKey::decrypt(const std::string& in, + const std::string& padding) + { + std::auto_ptr<PK_Decryptor> enc(get_pk_decryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return secvec2str(enc->decrypt(in_bytes, in.size())); + } + +std::string Py_RSA_PrivateKey::sign(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng) + { + std::auto_ptr<PK_Signer> sign(get_pk_signer(*rsa_key, padding)); + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + sign->update(in_bytes, in.size()); + return secvec2str(sign->signature(rng.get_underlying_rng())); + } + +Py_RSA_PrivateKey::Py_RSA_PrivateKey(u32bit bits, + Python_RandomNumberGenerator& rng) + { + rsa_key = new RSA_PrivateKey(rng.get_underlying_rng(), bits); + } + +Py_RSA_PrivateKey::Py_RSA_PrivateKey(std::string pem_str, + Python_RandomNumberGenerator& rng, + std::string passphrase) + { + DataSource_Memory in(pem_str); + + Private_Key* pkcs8_key = + PKCS8::load_key(in, + rng.get_underlying_rng(), + passphrase); + + rsa_key = dynamic_cast<RSA_PrivateKey*>(pkcs8_key); + + if(!rsa_key) + throw std::invalid_argument("Key is not an RSA key"); + } + +class Py_RSA_PublicKey + { + public: + Py_RSA_PublicKey(std::string pem_str); + Py_RSA_PublicKey(const Py_RSA_PrivateKey&); + ~Py_RSA_PublicKey() { delete rsa_key; } + + std::string get_N() const { return bigint2str(get_bigint_N()); } + std::string get_E() const { return bigint2str(get_bigint_E()); } + + const BigInt& get_bigint_N() const { return rsa_key->get_n(); } + const BigInt& get_bigint_E() const { return rsa_key->get_e(); } + + std::string to_string() const + { + return X509::PEM_encode(*rsa_key); + } + + std::string encrypt(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng); + + bool verify(const std::string& in, + const std::string& padding, + const std::string& signature); + private: + RSA_PublicKey* rsa_key; + }; + +Py_RSA_PublicKey::Py_RSA_PublicKey(const Py_RSA_PrivateKey& priv) + { + rsa_key = new RSA_PublicKey(priv.get_bigint_N(), priv.get_bigint_E()); + } + +Py_RSA_PublicKey::Py_RSA_PublicKey(std::string pem_str) + { + DataSource_Memory in(pem_str); + Public_Key* x509_key = X509::load_key(in); + + rsa_key = dynamic_cast<RSA_PublicKey*>(x509_key); + + if(!rsa_key) + throw std::invalid_argument("Key is not an RSA key"); + } + +std::string Py_RSA_PublicKey::encrypt(const std::string& in, + const std::string& padding, + Python_RandomNumberGenerator& rng) + { + std::auto_ptr<PK_Encryptor> enc(get_pk_encryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + + return secvec2str(enc->encrypt(in_bytes, in.size(), + rng.get_underlying_rng())); + } + +bool Py_RSA_PublicKey::verify(const std::string& in, + const std::string& signature, + const std::string& padding) + { + std::auto_ptr<PK_Verifier> ver(get_pk_verifier(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast<const byte*>(in.data()); + const byte* sig_bytes = reinterpret_cast<const byte*>(signature.data()); + + ver->update(in_bytes, in.size()); + return ver->check_signature(sig_bytes, signature.size()); + } + +void export_rsa() + { + python::class_<Py_RSA_PublicKey> + ("RSA_PublicKey", python::init<std::string>()) + .def(python::init<const Py_RSA_PrivateKey&>()) + .def("to_string", &Py_RSA_PublicKey::to_string) + .def("encrypt", &Py_RSA_PublicKey::encrypt) + .def("verify", &Py_RSA_PublicKey::verify) + .def("get_N", &Py_RSA_PublicKey::get_N) + .def("get_E", &Py_RSA_PublicKey::get_E); + + python::class_<Py_RSA_PrivateKey> + ("RSA_PrivateKey", python::init<std::string, Python_RandomNumberGenerator&, std::string>()) + .def(python::init<u32bit, Python_RandomNumberGenerator&>()) + .def("to_string", &Py_RSA_PrivateKey::to_string) + .def("decrypt", &Py_RSA_PrivateKey::decrypt) + .def("sign", &Py_RSA_PrivateKey::sign) + .def("get_N", &Py_RSA_PrivateKey::get_N) + .def("get_E", &Py_RSA_PrivateKey::get_E); + } |