mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
finally fixed all stream related problems, z85 transparent en/decoding works, unittests all ok.
This commit is contained in:
@@ -50,6 +50,9 @@
|
|||||||
on the caller if it works on files or on buffers.
|
on the caller if it works on files or on buffers.
|
||||||
Pcpstreams also automatically encode/decode Z85.
|
Pcpstreams also automatically encode/decode Z85.
|
||||||
|
|
||||||
|
Due to the new pcpstream class pcp now supports
|
||||||
|
armored encrypted files, which it didn't previously.
|
||||||
|
|
||||||
Lots of refactoring have been done to clear things
|
Lots of refactoring have been done to clear things
|
||||||
out and make the system work with the changes
|
out and make the system work with the changes
|
||||||
above.
|
above.
|
||||||
@@ -73,6 +76,11 @@
|
|||||||
in man/html/. Latest API docs can be found on
|
in man/html/. Latest API docs can be found on
|
||||||
http://www.daemon.de/libpcp/.
|
http://www.daemon.de/libpcp/.
|
||||||
|
|
||||||
|
At this point I'd like to thank Liquid Soul. Only
|
||||||
|
thanks to their music I was able to do those heavy
|
||||||
|
changes. It's like a drug boosting the brain. Love
|
||||||
|
U, man!
|
||||||
|
|
||||||
0.2.0 ED25519 and Curve25519 keys are now generated
|
0.2.0 ED25519 and Curve25519 keys are now generated
|
||||||
separately (previously they were generated from
|
separately (previously they were generated from
|
||||||
one random seed, the curve had been derived from
|
one random seed, the curve had been derived from
|
||||||
|
|||||||
1
TODO
1
TODO
@@ -46,6 +46,7 @@ Check is_utf8 license.
|
|||||||
|
|
||||||
Vault checksum with global vault
|
Vault checksum with global vault
|
||||||
|
|
||||||
|
Symmetric crypt mode tries to open vault
|
||||||
|
|
||||||
Python binding, e.g.:
|
Python binding, e.g.:
|
||||||
py % cdll.LoadLibrary("libsodium.so.8")
|
py % cdll.LoadLibrary("libsodium.so.8")
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ extern "C" {
|
|||||||
#include "pcp/config.h"
|
#include "pcp/config.h"
|
||||||
#include "pcp/base85.h"
|
#include "pcp/base85.h"
|
||||||
#include "pcp/buffer.h"
|
#include "pcp/buffer.h"
|
||||||
#include "pcp/config.h"
|
|
||||||
#include "pcp/crypto.h"
|
#include "pcp/crypto.h"
|
||||||
#include "pcp/defines.h"
|
#include "pcp/defines.h"
|
||||||
#include "pcp/digital_crc32.h"
|
#include "pcp/digital_crc32.h"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2013 T.Linden.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
You can contact me by mail: <tlinden AT cpan DOT org>.
|
You can contact me by mail: <tom AT vondein DOT org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -58,8 +58,8 @@ typedef unsigned short dbyte; /* Double byte = 16 bits */
|
|||||||
typedef unsigned int qbyte; /* Quad byte = 32 bits */
|
typedef unsigned int qbyte; /* Quad byte = 32 bits */
|
||||||
|
|
||||||
/* key stuff, deprecated. */
|
/* key stuff, deprecated. */
|
||||||
#define PCP_ENFILE_HEADER "~~~~~ BEGIN PCP ENCRYPTED FILE ~~~~~"
|
#define PCP_ENFILE_HEADER "~~~~~ BEGIN PCP ENCRYPTED FILE ~~~~~\r\n"
|
||||||
#define PCP_ENFILE_FOOTER "~~~~~ END PCP ENCRYPTED FILE ~~~~~"
|
#define PCP_ENFILE_FOOTER "\r\n~~~~~ END PCP ENCRYPTED FILE ~~~~~\r\n"
|
||||||
|
|
||||||
#define PCP_ZFILE_HEADER "~~~~~ BEGIN Z85 ENCODED FILE ~~~~~"
|
#define PCP_ZFILE_HEADER "~~~~~ BEGIN Z85 ENCODED FILE ~~~~~"
|
||||||
#define PCP_ZFILE_FOOTER "~~~~~ END Z85 ENCODED FILE ~~~~~"
|
#define PCP_ZFILE_FOOTER "~~~~~ END Z85 ENCODED FILE ~~~~~"
|
||||||
|
|||||||
@@ -70,6 +70,8 @@ struct _pcp_stream_t {
|
|||||||
uint8_t firstread; /**< Internal flag, will be set after first read() */
|
uint8_t firstread; /**< Internal flag, will be set after first read() */
|
||||||
size_t linewr; /**< Used for Z85 writing, number of chars written on last line */
|
size_t linewr; /**< Used for Z85 writing, number of chars written on last line */
|
||||||
size_t blocksize; /**< Blocksize used for z85, if requested */
|
size_t blocksize; /**< Blocksize used for z85, if requested */
|
||||||
|
uint8_t is_output; /**< marks the stream as output stream */
|
||||||
|
size_t pos; /**< remember i/o position */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The name used everywhere */
|
/** The name used everywhere */
|
||||||
@@ -254,6 +256,15 @@ void ps_setdetermine(Pcpstream *stream, size_t blocksize);
|
|||||||
*/
|
*/
|
||||||
void ps_armor(Pcpstream *stream, size_t blocksize);
|
void ps_armor(Pcpstream *stream, size_t blocksize);
|
||||||
|
|
||||||
|
|
||||||
|
/** Disable Z85 encoding for an output stream.
|
||||||
|
|
||||||
|
\param[in] stream The stream object.
|
||||||
|
*/
|
||||||
|
void ps_unarmor(Pcpstream *stream);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* read from primary source, decode z85 and out into cache.
|
/* read from primary source, decode z85 and out into cache.
|
||||||
if buf != NULL, consider it as the start of encoded data
|
if buf != NULL, consider it as the start of encoded data
|
||||||
and remove headers and comments, then continue as normal. */
|
and remove headers and comments, then continue as normal. */
|
||||||
@@ -280,6 +291,9 @@ void ps_write_encode(Pcpstream *stream, Buffer *dst);
|
|||||||
/* really write the buffer z into the output stream */
|
/* really write the buffer z into the output stream */
|
||||||
size_t ps_write_buf(Pcpstream *stream, Buffer *z);
|
size_t ps_write_buf(Pcpstream *stream, Buffer *z);
|
||||||
|
|
||||||
|
/* tell if we really reached eof, caching or not. 1=eof, 0=ok */
|
||||||
|
int ps_left(Pcpstream *stream);
|
||||||
|
|
||||||
#endif // HAVE_PCP_PCPSTEAM_H
|
#endif // HAVE_PCP_PCPSTEAM_H
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2013 T.Linden.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
You can contact me by mail: <tlinden AT cpan DOT org>.
|
You can contact me by mail: <tom AT vondein DOT org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#define PCP_VERSION_MAJOR 0
|
#define PCP_VERSION_MAJOR 0
|
||||||
#define PCP_VERSION_MINOR 2
|
#define PCP_VERSION_MINOR 2
|
||||||
#define PCP_VERSION_PATCH 1
|
#define PCP_VERSION_PATCH 2
|
||||||
|
|
||||||
#define PCP_MAKE_VERSION(major, minor, patch) \
|
#define PCP_MAKE_VERSION(major, minor, patch) \
|
||||||
((major) * 10000 + (minor) * 100 + (patch))
|
((major) * 10000 + (minor) * 100 + (patch))
|
||||||
|
|||||||
@@ -125,11 +125,16 @@ byte *buffer_get(Buffer *b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
|
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
|
||||||
if(len > b->end - b->offset || len == 0) {
|
if(len > b->end - b->offset) {
|
||||||
fatal("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
|
fatal("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
|
||||||
b->name, len, b->end - b->offset, b->offset);
|
b->name, len, b->end - b->offset, b->offset);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if(len == 0) {
|
||||||
|
/* FIXME: check how this happens */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(buf, b->buf + b->offset, len);
|
memcpy(buf, b->buf + b->offset, len);
|
||||||
|
|
||||||
b->offset += len;
|
b->offset += len;
|
||||||
@@ -137,11 +142,15 @@ size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t buffer_get_chunk_tobuf(Buffer *b, Buffer *dst, size_t len) {
|
size_t buffer_get_chunk_tobuf(Buffer *b, Buffer *dst, size_t len) {
|
||||||
if(len > b->end - b->offset || len == 0) {
|
if(len > b->end - b->offset) {
|
||||||
fatal("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
|
fatal("[buffer %s] attempt to read %ld bytes data from buffer with %ld bytes left at offset %ld\n",
|
||||||
b->name, len, b->end - b->offset, b->offset);
|
b->name, len, b->end - b->offset, b->offset);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
else if(len == 0) {
|
||||||
|
/* FIXME: check how this happens */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
buffer_resize(dst, len);
|
buffer_resize(dst, len);
|
||||||
memcpy(dst->buf+buffer_size(dst), b->buf + b->offset, len);
|
memcpy(dst->buf+buffer_size(dst), b->buf + b->offset, len);
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *sym
|
|||||||
|
|
||||||
nrec = recmatch = self = 0;
|
nrec = recmatch = self = 0;
|
||||||
|
|
||||||
if(ps_tell(in) == 1) {
|
if(ps_tell(in) > 1) {
|
||||||
/* header has already been determined outside the lib */
|
/* header has already been determined outside the lib */
|
||||||
if(symkey != NULL)
|
if(symkey != NULL)
|
||||||
self = 1;
|
self = 1;
|
||||||
@@ -233,7 +233,7 @@ size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *sym
|
|||||||
for(nrec=0; nrec<lenrec; nrec++) {
|
for(nrec=0; nrec<lenrec; nrec++) {
|
||||||
cur_bufsize = ps_read(in, &rec_buf, PCP_ASYM_RECIPIENT_SIZE); /* fread(&rec_buf, 1, PCP_ASYM_RECIPIENT_SIZE, in); */
|
cur_bufsize = ps_read(in, &rec_buf, PCP_ASYM_RECIPIENT_SIZE); /* fread(&rec_buf, 1, PCP_ASYM_RECIPIENT_SIZE, in); */
|
||||||
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !ps_end(in) && !ps_err(in)) {
|
if(cur_bufsize != PCP_ASYM_RECIPIENT_SIZE && !ps_end(in) && !ps_err(in)) {
|
||||||
fatal("Error: input file corrupted, incomplete or no recipients\n");
|
fatal("Error: input file corrupted, incomplete or no recipients (got %ld, exp %ld)\n", cur_bufsize, PCP_ASYM_RECIPIENT_SIZE );
|
||||||
goto errdef1;
|
goto errdef1;
|
||||||
}
|
}
|
||||||
recmatch = 0;
|
recmatch = 0;
|
||||||
@@ -263,16 +263,17 @@ size_t pcp_decrypt_stream(Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *sym
|
|||||||
goto errdef1;
|
goto errdef1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* step 5, actually decrypt the file, finally */
|
/* step 5, actually decrypt the file, finally */
|
||||||
if(verify) {
|
if(verify) {
|
||||||
pcp_rec_t *rec = pcp_rec_new(reccipher, nrec * PCP_ASYM_RECIPIENT_SIZE, NULL, cur);
|
pcp_rec_t *rec = pcp_rec_new(reccipher, nrec * PCP_ASYM_RECIPIENT_SIZE, NULL, cur);
|
||||||
return pcp_decrypt_stream_sym(in, out, symkey, rec);
|
size_t s = pcp_decrypt_stream_sym(in, out, symkey, rec);
|
||||||
pcp_rec_free(rec);
|
pcp_rec_free(rec);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t s = pcp_decrypt_stream_sym(in, out, symkey, NULL);
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
return pcp_decrypt_stream_sym(in, out, symkey, NULL);
|
|
||||||
|
|
||||||
|
|
||||||
errdef1:
|
errdef1:
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ void ps_setdetermine(Pcpstream *stream, size_t blocksize) {
|
|||||||
stream->determine = 1;
|
stream->determine = 1;
|
||||||
stream->blocksize = blocksize + (5 - (blocksize % 5));
|
stream->blocksize = blocksize + (5 - (blocksize % 5));
|
||||||
if(stream->cache == NULL) {
|
if(stream->cache == NULL) {
|
||||||
stream->cache = buffer_new(32, "Pcpstreamcache");
|
stream->cache = buffer_new(32, "Pcpstreamcachedetermine");
|
||||||
stream->next = buffer_new(32, "Pcpstreamcachenext");
|
stream->next = buffer_new(32, "Pcpstreamcachenextdetermin");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,6 +75,10 @@ void ps_armor(Pcpstream *stream, size_t blocksize) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ps_unarmor(Pcpstream *stream) {
|
||||||
|
stream->armor = 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
|
size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||||
size_t gotbytes = 0;
|
size_t gotbytes = 0;
|
||||||
|
|
||||||
@@ -107,18 +111,28 @@ size_t ps_read_raw(Pcpstream *stream, void *buf, size_t readbytes) {
|
|||||||
/* return readbytes from cache. if it is more than left in the cache
|
/* return readbytes from cache. if it is more than left in the cache
|
||||||
fetch (and decode) the next chunk, append it to cache and return from
|
fetch (and decode) the next chunk, append it to cache and return from
|
||||||
that */
|
that */
|
||||||
|
|
||||||
size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
|
size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||||
if(buffer_left(stream->cache) <= readbytes && buffer_left(stream->cache) > 0 && readbytes <= stream->blocksize) {
|
/*
|
||||||
|
fprintf(stderr, "%ld <= %ld && %ld <= %ld\n",
|
||||||
|
readbytes, buffer_left(stream->cache), readbytes, stream->blocksize) ;
|
||||||
|
|
||||||
|
fprintf(stderr, "%d == 1 && %ld >= %ld\n", ps_left(stream), readbytes, buffer_left(stream->cache));
|
||||||
|
*/
|
||||||
|
if(readbytes <= buffer_left(stream->cache) && readbytes <= stream->blocksize) {
|
||||||
/* enough left in current cache */
|
/* enough left in current cache */
|
||||||
return buffer_get_chunk(stream->cache, buf, readbytes);
|
return buffer_get_chunk(stream->cache, buf, readbytes);
|
||||||
}
|
}
|
||||||
|
else if(ps_left(stream) == 1 && readbytes >= buffer_left(stream->cache)) {
|
||||||
|
return buffer_get_chunk(stream->cache, buf, buffer_left(stream->cache));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
/* request for chunk larger than what we've got in the cache */
|
/* request for chunk larger than what we've got in the cache */
|
||||||
Buffer *tmp = buffer_new(stream->blocksize, "Pcpreadover");
|
Buffer *tmp = buffer_new(stream->blocksize, "Pcpreadchunktmp");
|
||||||
|
|
||||||
if( buffer_left(stream->cache) > 0) {
|
if( buffer_left(stream->cache) > 0) {
|
||||||
/* put the remaining cache into dest */
|
/* put the remaining cache into dest */
|
||||||
buffer_get_chunk_tobuf(stream->cache, tmp, buffer_size(stream->cache));
|
buffer_get_chunk_tobuf(stream->cache, tmp, buffer_left(stream->cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* how much left to fetch */
|
/* how much left to fetch */
|
||||||
@@ -170,6 +184,7 @@ size_t ps_read_cached(Pcpstream *stream, void *buf, size_t readbytes) {
|
|||||||
|
|
||||||
/* read and decode the next chunk and put it into stream->next */
|
/* read and decode the next chunk and put it into stream->next */
|
||||||
size_t ps_read_next(Pcpstream *stream) {
|
size_t ps_read_next(Pcpstream *stream) {
|
||||||
|
if(ps_left(stream) == 0) {
|
||||||
if(stream->armor == 1) {
|
if(stream->armor == 1) {
|
||||||
/* fetch next chunk and decode it */
|
/* fetch next chunk and decode it */
|
||||||
return ps_read_decode(stream, NULL, 0);
|
return ps_read_decode(stream, NULL, 0);
|
||||||
@@ -182,14 +197,18 @@ size_t ps_read_next(Pcpstream *stream) {
|
|||||||
return got;
|
return got;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
|
size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
|
||||||
|
size_t got = 0;
|
||||||
if(stream->cache == NULL) {
|
if(stream->cache == NULL) {
|
||||||
return ps_read_raw(stream, buf, readbytes);
|
got = ps_read_raw(stream, buf, readbytes);
|
||||||
}
|
}
|
||||||
else if(buffer_size(stream->cache) > 0) {
|
else if(buffer_size(stream->cache) > 0) {
|
||||||
/* use cache */
|
/* use cache */
|
||||||
return ps_read_cached(stream, buf, readbytes);
|
got = ps_read_cached(stream, buf, readbytes);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* no cache yet */
|
/* no cache yet */
|
||||||
@@ -197,18 +216,22 @@ size_t ps_read(Pcpstream *stream, void *buf, size_t readbytes) {
|
|||||||
/* fetch the first chunk into the cache and decode, if required,
|
/* fetch the first chunk into the cache and decode, if required,
|
||||||
recursively call ps_read() again to return the apropriate data */
|
recursively call ps_read() again to return the apropriate data */
|
||||||
ps_determine(stream);
|
ps_determine(stream);
|
||||||
return ps_read(stream, buf, readbytes);
|
got = ps_read(stream, buf, readbytes);
|
||||||
}
|
}
|
||||||
else if(stream->armor == 1) {
|
else if(stream->armor == 1) {
|
||||||
/* z85 encoding has already been determined, therefore the cache
|
/* z85 encoding has already been determined, therefore the cache
|
||||||
is now filled, use it then */
|
is now filled, use it then */
|
||||||
return ps_read_cached(stream, buf, readbytes);
|
got = ps_read_cached(stream, buf, readbytes);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* read directly from source */
|
/* read directly from source */
|
||||||
return ps_read_raw(stream, buf, readbytes);
|
got = ps_read_raw(stream, buf, readbytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream->pos += got;
|
||||||
|
|
||||||
|
return got;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps_determine(Pcpstream *stream) {
|
void ps_determine(Pcpstream *stream) {
|
||||||
@@ -285,6 +308,8 @@ size_t ps_read_decode(Pcpstream *stream, void *buf, size_t bufsize) {
|
|||||||
size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
|
size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
|
||||||
Buffer *z = buffer_new(32, "Pcpwritetemp");
|
Buffer *z = buffer_new(32, "Pcpwritetemp");
|
||||||
|
|
||||||
|
stream->is_output = 1;
|
||||||
|
|
||||||
if(stream->armor == 1) {
|
if(stream->armor == 1) {
|
||||||
if(buffer_size(stream->cache) + writebytes < stream->blocksize) {
|
if(buffer_size(stream->cache) + writebytes < stream->blocksize) {
|
||||||
/* just put it into the cache and done with it */
|
/* just put it into the cache and done with it */
|
||||||
@@ -350,13 +375,16 @@ size_t ps_write(Pcpstream *stream, void *buf, size_t writebytes) {
|
|||||||
/* actually put it out */
|
/* actually put it out */
|
||||||
size_t outsize = ps_write_buf(stream, z);
|
size_t outsize = ps_write_buf(stream, z);
|
||||||
buffer_free(z);
|
buffer_free(z);
|
||||||
return outsize;
|
writebytes = outsize;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* buf has been put into the cache only, no writing required */
|
/* buf has been put into the cache only, no writing required */
|
||||||
buffer_free(z);
|
buffer_free(z);
|
||||||
return writebytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stream->pos += writebytes;
|
||||||
|
|
||||||
|
return writebytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ps_write_encode(Pcpstream *stream, Buffer *dst) {
|
void ps_write_encode(Pcpstream *stream, Buffer *dst) {
|
||||||
@@ -372,14 +400,14 @@ void ps_write_encode(Pcpstream *stream, Buffer *dst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* z85 encode */
|
/* z85 encode */
|
||||||
zlen = (buffer_size(stream->cache) * 5 / 4);
|
zlen = (buffer_size(stream->cache) * 5 / 4) + 1;
|
||||||
char *z85 = ucmalloc(zlen);
|
char *z85 = ucmalloc(zlen);
|
||||||
|
|
||||||
zmq_z85_encode(z85, buffer_get(stream->cache), buffer_size(stream->cache));
|
zmq_z85_encode(z85, buffer_get(stream->cache), buffer_size(stream->cache));
|
||||||
|
|
||||||
/* add newlines */
|
/* add newlines */
|
||||||
pos = stream->linewr;
|
pos = stream->linewr;
|
||||||
for(i=0; i<zlen; ++i) {
|
for(i=0; i<zlen-1; ++i) {
|
||||||
if(pos >= 71) {
|
if(pos >= 71) {
|
||||||
buffer_add8(dst, '\r');
|
buffer_add8(dst, '\r');
|
||||||
buffer_add8(dst, '\n');
|
buffer_add8(dst, '\n');
|
||||||
@@ -445,7 +473,11 @@ size_t ps_print(Pcpstream *stream, const char * fmt, ...) {
|
|||||||
|
|
||||||
void ps_close(Pcpstream *stream) {
|
void ps_close(Pcpstream *stream) {
|
||||||
if(stream->cache != NULL) {
|
if(stream->cache != NULL) {
|
||||||
|
if(stream->is_output == 1) {
|
||||||
|
if(buffer_left(stream->cache) != 0)
|
||||||
|
buffer_info(stream->cache);
|
||||||
assert(buffer_left(stream->cache) == 0); /* there's something left in the cache, call ps_finish() */
|
assert(buffer_left(stream->cache) == 0); /* there's something left in the cache, call ps_finish() */
|
||||||
|
}
|
||||||
buffer_free(stream->cache);
|
buffer_free(stream->cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,25 +499,31 @@ void ps_close(Pcpstream *stream) {
|
|||||||
int ps_end(Pcpstream *stream) {
|
int ps_end(Pcpstream *stream) {
|
||||||
/* simulate open file if there's still something in the cache */
|
/* simulate open file if there's still something in the cache */
|
||||||
if(stream->cache != NULL)
|
if(stream->cache != NULL)
|
||||||
if(buffer_left(stream->cache) > 0)
|
if(buffer_left(stream->cache) > 0) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
return stream->eof;
|
return stream->eof;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ps_left(Pcpstream *stream) {
|
||||||
|
/* used internally to determine if we reached end of source */
|
||||||
|
if(stream->is_buffer) {
|
||||||
|
if(buffer_left(stream->b) == 0)
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return feof(stream->fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int ps_err(Pcpstream *stream) {
|
int ps_err(Pcpstream *stream) {
|
||||||
return stream->err;
|
return stream->err;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ps_tell(Pcpstream *stream) {
|
size_t ps_tell(Pcpstream *stream) {
|
||||||
if(stream->is_buffer) {
|
return stream->pos;
|
||||||
if(stream->b->end > stream->b->offset)
|
|
||||||
return stream->b->end; /* write buffer */
|
|
||||||
else
|
|
||||||
return stream->b->offset; /* read buffer */
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return ftell(stream->fd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer *ps_buffer(Pcpstream *stream) {
|
Buffer *ps_buffer(Pcpstream *stream) {
|
||||||
|
|||||||
@@ -448,6 +448,9 @@ secret key, R is the recipient list, L is the number of recipients,
|
|||||||
T is the filetype header, I is a block of input with a size
|
T is the filetype header, I is a block of input with a size
|
||||||
of 32k, N is a nonce (new per block) and S the symmetric key.
|
of 32k, N is a nonce (new per block) and S the symmetric key.
|
||||||
|
|
||||||
|
The encrypted output maybe Z85 encoded. In this case the Z85
|
||||||
|
encoding will be done blockwise with blocks of 16k bytes. The
|
||||||
|
decoded content inside will be as described above.
|
||||||
|
|
||||||
=head2 SIGNATURE FORMAT
|
=head2 SIGNATURE FORMAT
|
||||||
|
|
||||||
@@ -552,6 +555,19 @@ secret signing key and S the symmetric key.
|
|||||||
=head2 Z85 ENCODING
|
=head2 Z85 ENCODING
|
||||||
|
|
||||||
B<pcp1> uses Z85 to encode exported keys and armored signatures.
|
B<pcp1> uses Z85 to encode exported keys and armored signatures.
|
||||||
|
Comments in encoded files are surrounded by the tilde character.
|
||||||
|
We're using the tilde because it's not part of the Z85 base
|
||||||
|
charset. Sample:
|
||||||
|
|
||||||
|
~~~ Header ~~~
|
||||||
|
~ Version: 1 ~
|
||||||
|
246ge]+yn={<I&&Z%(pm[09lc5[dx4TZALi/6cjVe)Kx5S}7>}]Xi3*N3Xx34Y^0rz:r.5j
|
||||||
|
v#6Sh/m3XKwy?VlA+h8ks]9:kVj{D[fd7]NA]T-(ne+xo!W5X5-gIUWqM
|
||||||
|
~~~ Footer ~~~
|
||||||
|
|
||||||
|
Multiple tildes can be used as long as their number is uneven.
|
||||||
|
|
||||||
|
This is a proprietary PCP extension.
|
||||||
|
|
||||||
=head3 Z85 BACKGROUND
|
=head3 Z85 BACKGROUND
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@
|
|||||||
If none of -i or -r has been given, encrypt
|
If none of -i or -r has been given, encrypt
|
||||||
the message symetrically. This is the same
|
the message symetrically. This is the same
|
||||||
as -m (self-encryption mode).
|
as -m (self-encryption mode).
|
||||||
|
Add -z to ascii armor the output using Z85.
|
||||||
-m --encrypt-me Sym-Encrypt a message. Specify -I and/or
|
-m --encrypt-me Sym-Encrypt a message. Specify -I and/or
|
||||||
-O for input/output file. You will be asked
|
-O for input/output file. You will be asked
|
||||||
for a passphrase. No key material will
|
for a passphrase. No key material will
|
||||||
@@ -112,9 +113,9 @@
|
|||||||
If used with encryption or singing operation
|
If used with encryption or singing operation
|
||||||
encode its output. Otherwise encode a plain
|
encode its output. Otherwise encode a plain
|
||||||
file. Use -I and -O respectively, otherwise it
|
file. Use -I and -O respectively, otherwise it
|
||||||
stdin/stdout.
|
uses stdin/stdout.
|
||||||
-Z --z85-decode Decode (dearmor) something from Z85 encoding.
|
-Z --z85-decode Decode (dearmor) something from Z85 encoding.
|
||||||
Use -I and -O respectively, otherwise it
|
Use -I and -O respectively, otherwise it
|
||||||
stdin/stdout
|
uses stdin/stdout
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2013 T.Linden.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
You can contact me by mail: <tlinden AT cpan DOT org>.
|
You can contact me by mail: <tom AT vondein DOT org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -48,9 +48,15 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Pcpstream *pin = ps_new_file(in);
|
||||||
|
Pcpstream *pout = ps_new_file(out);
|
||||||
|
|
||||||
|
ps_setdetermine(pin, PCP_BLOCK_SIZE/2);
|
||||||
|
|
||||||
/* determine crypt mode */
|
/* determine crypt mode */
|
||||||
fread(&head, 1, 1, in);
|
ps_read(pin, &head, 1);
|
||||||
if(!feof(in) && !ferror(in)) {
|
|
||||||
|
if(!ps_end(pin) && !ps_err(pin)) {
|
||||||
if(head == PCP_SYM_CIPHER) {
|
if(head == PCP_SYM_CIPHER) {
|
||||||
/* symetric mode */
|
/* symetric mode */
|
||||||
byte *salt = ucmalloc(90);
|
byte *salt = ucmalloc(90);
|
||||||
@@ -110,9 +116,6 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
|
|||||||
goto errde3;
|
goto errde3;
|
||||||
}
|
}
|
||||||
|
|
||||||
Pcpstream *pin = ps_new_file(in);
|
|
||||||
Pcpstream *pout = ps_new_file(out);
|
|
||||||
|
|
||||||
if(symkey == NULL)
|
if(symkey == NULL)
|
||||||
dlen = pcp_decrypt_stream(pin, pout, secret, NULL, verify);
|
dlen = pcp_decrypt_stream(pin, pout, secret, NULL, verify);
|
||||||
else
|
else
|
||||||
@@ -136,7 +139,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt) {
|
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt, int armor) {
|
||||||
FILE *in = NULL;
|
FILE *in = NULL;
|
||||||
FILE *out = NULL;
|
FILE *out = NULL;
|
||||||
pcp_pubkey_t *pubhash = NULL; /* FIXME: add free() */
|
pcp_pubkey_t *pubhash = NULL; /* FIXME: add free() */
|
||||||
@@ -266,14 +269,26 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
|
|||||||
Pcpstream *pin = ps_new_file(in);
|
Pcpstream *pin = ps_new_file(in);
|
||||||
Pcpstream *pout = ps_new_file(out);
|
Pcpstream *pout = ps_new_file(out);
|
||||||
|
|
||||||
|
if(armor == 1) {
|
||||||
|
ps_print(pout, PCP_ENFILE_HEADER);
|
||||||
|
ps_armor(pout, PCP_BLOCK_SIZE/2);
|
||||||
|
}
|
||||||
|
|
||||||
if(self == 1)
|
if(self == 1)
|
||||||
clen = pcp_encrypt_stream_sym(pin, pout, symkey, 0, NULL);
|
clen = pcp_encrypt_stream_sym(pin, pout, symkey, 0, NULL);
|
||||||
else
|
else
|
||||||
clen = pcp_encrypt_stream(pin, pout, secret, pubhash, signcrypt);
|
clen = pcp_encrypt_stream(pin, pout, secret, pubhash, signcrypt);
|
||||||
|
|
||||||
ps_close(pin);
|
if(armor == 1) {
|
||||||
|
ps_finish(pout);
|
||||||
|
ps_unarmor(pout);
|
||||||
|
ps_print(pout, PCP_ENFILE_FOOTER);
|
||||||
|
}
|
||||||
|
|
||||||
ps_close(pout);
|
ps_close(pout);
|
||||||
|
|
||||||
|
ps_close(pin);
|
||||||
|
|
||||||
if(clen > 0) {
|
if(clen > 0) {
|
||||||
if(id == NULL && recipient == NULL)
|
if(id == NULL && recipient == NULL)
|
||||||
fprintf(stderr, "Encrypted %ld bytes symetrically\n", clen);
|
fprintf(stderr, "Encrypted %ld bytes symetrically\n", clen);
|
||||||
|
|||||||
@@ -38,6 +38,6 @@
|
|||||||
#include "pcpstream.h"
|
#include "pcpstream.h"
|
||||||
|
|
||||||
int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, int verify);
|
int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, int verify);
|
||||||
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt);
|
int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt, int armor);
|
||||||
|
|
||||||
#endif /* _HAVE_ENCRYPTION_H */
|
#endif /* _HAVE_ENCRYPTION_H */
|
||||||
|
|||||||
@@ -474,11 +474,11 @@ int main (int argc, char **argv) {
|
|||||||
if(useid == 1 && userec == 0) {
|
if(useid == 1 && userec == 0) {
|
||||||
/* one dst, FIXME: make id a list as well */
|
/* one dst, FIXME: make id a list as well */
|
||||||
id = pcp_normalize_id(keyid);
|
id = pcp_normalize_id(keyid);
|
||||||
pcpencrypt(id, infile, outfile, xpass, NULL, signcrypt);
|
pcpencrypt(id, infile, outfile, xpass, NULL, signcrypt, armor);
|
||||||
}
|
}
|
||||||
else if(useid == 0 && userec == 1) {
|
else if(useid == 0 && userec == 1) {
|
||||||
/* multiple dst */
|
/* multiple dst */
|
||||||
pcpencrypt(NULL, infile, outfile, xpass, recipient, signcrypt);
|
pcpencrypt(NULL, infile, outfile, xpass, recipient, signcrypt, armor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* -i and -r specified */
|
/* -i and -r specified */
|
||||||
@@ -558,7 +558,7 @@ int main (int argc, char **argv) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PCP_MODE_ENCRYPT_ME:
|
case PCP_MODE_ENCRYPT_ME:
|
||||||
pcpencrypt(NULL, infile, outfile, xpass, NULL, 0);
|
pcpencrypt(NULL, infile, outfile, xpass, NULL, 0, armor);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCP_MODE_TEXT:
|
case PCP_MODE_TEXT:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
#include <pcp.h>
|
#include <pcp.h>
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,40 @@ include keys.cfg
|
|||||||
</test>
|
</test>
|
||||||
|
|
||||||
|
|
||||||
|
<test check-streams>
|
||||||
|
<test check-streams-8-8>
|
||||||
|
md5 = `md5 -q ../COPYING`
|
||||||
|
cmd = ./pipetest 8 8 e < ../COPYING | ./pipetest 8 8 d | md5 -q
|
||||||
|
expect = /$md5/
|
||||||
|
</test>
|
||||||
|
<test check-streams-8-16>
|
||||||
|
md5 = `md5 -q ../COPYING`
|
||||||
|
cmd = ./pipetest 8 16 e < ../COPYING | ./pipetest 8 16 d | md5 -q
|
||||||
|
expect = /$md5/
|
||||||
|
</test>
|
||||||
|
<test check-streams-16-8>
|
||||||
|
md5 = `md5 -q ../COPYING`
|
||||||
|
cmd = ./pipetest 16 8 e < ../COPYING | ./pipetest 16 8 d | md5 -q
|
||||||
|
expect = /$md5/
|
||||||
|
</test>
|
||||||
|
<test check-streams-64-32>
|
||||||
|
md5 = `md5 -q ../COPYING`
|
||||||
|
cmd = ./pipetest 64 32 e < ../COPYING | ./pipetest 64 32 d | md5 -q
|
||||||
|
expect = /$md5/
|
||||||
|
</test>
|
||||||
|
<test check-streams-32-64>
|
||||||
|
md5 = `md5 -q ../COPYING`
|
||||||
|
cmd = ./pipetest 32 64 e < ../COPYING | ./pipetest 32 64 d | md5 -q
|
||||||
|
expect = /$md5/
|
||||||
|
</test>
|
||||||
|
<test check-streams-64-64>
|
||||||
|
md5 = `md5 -q ../COPYING`
|
||||||
|
cmd = ./pipetest 64 64 e < ../COPYING | ./pipetest 64 64 d | md5 -q
|
||||||
|
expect = /$md5/
|
||||||
|
</test>
|
||||||
|
</test>
|
||||||
|
|
||||||
|
|
||||||
<test check-show-help>
|
<test check-show-help>
|
||||||
cmd = $pcp -h
|
cmd = $pcp -h
|
||||||
expect = /export/
|
expect = /export/
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ sub runtest {
|
|||||||
my($cfg, $name) = @_;
|
my($cfg, $name) = @_;
|
||||||
my($in, $out, $error, $timeout);
|
my($in, $out, $error, $timeout);
|
||||||
|
|
||||||
|
foreach my $key (keys %{$cfg}) {
|
||||||
|
$cfg->{$key} =~ s/\`([^\`]*)\`/my $result = `$1`; chomp $result; $result/ge;
|
||||||
|
}
|
||||||
|
|
||||||
if (exists $cfg->{prepare}) {
|
if (exists $cfg->{prepare}) {
|
||||||
print STDERR " executing prepare command: $cfg->{prepare}\n" if ($verbose);
|
print STDERR " executing prepare command: $cfg->{prepare}\n" if ($verbose);
|
||||||
if ($cfg->{prepare} =~ />/) {
|
if ($cfg->{prepare} =~ />/) {
|
||||||
|
|||||||
Reference in New Issue
Block a user