From 5f8d50ec470bb96adcb2340b3c8529145b74ac4f Mon Sep 17 00:00:00 2001 From: "git@daemon.de" Date: Wed, 24 Dec 2014 11:17:03 +0100 Subject: [PATCH] py: added doc, unittests, anonymous encryption mode --- bindings/py/gencffi.pl | 1 - bindings/py/pypcp/__init__.py | 1 + bindings/py/pypcp/context.py | 129 ++++++++++++++++++++++-- bindings/py/pypcp/dll.py | 30 +++++- bindings/py/pypcp/key.py | 43 ++++++++ bindings/py/pypcp/publickey.py | 36 +++++++ bindings/py/pypcp/raw.py | 134 ++++++++++++------------- bindings/py/pypcp/stream.py | 27 +++++ tests/Makefile.am | 13 ++- bindings/py/test.py => tests/pytest.py | 0 tests/pyunittests.cfg | 58 +++++++++++ 11 files changed, 394 insertions(+), 78 deletions(-) rename bindings/py/test.py => tests/pytest.py (100%) create mode 100644 tests/pyunittests.cfg diff --git a/bindings/py/gencffi.pl b/bindings/py/gencffi.pl index 8d5d022..a1cf0a8 100755 --- a/bindings/py/gencffi.pl +++ b/bindings/py/gencffi.pl @@ -68,7 +68,6 @@ foreach my $head (@ARGV) { my ($name, $def) = split /\s\s*/, $1, 2; $def =~ s/\/\*.*//; if (!exists $defs{$name} && $def !~ /(sizeof| \+ )/) { - print STDERR "name: $name\ndef: $def\n\n"; $defs{$name} = "\n# $0: from $head:$.\n$name = $def\n"; } } diff --git a/bindings/py/pypcp/__init__.py b/bindings/py/pypcp/__init__.py index bc64e87..6498b92 100644 --- a/bindings/py/pypcp/__init__.py +++ b/bindings/py/pypcp/__init__.py @@ -14,3 +14,4 @@ __all__ = ('raw Context Key PublicKey Stream Buffer'.split() ) + diff --git a/bindings/py/pypcp/context.py b/bindings/py/pypcp/context.py index 26edfac..1fc1cf6 100644 --- a/bindings/py/pypcp/context.py +++ b/bindings/py/pypcp/context.py @@ -1,44 +1,144 @@ +# +# This file is part of Pretty Curved Privacy (pcp1). +# +# Copyright (C) 2013-2015 T. von Dein. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# You can contact me by mail: . +# + from pypcp.dll import * from pypcp.stream import * class Context(object): + """ + A libpcp context object, required for all operations. + """ def __init__(self): + """ + Create a new instance: + + >>> ctx = Context() + """ self._ctx = libpcp.ptx_new() self._sk = None def __del__(self): + """ + Destructor, automatically called + """ libpcp.ptx_clean(self._ctx) def throw(self, E=None, msg=None): + """ + Used internally to propagate libpcp errors. + + Throw libpcp error: + >>> ctx.throw(IOError, "additional message") + + Throw pure python exception: + >>> ctx.throw(None, "pypcp error") + """ # forward libpcp generated exceptions - pcpmsg = ffi.string(self._ctx.pcp_err) - if msg: - pcpmsg = "%s: %s" % (msg, pcpmsg) + pcpmsg = '' + + if self._ctx.pcp_errset == 1: + pcpmsg = ffi.string(self._ctx.pcp_err) + if E: + if msg: + pcpmsg = "%s: %s" % (msg, pcpmsg) raise E(pcpmsg) else: - raise RuntimeError(pcpmsg) + raise RuntimeError(msg) def addkey(self, Key): + """ + Add a secret key to the contect. Required for encryption + and signing operations. If you don't add a secret key to + the context, anonymous encryption will be done. + + >>> key = Key(owner="alicia") + >>> ctx.addkey(key) + """ self._sk = Key._sk def pubkeycount(self): + """ + Return the number of public keys known. + """ return libpcp.pcphash_countpub(self._ctx) def recipients(self, *recipients): + """ + Add one or more public keys. Required for encryption + and signing operations. + + >>> keyfile = open("bobby.pub", "r") + >>> bobby = PublicKey(encoded=keyfile).read() + >>> ctx.recipients(bobby) + """ for key in recipients: libpcp.pcphash_add(self._ctx, key._pk, key._pk.type) def encrypt(self, source=None, sign=False, passphrase=None, armor=False): + """ + Encrypt a file or a string. + + Args: + - 'source' can be a file handle (returned by open()) + or a python string containing the data to be encrypted + - 'sign': if set to True, append a signature to encrypted output + - 'passphrase': If set, do symmetric encryption (self mode) + - 'armor': if set to True, encode the output using Z85 + + Returns: + returns the encrypted result. + + Encrypt asymmetrically: + >>> seca = Key(encoded=alicesec, 'a') # import keys + >>> secb = Key(encoded=bobsec, 'b') + >>> puba = PublicKey(encoded=alicepub) + >>> pubb = PublicKey(encoded=bobpub) + >>> + >>> ctxA = Context() # 2 contexts, one for sender, one for recipient + >>> ctxA.addkey(seca) + >>> ctxA.recipients(pubb) + >>> ctxB = Context() + >>> ctxB.addkey(secb) + >>> ctxB.recipients(puba) + >>> + >>> encrypted = ctxA.encrypt(source='hello world') # encrypt alice => bob + >>> decrypted = ctxB.decrypt(source=encrypted) # decrypt bob <= alice + + Encrypt symmetrically: + >>> ctx = Context() + >>> encrypted = ctx.encrypt(source='hello world', passphrase='x') + >>> decrypted = ctx.decrypt(source=encrypted, passphrase='x') + + """ anon = 0 dosign = 0 instream = None outstream = None + sk = self._sk if source: instream = Stream(source) else: - self.throw(RuntimeError, "source argument required") + self.throw(None, "source argument required") outstream = Stream() @@ -53,12 +153,13 @@ class Context(object): if not self._sk: # no secret key known, anonymous mode anon = 1 + sk = libpcp.pcpkey_new() if sign: dosign = 1 size = libpcp.pcp_encrypt_stream(self._ctx, instream._stream, outstream._stream, - self._sk, self._ctx.pcppubkey_hash, dosign, anon) + sk, self._ctx.pcppubkey_hash, dosign, anon) if size <= 0: self.throw(IOError, "failed to encrypt") @@ -85,6 +186,20 @@ class Context(object): def decrypt(self, source=None, verify=False, passphrase=None): + """ + Decrypt a file or string + + Args: + - 'source' can be a file handle (returned by open()) + or a python string containing the data to be encrypted + - 'verify': if set to True, verify a signature, if present + - 'passphrase': If set, do symmetric encryption (self mode) + + Returns: + returns the decrypted result. + + For usage example see encrypt(). + """ doverify = 0 doanon = 0 instream = None @@ -120,7 +235,7 @@ class Context(object): else: # asymmetric if not self._sk: - self.throw(RuntimeError, "no secret key associated with current context") + self.throw(None, "no secret key associated with current context") if head[0] == PCP_ASYM_CIPHER_ANON: doanon = 1 diff --git a/bindings/py/pypcp/dll.py b/bindings/py/pypcp/dll.py index b4d83d4..a92801e 100644 --- a/bindings/py/pypcp/dll.py +++ b/bindings/py/pypcp/dll.py @@ -1,3 +1,25 @@ +# +# This file is part of Pretty Curved Privacy (pcp1). +# +# Copyright (C) 2013-2015 T. von Dein. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# You can contact me by mail: . +# + +import os from raw import * from static import * @@ -30,7 +52,13 @@ def convert_to_python(s): return int(s) ffi = FFI() +libso = '' -libpcp = ffi.dlopen('libpcp1.so.0') +if 'PCPCP_MAKE_TEST' in os.environ: + libso = "../libpcp/.libs/libpcp1.so.0" +else: + libso = "libpcp1.so.0" + +libpcp = ffi.dlopen(libso) ffi.cdef("%s\n%s\n" % (STATIC, PCP_RAW_CODE)) diff --git a/bindings/py/pypcp/key.py b/bindings/py/pypcp/key.py index fce0cc5..02e506b 100644 --- a/bindings/py/pypcp/key.py +++ b/bindings/py/pypcp/key.py @@ -1,8 +1,42 @@ +# +# This file is part of Pretty Curved Privacy (pcp1). +# +# Copyright (C) 2013-2015 T. von Dein. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# You can contact me by mail: . +# from pypcp.dll import * from pypcp.context import * class Key(object): + """ + A libpcp secret key object. + """ def __init__(self, owner=None, mail=None, sk=None, encoded=None, passphrase=None): + """ + Create a new secret key or import one. + + If 'owner' or 'mail' are set, a new secret key will be generated. + + If 'encoded' is provided, a key will be imported, 'encoded' can be a file + handle (returned by open()) or a python string. If the key is encrypted, + you need to supply 'passphrase' as well. + + Without arguments an empty key object will be used. Don't do that. + """ self._sk = None if owner or mail: @@ -26,16 +60,25 @@ class Key(object): self.__setattr__(key, value) def importkey(self, context, encoded=None, passphrase=None): + """ + Internal method to import a key from the outside. + """ 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): + """ + Internal method to generate a new secret key. + """ self._sk = libpcp.pcpkey_new() if owner: libpcp.pcpkey_setowner(self._sk, owner, mail) def dump(self): + """ + Dump the contents of the key to STDERR. + """ if self._sk: libpcp.pcp_dumpkey(self._sk) diff --git a/bindings/py/pypcp/publickey.py b/bindings/py/pypcp/publickey.py index cc7c50f..49aabe7 100644 --- a/bindings/py/pypcp/publickey.py +++ b/bindings/py/pypcp/publickey.py @@ -1,8 +1,38 @@ +# +# This file is part of Pretty Curved Privacy (pcp1). +# +# Copyright (C) 2013-2015 T. von Dein. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# You can contact me by mail: . +# + from pypcp.dll import * from pypcp.context import * class PublicKey(object): + """ + A libpcp public key object. + """ def __init__(self, pk=None, encoded=None): + """ + Import a public key. + + 'encoded' can be a file handle (returned by open()) or a python string + containing the public key. + """ self._pk = None if pk: @@ -16,12 +46,18 @@ class PublicKey(object): self.__setattr__(key, value) def importkey(self, context, encoded=None): + """ + Internal method to import a key from the outside. + """ 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): + """ + Dump the contents of the key to STDERR. + """ if self._pk: libpcp.pcp_dumppubkey(self._pk) diff --git a/bindings/py/pypcp/raw.py b/bindings/py/pypcp/raw.py index 2c00faa..80a1c3a 100644 --- a/bindings/py/pypcp/raw.py +++ b/bindings/py/pypcp/raw.py @@ -545,205 +545,205 @@ 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/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ Buffer *pcp_export_rfc_pub (pcp_key_t *sk); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ Buffer *pcp_export_pbp_pub(pcp_key_t *sk); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ Buffer *pcp_export_yaml_pub(pcp_key_t *sk); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ Buffer *pcp_export_perl_pub(pcp_key_t *sk); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ Buffer *pcp_export_c_pub(pcp_key_t *sk); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ pcp_ks_bundle_t *pcp_import_binpub(PCPCTX *ptx, byte *raw, size_t rawsize); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ pcp_ks_bundle_t *pcp_import_pub(PCPCTX *ptx, byte *raw, size_t rawsize); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ 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 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ 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 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphrase); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h); -/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2712 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ 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 */ +/*** bindings/py/gencffi.pl: from include/pcp/mgmt.h:2728 */ int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ void pcphash_del(PCPCTX *ptx, void *key, int type); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ void pcphash_clean(PCPCTX *ptx); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ void pcphash_cleanpub(pcp_pubkey_t *pub); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ pcp_key_t *pcphash_keyexists(PCPCTX *ptx, char *id); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ pcp_pubkey_t *pcphash_pubkeyexists(PCPCTX *ptx, char *id); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ void pcphash_add(PCPCTX *ptx, void *key, int type); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ int pcphash_count(PCPCTX *ptx); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ int pcphash_countpub(PCPCTX *ptx); -/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2865 */ +/*** bindings/py/gencffi.pl: from include/pcp/keyhash.h:2881 */ pcp_keysig_t *pcphash_keysigexists(PCPCTX *ptx, char *id); -/*** bindings/py/gencffi.pl: from include/pcp/scrypt.h:2908 */ +/*** bindings/py/gencffi.pl: from include/pcp/scrypt.h:2924 */ byte * pcp_scrypt(PCPCTX *ptx, char *passwd, size_t passwdlen, byte *nonce, size_t noncelen); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ Pcpstream *ps_init(void); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ Pcpstream *ps_new_file(FILE *backendfd); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ Pcpstream *ps_new_inbuffer(Buffer *b); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ Pcpstream *ps_new_outbuffer(); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_finish(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_print(Pcpstream *stream, const char * fmt, ...); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_tell(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ Buffer *ps_buffer(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ void ps_close(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ int ps_end(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ int ps_err(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ void ps_setdetermine(Pcpstream *stream, size_t blocksize); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ void ps_armor(Pcpstream *stream, size_t blocksize); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ void ps_unarmor(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_read_decode(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ void ps_determine(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_read_next(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ void ps_write_encode(Pcpstream *stream, Buffer *dst); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ size_t ps_write_buf(Pcpstream *stream, Buffer *z); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ int ps_left(Pcpstream *stream); -/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3199 */ +/*** bindings/py/gencffi.pl: from include/pcp/pcpstream.h:3215 */ int ps_readline(Pcpstream *stream, Buffer *line); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ byte *pcp_padfour(byte *src, size_t srclen, size_t *dstlen); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ size_t pcp_unpadfour(byte *src, size_t srclen); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ byte *pcp_z85_decode(PCPCTX *ptx, char *z85block, size_t *dstlen); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ char *pcp_z85_encode(byte *raw, size_t srclen, size_t *dstlen, int doblock); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ char *pcp_readz85file(PCPCTX *ptx, FILE *infile); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ char *pcp_readz85string(PCPCTX *ptx, byte *input, size_t bufsize); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ uint8_t is_utf8(const byte * bytes); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ size_t _buffer_is_binary(byte *buf, size_t len); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ uint8_t _parse_zchar(Buffer *z, uint8_t c, uint8_t is_comment); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ long int z85_header_startswith(Buffer *buf, char *what); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ int z85_isheader(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ int z85_isend(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ int z85_isbegin(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ int z85_iscomment(Buffer *buf); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ int z85_isempty(Buffer *line); -/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3377 */ +/*** bindings/py/gencffi.pl: from include/pcp/z85.h:3393 */ int z85_isencoded(Buffer *line);''' # bindings/py/gencffi.pl: from include/pcp/defines.h:187 diff --git a/bindings/py/pypcp/stream.py b/bindings/py/pypcp/stream.py index 1a1bf8d..5597116 100644 --- a/bindings/py/pypcp/stream.py +++ b/bindings/py/pypcp/stream.py @@ -1,7 +1,31 @@ +# +# This file is part of Pretty Curved Privacy (pcp1). +# +# Copyright (C) 2013-2015 T. von Dein. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# You can contact me by mail: . +# + from pypcp.dll import * class Stream(object): + """ + libpcp Stream object, used by pypcp to interact with libpcp. + """ def __init__(self, backend=None): if type(backend) is file: fd = open(backend, 'r') @@ -17,6 +41,9 @@ class Stream(object): class Buffer(object): + """ + libpcp Buffer object, used by pypcp to interact with libpcp. + """ def __init__(self, string=None): if string: self._buffer = libpcp.buffer_new_buf('pybuf', string, len(string)) diff --git a/tests/Makefile.am b/tests/Makefile.am index 0550c84..891cf35 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,7 +1,7 @@ # # This file is part of Pretty Curved Privacy (pcp1). # -# Copyright (C) 2013 T.Linden. +# Copyright (C) 2013-2015 T. von Dein. # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -64,11 +64,20 @@ cpptest_SOURCES = cpptest.cpp # %wheel ALL = NOPASSWD: /sbin/umount # %wheel ALL = NOPASSWD: /sbin/mdmfs -test: check +if BUILDPY + MAYPY=pytest +endif + +test: check $(MAYPY) + +ctest: rm -f test* v* stresstest/* ./unittests.pl unittests.cfg $(CHECK) @echo "To run a single test only, type: 'make test CHECK=testname'" +pytest: + ./unittests.pl pyunittests.cfg $(CHECK) + stresstest: check ./unittests.pl stresstests.cfg diff --git a/bindings/py/test.py b/tests/pytest.py similarity index 100% rename from bindings/py/test.py rename to tests/pytest.py diff --git a/tests/pyunittests.cfg b/tests/pyunittests.cfg new file mode 100644 index 0000000..06a92d4 --- /dev/null +++ b/tests/pyunittests.cfg @@ -0,0 +1,58 @@ +# +# This file is part of Pretty Curved Privacy (pcp1). +# +# Copyright (C) 2013-2015 T.Linden. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# You can contact me by mail: . +# + +py = ./pytest.py + + + cmd = $py impkeys + expect = /ok/ + + + + + cmd = $py asymarmor + expect = /ok/ + + + + cmd = $py asymraw + expect = /ok/ + + + + cmd = $py asymsign + expect = /ok/ + + + + cmd = $py asymanon + expect = /ok/ + + + + cmd = $py symarmor + expect = /ok/ + + + + cmd = $py symraw + expect = /ok/ + \ No newline at end of file