From 997e6c97b8ace857d00f9fd57f621ba9323c75df Mon Sep 17 00:00:00 2001 From: lloyd Date: Fri, 9 Oct 2009 18:06:06 +0000 Subject: Add more or less functional integration with Boost.Python. Use --use-boost-python to enable creating a second makefile, Makefile.python, which has targets for building and installing the Python module. --- src/wrap/python/python_botan.h | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/wrap/python/python_botan.h (limited to 'src/wrap/python/python_botan.h') diff --git a/src/wrap/python/python_botan.h b/src/wrap/python/python_botan.h new file mode 100644 index 000000000..18c51dbb1 --- /dev/null +++ b/src/wrap/python/python_botan.h @@ -0,0 +1,51 @@ + +#ifndef BOTAN_BOOST_PYTHON_COMMON_H__ +#define BOTAN_BOOST_PYTHON_COMMON_H__ + +#include +#include +#include +using namespace Botan; + +#include +namespace python = boost::python; + +extern void export_filters(); +extern void export_pk(); +extern void export_x509(); + +class Bad_Size : public Exception + { + public: + Bad_Size(u32bit got, u32bit expected) : + Exception("Bad size detected in Python/C++ conversion layer: got " + + to_string(got) + " bytes, expected " + to_string(expected)) + {} + }; + +inline std::string make_string(const byte input[], u32bit length) + { + return std::string((const char*)input, length); + } + +inline std::string make_string(const MemoryRegion& in) + { + return make_string(in.begin(), in.size()); + } + +inline void string2binary(const std::string& from, byte to[], u32bit expected) + { + if(from.size() != expected) + throw Bad_Size(from.size(), expected); + std::memcpy(to, from.data(), expected); + } + +template +inline python::object get_owner(T* me) + { + return python::object( + python::handle<>( + python::borrowed(python::detail::wrapper_base_::get_owner(*me)))); + } + +#endif -- cgit v1.2.3 From 9db719642349bc37126dee4b2837d3bba022d734 Mon Sep 17 00:00:00 2001 From: lloyd Date: Fri, 9 Oct 2009 22:28:02 +0000 Subject: Reasonably functional RSA support; keygen, import/export, encrypt/decrypt, sign/verify --- src/pubkey/rsa/rsa.h | 8 +- src/wrap/python/core.cpp | 30 +------ src/wrap/python/pk.cpp | 125 -------------------------- src/wrap/python/python_botan.h | 30 ++++++- src/wrap/python/rsa.cpp | 194 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 231 insertions(+), 156 deletions(-) delete mode 100644 src/wrap/python/pk.cpp create mode 100644 src/wrap/python/rsa.cpp (limited to 'src/wrap/python/python_botan.h') 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 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(&s[0]), n); - return s; - } - - void add_entropy(const std::string& in) - { rng->add_entropy(reinterpret_cast(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 -#include -#include -#include -using namespace Botan; - -#include -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 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 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::def("public_key", load_public, - python::return_value_policy()); - */ - - python::class_ - ("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_, boost::noncopyable> - ("PK_Encrypting_Key", python::no_init); - - python::class_, boost::noncopyable> - ("Private_Key", python::no_init) - .def("private_key", encode_priv); - - python::class_, boost::noncopyable> - ("PK_Decrypting_Key", python::no_init); - - python::class_ > - ("RSA_PublicKey", python::no_init); - - python::class_ > - ("DSA_PublicKey", python::no_init); - - /* - python::class_ > - ("RSA_PrivateKey", python::init()); - */ - - /* - python::class_ - ("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", 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(&s[0]), n); + return s; + } + + void add_entropy(const std::string& in) + { rng->add_entropy(reinterpret_cast(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 +#include +#include +#include +using namespace Botan; + +#include "python_botan.h" +#include + +std::string bigint2str(const BigInt& n) + { + std::ostringstream out; + out << n; + return out.str(); + } + +std::string secvec2str(const MemoryRegion& 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 enc(get_pk_decryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast(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 sign(get_pk_signer(*rsa_key, padding)); + const byte* in_bytes = reinterpret_cast(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(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(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 enc(get_pk_encryptor(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast(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 ver(get_pk_verifier(*rsa_key, padding)); + + const byte* in_bytes = reinterpret_cast(in.data()); + const byte* sig_bytes = reinterpret_cast(signature.data()); + + ver->update(in_bytes, in.size()); + return ver->check_signature(sig_bytes, signature.size()); + } + +void export_rsa() + { + python::class_ + ("RSA_PublicKey", python::init()) + .def(python::init()) + .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_ + ("RSA_PrivateKey", python::init()) + .def(python::init()) + .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); + } -- cgit v1.2.3