diff options
author | lloyd <[email protected]> | 2008-09-17 22:42:36 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2008-09-17 22:42:36 +0000 |
commit | 2b6ad3a07e89e3c93425b1fffb78d4877299b414 (patch) | |
tree | cc7794b7dcecffe5b29d29a33f8f914a850a1663 | |
parent | e65adc861146a0d88064a3889ed2efa2bbd9133f (diff) |
Add an old attempt I made to wrap Botan using SWIG. Includes some tests
in Python. There are probably bugs and it may not even compile currently.
(Just cleaning out the old ~ today... everything goes into mtn or /dev/null)
-rw-r--r-- | misc/swig/Makefile | 32 | ||||
-rw-r--r-- | misc/swig/base.cpp | 61 | ||||
-rw-r--r-- | misc/swig/base.h | 102 | ||||
-rw-r--r-- | misc/swig/botan.swg | 26 | ||||
-rwxr-xr-x | misc/swig/doit.py | 49 | ||||
-rw-r--r-- | misc/swig/filter.cpp | 39 | ||||
-rw-r--r-- | misc/swig/pipe.cpp | 89 | ||||
-rw-r--r-- | misc/swig/pk.swg | 8 | ||||
-rw-r--r-- | misc/swig/readme.txt | 34 | ||||
-rw-r--r-- | misc/swig/tests/block.py | 52 | ||||
-rw-r--r-- | misc/swig/tests/block2.py | 44 | ||||
-rw-r--r-- | misc/swig/tests/encrypt.py | 37 | ||||
-rw-r--r-- | misc/swig/tests/filter.py | 27 | ||||
-rw-r--r-- | misc/swig/tests/hash.py | 30 | ||||
-rw-r--r-- | misc/swig/tests/mac.py | 12 | ||||
-rw-r--r-- | misc/swig/tests/pubkey.py | 10 | ||||
-rw-r--r-- | misc/swig/tests/stream.py | 17 | ||||
-rw-r--r-- | misc/swig/x509.swg | 9 |
18 files changed, 678 insertions, 0 deletions
diff --git a/misc/swig/Makefile b/misc/swig/Makefile new file mode 100644 index 000000000..ff55c793c --- /dev/null +++ b/misc/swig/Makefile @@ -0,0 +1,32 @@ +LANG=-python +LANG_INC=/usr/include/python2.3 + +CFLAGS=$(shell botan-config --cflags) +LIBS=$(shell botan-config --libs) + +CXX = g++ -g +SWIG = swig -Wall + +all: _botan.so + +_botan.so: base.o pipe.o filter.o botan_wrap.o + $(CXX) -shared $^ $(LIBS) -o $@ + +botan_wrap.cpp: botan.swg base.h + $(SWIG) $(LANG) -c++ -o $@ $< + +botan_wrap.o: botan_wrap.cpp + $(CXX) $(CFLAGS) -I$(LANG_INC) -c $^ -o $@ + +base.o: base.cpp base.h + $(CXX) $(CFLAGS) -c $< -o $@ + +pipe.o: pipe.cpp base.h + $(CXX) $(CFLAGS) -c $< -o $@ + +filter.o: filter.cpp base.h + $(CXX) $(CFLAGS) -c $< -o $@ + +clean: + rm -f *.o _botan.so botan.py botan.pyc + rm -f *_wrap.o *_wrap.cpp diff --git a/misc/swig/base.cpp b/misc/swig/base.cpp new file mode 100644 index 000000000..2550b915b --- /dev/null +++ b/misc/swig/base.cpp @@ -0,0 +1,61 @@ +/************************************************* +* SWIG Interface for basic Botan interface * +* (C) 1999-2003 The Botan Project * +*************************************************/ + +#include "base.h" +#include <botan/init.h> + +#include <stdio.h> + +/************************************************* +* Initialize the library * +*************************************************/ +LibraryInitializer::LibraryInitializer(const char* args) + { + Botan::Init::initialize(args); + } + +/************************************************* +* Shut down the library * +*************************************************/ +LibraryInitializer::~LibraryInitializer() + { + Botan::Init::deinitialize(); + } + +/************************************************* +* Create a SymmetricKey * +*************************************************/ +SymmetricKey::SymmetricKey(const std::string& str) + { + key = new Botan::SymmetricKey(str); + printf("STR CON: %p %p\n", this, key); + } + +/************************************************* +* Create a SymmetricKey * +*************************************************/ +SymmetricKey::SymmetricKey(u32bit n) + { + key = new Botan::SymmetricKey(n); + printf("N CON: %p %p\n", this, key); + } + +/************************************************* +* Destroy a SymmetricKey * +*************************************************/ +SymmetricKey::~SymmetricKey() + { + printf("DESTR: %p %p\n", this, key); + delete key; + key = 0; + //printf("deleted\n"); + } + +/************************************************* +* Create an InitializationVector * +*************************************************/ +InitializationVector::InitializationVector(const std::string& str) : iv(str) + { + } diff --git a/misc/swig/base.h b/misc/swig/base.h new file mode 100644 index 000000000..c3fd8426e --- /dev/null +++ b/misc/swig/base.h @@ -0,0 +1,102 @@ +/************************************************* +* SWIG Interface for Botan * +* (C) 1999-2003 The Botan Project * +*************************************************/ + +#ifndef BOTAN_WRAP_BASE_H__ +#define BOTAN_WRAP_BASE_H__ + +#include <botan/pipe.h> + +#if !defined(SWIG) + #define OUTPUT + #define INOUT +#endif + +/************************************************* +* Typedefs * +*************************************************/ +typedef unsigned char byte; +typedef unsigned int u32bit; + +/************************************************* +* Library Initalization/Shutdown Object * +*************************************************/ +class LibraryInitializer + { + public: + LibraryInitializer(const char*); + ~LibraryInitializer(); + }; + +/************************************************* +* Symmetric Key Object * +*************************************************/ +class SymmetricKey + { + public: + std::string as_string() const { return key->as_string(); } + u32bit length() const { return key->length(); } + SymmetricKey(u32bit = 0); + SymmetricKey(const std::string&); + ~SymmetricKey(); + private: + Botan::SymmetricKey* key; + }; + +/************************************************* +* Initialization Vector Object * +*************************************************/ +class InitializationVector + { + public: + std::string as_string() const { return iv.as_string(); } + u32bit length() const { return iv.length(); } + InitializationVector(u32bit n = 0) { iv.change(n); } + InitializationVector(const std::string&); + private: + Botan::InitializationVector iv; + }; + +/************************************************* +* Filter Object * +*************************************************/ +class Filter + { + public: + Filter(const char*); + //Filter(const char*, const SymmetricKey&); + //Filter(const char*, const SymmetricKey&, const InitializationVector&); + ~Filter(); + private: + friend class Pipe; + Botan::Filter* filter; + bool pipe_owns; + }; + +/************************************************* +* Pipe Object * +*************************************************/ +class Pipe + { + public: + static const u32bit DEFAULT_MESSAGE = 0xFFFFFFFF; + + void write_file(const char*); + void write_string(const char*); + + u32bit read(byte*, u32bit, u32bit = DEFAULT_MESSAGE); + std::string read_all_as_string(u32bit = DEFAULT_MESSAGE); + + u32bit remaining(u32bit = DEFAULT_MESSAGE); + + void start_msg(); + void end_msg(); + + Pipe(Filter* = 0, Filter* = 0, Filter* = 0, Filter* = 0); + ~Pipe(); + private: + Botan::Pipe* pipe; + }; + +#endif diff --git a/misc/swig/botan.swg b/misc/swig/botan.swg new file mode 100644 index 000000000..9088f4272 --- /dev/null +++ b/misc/swig/botan.swg @@ -0,0 +1,26 @@ +/************************************************* +* SWIG Interface for Botan * +*************************************************/ +%module botan + +%include "typemaps.i" +%include "std_string.i" +%include "exception.i" +%include "constraints.i" +%include "carrays.i" + +%{ +#include "base.h" +%} + +%exception { + try { + $action + } + catch(std::exception& e) + { + SWIG_exception(SWIG_RuntimeError, e.what()); + } +} + +%include "base.h" diff --git a/misc/swig/doit.py b/misc/swig/doit.py new file mode 100755 index 000000000..98bc97087 --- /dev/null +++ b/misc/swig/doit.py @@ -0,0 +1,49 @@ +#!/usr/bin/python2 + +import botan + +def hash_it(hash, input): + f1 = botan.Filter("MD5") + f2 = botan.Filter("Hex_Encoder") + pipe = botan.Pipe(f1, f2) + + pipe.start_msg() + pipe.write_string(input) + pipe.end_msg() + + print pipe.remaining() + + out = pipe.read(0) + + + + +def main: + init = botan.LibraryInitializer + + print hash_it("MD5", "foo") + + + key1 = botan.SymmetricKey("ABCD") + print key1.as_string() + key2 = botan.SymmetricKey(16) + print key2.as_string() + + iv1 = botan.InitializationVector(8) + print iv1.as_string() + + + f3 = pipe.read(pipe.remaining()) + + size = pipe.remaining() + out = botan.byte_array(size) + pipe.read(out.cast,size) + + for i in range (0,size): + print "%02X" % out[i] + + print pipe.read_all_as_string() + +if __name__ == "__main__": + sys.exit(main()) + diff --git a/misc/swig/filter.cpp b/misc/swig/filter.cpp new file mode 100644 index 000000000..ec9ce6603 --- /dev/null +++ b/misc/swig/filter.cpp @@ -0,0 +1,39 @@ +/************************************************* +* SWIG Interface for Filter Retrieval * +* (C) 1999-2003 The Botan Project * +*************************************************/ + +#include "base.h" +#include <botan/lookup.h> +#include <botan/filters.h> + +/************************************************* +* Filter Creation * +*************************************************/ +Filter::Filter(const char* filt_string) + { + filter = 0; + pipe_owns = false; + + /* + Fixme: This is all so totally wrong. It needs to have full argument + processing for everything, all that kind of crap. + */ + const std::string filt_name = filt_string; + + if(Botan::have_hash(filt_name)) + filter = new Botan::Hash_Filter(filt_name); + else if(filt_name == "Hex_Encoder") + filter = new Botan::Hex_Encoder; + } + +/************************************************* +* Filter Destruction * +*************************************************/ +Filter::~Filter() + { + /* + if(!pipe_owns) + delete filter; + */ + } diff --git a/misc/swig/pipe.cpp b/misc/swig/pipe.cpp new file mode 100644 index 000000000..2ccdd5dfd --- /dev/null +++ b/misc/swig/pipe.cpp @@ -0,0 +1,89 @@ +/************************************************* +* SWIG Interface for Botan Pipe API * +* (C) 1999-2003 The Botan Project * +*************************************************/ + +#include "base.h" +#include <botan/pipe.h> + +#include <stdio.h> + +/************************************************* +* Write the contents of a file into a Pipe * +*************************************************/ +void Pipe::write_file(const char* filename) + { + Botan::DataSource_Stream in(filename); + pipe->write(in); + } + +/************************************************* +* Write the contents of a string into a Pipe * +*************************************************/ +void Pipe::write_string(const char* string) + { + pipe->write(string); + } + +/************************************************* +* Read the contents of a Pipe into a buffer * +*************************************************/ +u32bit Pipe::read(byte* buf, u32bit length, u32bit msg) + { + printf("read %p %d\n", buf, length); + return 0; + //return pipe->read(buf, length, msg); + } + +/************************************************* +* Read the contents of a Pipe as a string * +*************************************************/ +std::string Pipe::read_all_as_string(u32bit msg) + { + return pipe->read_all_as_string(msg); + } + +/************************************************* +* Find out how much stuff the Pipe still has * +*************************************************/ +u32bit Pipe::remaining(u32bit msg) + { + return pipe->remaining(); + } + +/************************************************* +* Start a new message * +*************************************************/ +void Pipe::start_msg() + { + pipe->start_msg(); + } + +/************************************************* +* End the current msessage * +*************************************************/ +void Pipe::end_msg() + { + pipe->end_msg(); + } + +/************************************************* +* Create a new Pipe * +*************************************************/ +Pipe::Pipe(Filter* f1, Filter* f2, Filter* f3, Filter* f4) + { + pipe = new Botan::Pipe(); + + if(f1) { pipe->append(f1->filter); f1->pipe_owns = true; } + if(f2) { pipe->append(f2->filter); f2->pipe_owns = true; } + if(f3) { pipe->append(f3->filter); f3->pipe_owns = true; } + if(f4) { pipe->append(f4->filter); f4->pipe_owns = true; } + } + +/************************************************* +* Destroy this Pipe * +*************************************************/ +Pipe::~Pipe() + { + delete pipe; + } diff --git a/misc/swig/pk.swg b/misc/swig/pk.swg new file mode 100644 index 000000000..8e03cf120 --- /dev/null +++ b/misc/swig/pk.swg @@ -0,0 +1,8 @@ +%module botan + +%{ +#undef ANY +#include "botan/pubkey.h" +%} + +%include "botan/pubkey.h" diff --git a/misc/swig/readme.txt b/misc/swig/readme.txt new file mode 100644 index 000000000..a9965d914 --- /dev/null +++ b/misc/swig/readme.txt @@ -0,0 +1,34 @@ +This is the beginning of an attempt to SWIG-ify Botan so it can be accessed by +other languages. You should use the latest SWIG 1.3 release (I am currently +using SWIG 1.3.19). Currently I am only testing this code with Python 2.2.1, +since that is the language I am mainly interested in at this point. Feel free +to send me patches so this is usable with Perl or whatever. + +I'm not attempting to make everything in Botan usable from a script - +basically, I just want the parts that *I* want to use. Most things are not +supported yet, and there are lots of bugs in the stuff that does exist. If +there is something in particular that you would like to be able to use from a +script, let me know (patches are good, too). + +Todo: + * Why does it seg fault if we don't create a LibraryInitializer. It should + throw an exception, like it does in C++. Maybe have it init Botan when the + module is loaded? That seems a lot cleaner/nicer, but I don't know how to + do it yet. + * Lots of problems with exceptions + * Use constraints to prevent bad args when possible + * Pipe/Filter + - Better argument processing for all filters + - Support for ciphers, MACs, etc + - Chain + Fork + - Support for append/prepend/pop/reset in Pipe? + * Public Key Crypto + - RSA + - DSA + - DH + - Generic X.509 and PKCS #8 stuff + * PKI + - X.509 certs + CRLs + - PKCS #10 requests + - X.509 stores + - X.509 CA diff --git a/misc/swig/tests/block.py b/misc/swig/tests/block.py new file mode 100644 index 000000000..593937c81 --- /dev/null +++ b/misc/swig/tests/block.py @@ -0,0 +1,52 @@ +#!/usr/bin/python + +import botan, base64 + +class MyCipher(botan.BlockCipher): + def __init__(self): + botan.BlockCipher.__init__(self, 16, 16, 32, 8) + def encrypt(self, val): + print "encrypt", val + return val.swapcase() + def decrypt(self, val): + print "decrypt", val + return val.swapcase() + def set_key(self, key): + print "set_key", key + def clone(self): + print "cloning" + return MyCipher() + def name(self): + print "naming" + return "MyCipher" + +cipher = botan.BlockCipher("AES-128") + +print cipher.block_size +print cipher.keylength_min +print cipher.keylength_max +print cipher.keylength_mod +print cipher.name() + +for kl in range(1, 128): + if cipher.valid_keylength(kl): + print "1", + else: + print "0", +print +key = botan.SymmetricKey(16) + +cipher.set_key(key) +ciphertext = cipher.encrypt("ABCDEFGH12345678") +print base64.b16encode(ciphertext) + +cipher2 = cipher.clone() +cipher2.set_key(key) + +plaintext = cipher2.decrypt(ciphertext) +print plaintext + +botan.get_info(cipher) + +mycipher = MyCipher() +botan.get_info(mycipher) diff --git a/misc/swig/tests/block2.py b/misc/swig/tests/block2.py new file mode 100644 index 000000000..5faccaf9a --- /dev/null +++ b/misc/swig/tests/block2.py @@ -0,0 +1,44 @@ +#!/usr/bin/python + +import botan, base64 + +class MyCipher(botan.BlockCipherImpl): + def __init__(self): + botan.BlockCipherImpl.__init__(self, 8, 8, 16, 1) + + def name(self): + return "MyCipher" + + def encrypt(self, input): + return input.swapcase() + + def decrypt(self, input): + return input.swapcase() + + def set_key(self, key): + print "Got key",key + +def test(cipher): + print + print cipher + print "Testing", cipher.name() + print cipher.block_size + print cipher.keylength_min, cipher.keylength_max, cipher.keylength_mod + for i in range(1, 64): + if cipher.valid_keylength(i): + print "1", + else: + print "0", + print + cipher.set_key(botan.SymmetricKey(16)) + ciphertext = cipher.encrypt("aBcDeFgH" * (cipher.block_size / 8)) + print repr(ciphertext) + print cipher.decrypt(ciphertext) + +def main(): + test(botan.BlockCipher("Blowfish")) + test(MyCipher()) + test(botan.BlockCipher("AES")) + +if __name__ == "__main__": + main() diff --git a/misc/swig/tests/encrypt.py b/misc/swig/tests/encrypt.py new file mode 100644 index 000000000..9896777d4 --- /dev/null +++ b/misc/swig/tests/encrypt.py @@ -0,0 +1,37 @@ +#!/usr/bin/python + +import sys, botan + +def encrypt(input): + cipher_key = botan.SymmetricKey("AABB") + print cipher_key.length + cipher_key = botan.SymmetricKey("AABBCCDD") + print cipher_key.length + + cipher = botan.Filter("ARC4", key = cipher_key) + + pipe = botan.Pipe(cipher, botan.Filter("Hex_Encoder")) + + pipe.start_msg() + pipe.write(input) + pipe.end_msg() + + str = pipe.read_all() + print str + return str + +def decrypt(input): + pipe = botan.Pipe(botan.Filter("Hex_Decoder"), + botan.Filter("ARC4", + key = botan.SymmetricKey("AABBCCDD"))) + + pipe.process_msg(input) + return pipe.read_all() + +def main(): + ciphertext = encrypt("hi chappy") + print ciphertext + print decrypt(ciphertext) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/misc/swig/tests/filter.py b/misc/swig/tests/filter.py new file mode 100644 index 000000000..2b65d9ff2 --- /dev/null +++ b/misc/swig/tests/filter.py @@ -0,0 +1,27 @@ +#!/usr/bin/python + +import sys, botan + +class MyFilter(botan.FilterObj): + def write(self, input): + print "MyFilter::write",input + self.send(input) + def start_msg(self): + print "MyFilter::start_msg" + def end_msg(self): + print "MyFilter::end_msg" + def __del__(self): + print "~MyFilter" + +def main(): + filter = MyFilter() + + pipe = botan.Pipe(botan.Filter("Hex_Encoder"), filter, + botan.Filter("Hex_Decoder")) + pipe.start_msg() + pipe.write("hi chappy") + pipe.end_msg() + print pipe.read_all() + +if __name__ == "__main__": + sys.exit(main()) diff --git a/misc/swig/tests/hash.py b/misc/swig/tests/hash.py new file mode 100644 index 000000000..930b8c81a --- /dev/null +++ b/misc/swig/tests/hash.py @@ -0,0 +1,30 @@ +#!/usr/bin/python + +import botan, base64, md5 + +class PyMD5(botan.HashFunctionImpl): + def name(self): + return "PyMD5" + def update(self, input): + self.md5.update(input) + def final(self): + output = self.md5.digest() + self.md5 = md5.new() + return output + def __init__(self): + botan.HashFunctionImpl.__init__(self, 16, 64) + self.md5 = md5.new() + +hash = botan.HashFunction("SHA-256") + +print hash.name() +print hash.digest_size + +hash.update("hi") +hash.update(" ") +hash.update("chappy") +print base64.b16encode(hash.final()) + +hash2 = PyMD5() +hash2.update("hi chappy") +print base64.b16encode(hash2.final()) diff --git a/misc/swig/tests/mac.py b/misc/swig/tests/mac.py new file mode 100644 index 000000000..6110b6102 --- /dev/null +++ b/misc/swig/tests/mac.py @@ -0,0 +1,12 @@ +#!/usr/bin/python + +import botan, base64 + +mac = botan.MAC("HMAC(SHA-512)") + +print mac.name +print mac.output_length + +mac.set_key(botan.SymmetricKey("abcd")) +mac.update("hi chappy") +print base64.b16encode(mac.final()) diff --git a/misc/swig/tests/pubkey.py b/misc/swig/tests/pubkey.py new file mode 100644 index 000000000..456c52069 --- /dev/null +++ b/misc/swig/tests/pubkey.py @@ -0,0 +1,10 @@ +#!/usr/bin/python + +import botan + +key = botan.X509_PublicKey("rsapub.pem") +print key +print key.key_id() +print key.max_input_bits +print key.algo +print key.oid diff --git a/misc/swig/tests/stream.py b/misc/swig/tests/stream.py new file mode 100644 index 000000000..59d3ffa16 --- /dev/null +++ b/misc/swig/tests/stream.py @@ -0,0 +1,17 @@ +#!/usr/bin/python + +import botan, base64 + +cipher = botan.StreamCipher("ARC4") + +print cipher.name + +key = botan.SymmetricKey(16) + +cipher.set_key(key) +ciphertext = cipher.crypt("hi chappy") + +cipher.set_key(key) +plaintext = cipher.crypt(ciphertext) + +print plaintext diff --git a/misc/swig/x509.swg b/misc/swig/x509.swg new file mode 100644 index 000000000..736d3a385 --- /dev/null +++ b/misc/swig/x509.swg @@ -0,0 +1,9 @@ +%module botan + +class X509_Certificate + { + public: + + + private: + }; |