aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2009-10-09 22:28:02 +0000
committerlloyd <[email protected]>2009-10-09 22:28:02 +0000
commit9db719642349bc37126dee4b2837d3bba022d734 (patch)
treed77b7f94dbba6b7852da7c3e075bcd548b74caaf
parentd970d9feb203e497f72f1e9b4dc095b1d7ca308f (diff)
Reasonably functional RSA support; keygen, import/export, encrypt/decrypt, sign/verify
-rw-r--r--src/pubkey/rsa/rsa.h8
-rw-r--r--src/wrap/python/core.cpp30
-rw-r--r--src/wrap/python/pk.cpp125
-rw-r--r--src/wrap/python/python_botan.h30
-rw-r--r--src/wrap/python/rsa.cpp194
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);
+ }