diff --git a/autogen.sh b/autogen.sh index 22bf868..fab63b9 100755 --- a/autogen.sh +++ b/autogen.sh @@ -63,6 +63,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography. bindings/py/gencffi.pl include/pcp/defines.h include/pcp/structs.h include/pcp/key.h \ include/pcp/buffer.h include/pcp/context.h include/pcp/mac.h \ include/pcp/ed.h include/pcp/crypto.h include/pcp/vault.h \ + include/pcp/mgmt.h \ include/pcp/pcpstream.h include/pcp/z85.h > bindings/py/pypcp/raw.py exit diff --git a/bindings/py/pypcp/__init__.py b/bindings/py/pypcp/__init__.py index 8eea836..ea9d076 100644 --- a/bindings/py/pypcp/__init__.py +++ b/bindings/py/pypcp/__init__.py @@ -1,18 +1,83 @@ from cffi import FFI from pypcp.dll import * +from pprint import pprint -__all__ = ('raw Key'.split() ) +__all__ = ('raw Key PublicKey'.split() ) +# https://gist.github.com/inactivist/4ef7058c2132fa16759d + +class Context(object): + def __init__(self): + self._ctx = libpcp.ptx_new() + + def __del__(self): + libpcp.ptx_clean(self._ctx) + + def throw(self, E=None, msg=None): + # forward libpcp generated exceptions + pcpmsg = ffi.string(self._ctx.pcp_err) + if msg: + pcpmsg = "%s: %s" % (msg, pcpmsg) + if E: + raise E(pcpmsg) + else: + raise RuntimeError(pcpmsg) + +class PublicKey(object): + def __init__(self, pk=None, encoded=None): + self._pk = None + + if pk: + self._pk = pk + elif encoded: + self.importkey(Context(), encoded) + else: + self._pk = ffi.new("struct _pcp_pubkey_t*") + + for key, value in convert_to_python(self._pk).iteritems(): + self.__setattr__(key, value) + + def importkey(self, context, encoded=None): + ks = libpcp.pcp_import_pub(context._ctx, encoded, len(encoded)) + if not ks: + context.throw(IOError, "failed to import key") + self._pk = ks.p + + def dump(self): + if self._pk: + libpcp.pcp_dumppubkey(self._pk) + + def __dict__(self): + return convert_to_python(self._pk) class Key(object): - def __init__(self, owner=None, mail=None, sk=None): + def __init__(self, owner=None, mail=None, sk=None, encoded=None, passphrase=None): self._sk = None + if owner or mail: + # generate new one if not owner: owner='' if not mail: mail='' self.generate(owner, mail) + elif sk: + # use the raw sk + self._sk = sk + elif encoded: + # import an encoded key + self.importkey(Context(), encoded, passphrase) + else: + self._sk = ffi.new("struct pcp_key_t*") + + for key, value in convert_to_python(self._sk).iteritems(): + self.__setattr__(key, value) + + def importkey(self, context, encoded=None, passphrase=None): + sk = libpcp.pcp_import_secret(context._ctx, encoded, len(encoded), passphrase) + if not sk: + context.throw(IOError, "failed to import key") + self._sk = sk def generate(self, owner=None, mail=None): self._sk = libpcp.pcpkey_new() diff --git a/bindings/py/pypcp/dll.py b/bindings/py/pypcp/dll.py index 49169b4..b4d83d4 100644 --- a/bindings/py/pypcp/dll.py +++ b/bindings/py/pypcp/dll.py @@ -3,6 +3,32 @@ from static import * from cffi import FFI +# from: +# https://gist.github.com/inactivist/4ef7058c2132fa16759d +# with fixes + +def __convert_struct_field( s, fields ): + for field,fieldtype in fields: + if fieldtype.type.kind == 'primitive': + yield (field,getattr( s, field )) + else: + yield (field, convert_to_python( getattr( s, field ) )) + +def convert_to_python(s): + type=ffi.typeof(s) + if type.item.kind == 'struct': + return dict(__convert_struct_field( s, type.item.fields ) ) + elif type.kind == 'array': + if type.item.kind == 'primitive': + if type.item.cname == 'char': + return ffi.string(s) + else: + return [ s[i] for i in range(type.length) ] + else: + return [ convert_to_python(s[i]) for i in range(type.length) ] + elif type.kind == 'primitive': + return int(s) + ffi = FFI() libpcp = ffi.dlopen('libpcp1.so.0') diff --git a/bindings/py/pypcp/raw.py b/bindings/py/pypcp/raw.py index a6a2ede..0347c32 100644 --- a/bindings/py/pypcp/raw.py +++ b/bindings/py/pypcp/raw.py @@ -545,125 +545,173 @@ vault_item_header_t * ih2be(vault_item_header_t *h); /*** bindings/py/gencffi.pl: from include/pcp/vault.h:2453 */ vault_item_header_t * ih2native(vault_item_header_t *h); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +Buffer *pcp_export_rfc_pub (pcp_key_t *sk); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +Buffer *pcp_export_pbp_pub(pcp_key_t *sk); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +Buffer *pcp_export_yaml_pub(pcp_key_t *sk); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +Buffer *pcp_export_perl_pub(pcp_key_t *sk); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +Buffer *pcp_export_c_pub(pcp_key_t *sk); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +pcp_ks_bundle_t *pcp_import_binpub(PCPCTX *ptx, byte *raw, size_t rawsize); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +pcp_ks_bundle_t *pcp_import_pub(PCPCTX *ptx, byte *raw, size_t rawsize); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +pcp_key_t *pcp_import_secret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphrase); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t *sk); + +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader); + +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ Pcpstream *ps_init(void); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ Pcpstream *ps_new_file(FILE *backendfd); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ Pcpstream *ps_new_inbuffer(Buffer *b); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ Pcpstream *ps_new_outbuffer(); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_finish(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_print(Pcpstream *stream, const char * fmt, ...); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_tell(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ Buffer *ps_buffer(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ void ps_close(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ int ps_end(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ int ps_err(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ void ps_setdetermine(Pcpstream *stream, size_t blocksize); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ void ps_armor(Pcpstream *stream, size_t blocksize); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ void ps_unarmor(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_read_decode(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ void ps_determine(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_read_next(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ void ps_write_encode(Pcpstream *stream, Buffer *dst); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ size_t ps_write_buf(Pcpstream *stream, Buffer *z); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ int ps_left(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:2744 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3003 */ int ps_readline(Pcpstream *stream, Buffer *line); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ byte *pcp_padfour(byte *src, size_t srclen, size_t *dstlen); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ size_t pcp_unpadfour(byte *src, size_t srclen); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ byte *pcp_z85_decode(PCPCTX *ptx, char *z85block, size_t *dstlen); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ char *pcp_z85_encode(byte *raw, size_t srclen, size_t *dstlen, int doblock); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ char *pcp_readz85file(PCPCTX *ptx, FILE *infile); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ char *pcp_readz85string(PCPCTX *ptx, byte *input, size_t bufsize); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ uint8_t is_utf8(const byte * bytes); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ size_t _buffer_is_binary(byte *buf, size_t len); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ uint8_t _parse_zchar(Buffer *z, uint8_t c, uint8_t is_comment); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ long int z85_header_startswith(Buffer *buf, char *what); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ int z85_isheader(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ int z85_isend(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ int z85_isbegin(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ int z85_iscomment(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ int z85_isempty(Buffer *line); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:2922 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3181 */ int z85_isencoded(Buffer *line);''' diff --git a/bindings/py/test.py b/bindings/py/test.py index 285194f..cf763b5 100755 --- a/bindings/py/test.py +++ b/bindings/py/test.py @@ -1,7 +1,18 @@ #!/usr/local/bin/python from pypcp import * +from pprint import pprint sk = Key("tom", "me@there") sk.dump() +encoded = open("../../tests/key-bobby-sec", "r").read() + +sk = Key(encoded=encoded, passphrase="b") +sk.dump() + +p = open("../../tests/key-bobby-pub", "r").read() +pk = PublicKey(encoded=p) +pk.dump() + +pprint(pk.masterpub) diff --git a/include/pcp.h b/include/pcp.h index 45255d0..b9881a9 100644 --- a/include/pcp.h +++ b/include/pcp.h @@ -8,7 +8,6 @@ extern "C" { #include "pcp/config.h" #include "pcp/base85.h" #include "pcp/buffer.h" -#include "pcp/config.h" #include "pcp/context.h" #include "pcp/crypto.h" #include "pcp/defines.h"