diff --git a/ChangeLog b/ChangeLog
index 669de9c..32e0bc8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+0.2.3 Z85 block encoding changed. 4 bytes are appended
+ to each input block to denote if and how many
+ zeroes have been used for padding, necessary
+ since z85 doesn't have any native padding scheme,
+ and only padding with zeroes is insuffucient. This
+ change breaks - currently - compatibility to pbp.
+
+ Added new option --anonymous (-A) which uses a
+ generated keypair for encryption and puts the
+ public part into the encrypted message.
+
+ Fixed lots of memory leaks.
+
0.2.2 Enhanded --edit-key a little, it's now possible to
make a secret the primary one.
diff --git a/bindings/cpp/crypto.cpp b/bindings/cpp/crypto.cpp
index 5cdc58e..0d8cbb5 100644
--- a/bindings/cpp/crypto.cpp
+++ b/bindings/cpp/crypto.cpp
@@ -54,7 +54,7 @@ bool Crypto::encrypt(FILE *in, FILE *out, bool sign) {
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
- size_t clen = pcp_encrypt_stream(PTX->ptx, pin, pout, S.K, pubhash, sign);
+ size_t clen = pcp_encrypt_stream(PTX->ptx, pin, pout, S.K, pubhash, sign, 0); // FIXME: add anon support
if(clen <= 0)
throw exception(PTX);
ps_close(pin);
@@ -66,7 +66,7 @@ bool Crypto::decrypt(FILE *in, FILE *out, bool verify) {
Pcpstream *pin = ps_new_file(in);
Pcpstream *pout = ps_new_file(out);
- if(pcp_decrypt_stream(PTX->ptx, pin, pout, S.K, NULL, verify) <= 0)
+ if(pcp_decrypt_stream(PTX->ptx, pin, pout, S.K, NULL, verify, 0) <= 0)
throw exception(PTX);
ps_close(pin);
ps_close(pout);
diff --git a/include/pcp/crypto.h b/include/pcp/crypto.h
index 07a6938..3ab2575 100644
--- a/include/pcp/crypto.h
+++ b/include/pcp/crypto.h
@@ -195,11 +195,13 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
\param[in] p Public key hash containing a list of the recipients.
- \param signcrypt Flag to indicate sign+crypt. If 1 it adds a signature, otherwise not.
+ \param[in] signcrypt Flag to indicate sign+crypt. If 1 it adds a signature, otherwise not.
+
+ \param[in] anon Flag to indicate if using anonymous sender key. 0 retains std behaviour, not anon.
\return Returns the size of the output written to the output stream or 0 in case of errors.
*/
-size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, pcp_pubkey_t *p, int signcrypt);
+size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, pcp_pubkey_t *p, int signcrypt, int anon);
/** Symmetrically encrypt a file or a buffer stream.
@@ -248,9 +250,11 @@ size_t pcp_encrypt_stream_sym(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, byte *
\param verify Flag to indicate sign+crypt. If 1 it tries to verify a signature, otherwise not.
+ \param[in] anon Flag to indicate if using anonymous sender key. 0 retains std behaviour, not anon.
+
\return Returns the size of the output written to the output stream or 0 in case of errors.
*/
-size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *symkey, int verify);
+size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *symkey, int verify, int anon);
/** Symmetrically decrypt a file or a buffer stream.
diff --git a/include/pcp/defines.h b/include/pcp/defines.h
index a3bc158..89583b0 100644
--- a/include/pcp/defines.h
+++ b/include/pcp/defines.h
@@ -117,12 +117,14 @@ typedef enum _PCP_KEY_TYPES {
/* enabled via config.h (configure --enable-cbc) */
#ifndef PCP_CBC
#define PCP_ASYM_CIPHER 5
+ #define PCP_ASYM_CIPHER_ANON 6
#define PCP_SYM_CIPHER 23
#define PCP_ASYM_CIPHER_SIG 24
#define PCP_BLOCK_SIZE 32 * 1024
#else
/* CBC mode, use smaller blocks */
#define PCP_ASYM_CIPHER 7
+ #define PCP_ASYM_CIPHER_ANON 9
#define PCP_ASYM_CIPHER_SIG 8
#define PCP_SYM_CIPHER 25
#define PCP_BLOCK_SIZE 1 * 1024
diff --git a/include/pcp/version.h b/include/pcp/version.h
index b3a672d..b570027 100644
--- a/include/pcp/version.h
+++ b/include/pcp/version.h
@@ -25,7 +25,7 @@
#define PCP_VERSION_MAJOR 0
#define PCP_VERSION_MINOR 2
-#define PCP_VERSION_PATCH 2
+#define PCP_VERSION_PATCH 3
#define PCP_MAKE_VERSION(major, minor, patch) \
((major) * 10000 + (minor) * 100 + (patch))
diff --git a/libpcp/crypto.c b/libpcp/crypto.c
index 9460064..9032887 100644
--- a/libpcp/crypto.c
+++ b/libpcp/crypto.c
@@ -161,19 +161,15 @@ byte *pcp_box_decrypt(PCPCTX *ptx, pcp_key_t *secret, pcp_pubkey_t *pub,
return NULL;
}
-size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *symkey, int verify) {
+size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t *s, byte *symkey, int verify, int anon) {
pcp_pubkey_t *cur = NULL;
byte *reccipher = NULL;
int recmatch, self;
uint32_t lenrec;
byte head[1];
size_t cur_bufsize, rec_size, nrec;
-
byte *rec_buf = NULL;
-
-#ifdef PCP_ASYM_ADD_SENDER_PUB
- byte *senderpub;
-#endif
+ pcp_pubkey_t *senderpub = NULL; /* anon only */
nrec = recmatch = self = 0;
@@ -194,6 +190,10 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
goto errdef1;
}
}
+ else if(head[0] == PCP_ASYM_CIPHER_ANON) {
+ self = 0;
+ anon = 1;
+ }
else if(head[0] == PCP_ASYM_CIPHER) {
self = 0;
}
@@ -213,14 +213,15 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
return pcp_decrypt_stream_sym(ptx, in, out, symkey, NULL);
}
-#ifdef PCP_ASYM_ADD_SENDER_PUB
- /* step 2, sender's pubkey */
- cur_bufsize = ps_read(in, &in_buf, crypto_box_PUBLICKEYBYTES);
- if(cur_bufsize != crypto_box_PUBLICKEYBYTES && !ps_end(in) && !ps_err(in)) {
- fatal(ptx, "Error: input file doesn't contain senders public key\n");
- goto errdef1;
+ if(anon) {
+ /* step 2, sender's pubkey */
+ senderpub = ucmalloc(sizeof(pcp_pubkey_t));
+ cur_bufsize = ps_read(in, senderpub->pub, crypto_box_PUBLICKEYBYTES);
+ if(cur_bufsize != crypto_box_PUBLICKEYBYTES && !ps_end(in) && !ps_err(in)) {
+ fatal(ptx, "Error: input file doesn't contain senders public key\n");
+ goto errdef1;
+ }
}
-#endif
/* step 3, check len recipients */
cur_bufsize = ps_read(in, &lenrec, 4); /* fread(&lenrec, 1, 4, in); */
@@ -247,17 +248,36 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
}
recmatch = 0;
- pcphash_iteratepub(ptx, cur) {
+ if(anon) {
+ /* anonymous sender */
byte *recipient;
- recipient = pcp_box_decrypt(ptx, s, cur, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
+ recipient = pcp_box_decrypt(ptx, s, senderpub, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
/* found a match */
recmatch = 1;
symkey = ucmalloc(crypto_secretbox_KEYBYTES);
memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
free(recipient);
+ ucfree(senderpub, sizeof(pcp_pubkey_t));
break;
}
+ free(recipient);
+ }
+ else {
+ /* dig through our list of known public keys for a match */
+ pcphash_iteratepub(ptx, cur) {
+ byte *recipient;
+ recipient = pcp_box_decrypt(ptx, s, cur, rec_buf, PCP_ASYM_RECIPIENT_SIZE, &rec_size);
+ if(recipient != NULL && rec_size == crypto_secretbox_KEYBYTES) {
+ /* found a match */
+ recmatch = 1;
+ symkey = ucmalloc(crypto_secretbox_KEYBYTES);
+ memcpy(symkey, recipient, crypto_secretbox_KEYBYTES);
+ free(recipient);
+ break;
+ }
+ free(recipient);
+ }
}
if(verify) {
size_t R = nrec * (PCP_ASYM_RECIPIENT_SIZE);
@@ -290,7 +310,7 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
return 0;
}
-size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t *s, pcp_pubkey_t *p, int sign) {
+size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t *s, pcp_pubkey_t *p, int sign, int anon) {
byte *symkey;
int recipient_count;
byte *recipients_cipher;
@@ -336,24 +356,25 @@ size_t pcp_encrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream *out, pcp_key_t
/* step 1, file header */
if(sign)
head[0] = PCP_ASYM_CIPHER_SIG;
+ else if(anon)
+ head[0] = PCP_ASYM_CIPHER_ANON;
else
head[0] = PCP_ASYM_CIPHER;
ps_write(out, head, 1);
- /* fwrite(head, 1, 1, out); */
- /* fprintf(stderr, "D: header - 1\n"); */
+
if(ps_err(out) != 0) {
fatal(ptx, "Failed to write encrypted output!\n");
goto errec1;
}
-#ifdef PCP_ASYM_ADD_SENDER_PUB
- /* step 2, sender's pubkey */
- ps_write(out, s->pub, crypto_box_PUBLICKEYBYTES);
- /*fwrite(s->pub, crypto_box_PUBLICKEYBYTES, 1, out); */
- /* fprintf(stderr, "D: sender pub - %d\n", crypto_box_PUBLICKEYBYTES); */
- if(ps_err(out) != 0)
- goto errec1;
-#endif
+ if(anon) {
+ /* step 2, sender's pubkey */
+ ps_write(out, s->pub, crypto_box_PUBLICKEYBYTES);
+ /*fwrite(s->pub, crypto_box_PUBLICKEYBYTES, 1, out); */
+ /* fprintf(stderr, "D: sender pub - %d\n", crypto_box_PUBLICKEYBYTES); */
+ if(ps_err(out) != 0)
+ goto errec1;
+ }
/* step 3, len recipients, big endian */
lenrec = recipient_count;
diff --git a/src/encryption.c b/src/encryption.c
index 82535c2..3a16d24 100644
--- a/src/encryption.c
+++ b/src/encryption.c
@@ -29,6 +29,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
byte *symkey = NULL;
size_t dlen;
uint8_t head;
+ int anon = 0;
if(infile == NULL)
in = stdin;
@@ -77,7 +78,7 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
ucfree(passphrase, strlen(passwd)+1);
free(salt);
}
- else if(head == PCP_ASYM_CIPHER || head == PCP_ASYM_CIPHER_SIG) {
+ else if(head == PCP_ASYM_CIPHER || head == PCP_ASYM_CIPHER_SIG || head == PCP_ASYM_CIPHER_ANON) {
/* asymetric mode */
if(useid) {
secret = pcphash_keyexists(ptx, id);
@@ -111,6 +112,9 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
if(secret == NULL)
goto errde3;
+ if(head == PCP_ASYM_CIPHER_ANON)
+ anon = 1;
+
if(head == PCP_ASYM_CIPHER_SIG)
verify = 1;
}
@@ -126,10 +130,10 @@ int pcpdecrypt(char *id, int useid, char *infile, char *outfile, char *passwd, i
}
if(symkey == NULL) {
- dlen = pcp_decrypt_stream(ptx, pin, pout, secret, NULL, verify);
+ dlen = pcp_decrypt_stream(ptx, pin, pout, secret, NULL, verify, anon);
}
else {
- dlen = pcp_decrypt_stream(ptx, pin, pout, NULL, symkey, verify);
+ dlen = pcp_decrypt_stream(ptx, pin, pout, NULL, symkey, verify, 0);
ucfree(symkey, 64);
}
@@ -154,7 +158,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 armor) {
+int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt, int armor, int anon) {
FILE *in = NULL;
FILE *out = NULL;
pcp_pubkey_t *pubhash = NULL; /* FIXME: add free() */
@@ -234,32 +238,33 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
if(self != 1) {
/* we're using a random secret keypair on our side */
-#ifdef PCP_ASYM_ADD_SENDER_PUB
- secret = pcpkey_new();
-#else
- secret = pcp_find_primary_secret();
- if(secret == NULL) {
- fatal(ptx, "Could not find a secret key in vault %s!\n", id, vault->filename);
- goto erren2;
+ if(anon) {
+ secret = pcpkey_new();
}
-
- if(secret->secret[0] == 0) {
- /* encrypted, decrypt it */
- char *passphrase;
- if(passwd == NULL) {
- pcp_readpass(&passphrase,
- "Enter passphrase to decrypt your secret key", NULL, 1);
- }
- else {
- passphrase = ucmalloc(strlen(passwd)+1);
- strncpy(passphrase, passwd, strlen(passwd)+1);
- }
- secret = pcpkey_decrypt(ptx, secret, passphrase);
- ucfree(passphrase, strlen(passwd)+1);
- if(secret == NULL)
+ else {
+ secret = pcp_find_primary_secret();
+ if(secret == NULL) {
+ fatal(ptx, "Could not find a secret key in vault %s!\n", id, vault->filename);
goto erren2;
+ }
+
+ if(secret->secret[0] == 0) {
+ /* encrypted, decrypt it */
+ char *passphrase;
+ if(passwd == NULL) {
+ pcp_readpass(&passphrase,
+ "Enter passphrase to decrypt your secret key", NULL, 1);
+ }
+ else {
+ passphrase = ucmalloc(strlen(passwd)+1);
+ strncpy(passphrase, passwd, strlen(passwd)+1);
+ }
+ secret = pcpkey_decrypt(ptx, secret, passphrase);
+ ucfree(passphrase, strlen(passwd)+1);
+ if(secret == NULL)
+ goto erren2;
+ }
}
-#endif
}
if(infile == NULL)
@@ -295,7 +300,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
ucfree(symkey, 64);
}
else {
- clen = pcp_encrypt_stream(ptx, pin, pout, secret, pubhash, signcrypt);
+ clen = pcp_encrypt_stream(ptx, pin, pout, secret, pubhash, signcrypt, anon);
}
if(armor == 1) {
diff --git a/src/encryption.h b/src/encryption.h
index 7856269..d1377cc 100644
--- a/src/encryption.h
+++ b/src/encryption.h
@@ -39,6 +39,6 @@
#include "context.h"
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 armor);
+int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *recipient, int signcrypt, int armor, int anon);
#endif /* _HAVE_ENCRYPTION_H */
diff --git a/src/pcp.c b/src/pcp.c
index 6f05205..37d16cc 100644
--- a/src/pcp.c
+++ b/src/pcp.c
@@ -46,7 +46,7 @@ char *default_vault() {
}
int main (int argc, char **argv) {
- int opt, mode, usevault, useid, userec, lo, armor, detach, signcrypt, exportformat;
+ int opt, mode, usevault, useid, userec, lo, armor, detach, signcrypt, exportformat, anon;
char *vaultfile = default_vault();
char *outfile = NULL;
char *infile = NULL;
@@ -68,6 +68,7 @@ int main (int argc, char **argv) {
armor = 0;
detach = 0;
signcrypt = 0;
+ anon = 0;
exportformat = EXP_FORMAT_NATIVE;
ptx = ptx_new();
@@ -100,6 +101,7 @@ int main (int argc, char **argv) {
{ "encrypt", no_argument, NULL, 'e' },
{ "encrypt-me", no_argument, NULL, 'm' },
{ "decrypt", no_argument, NULL, 'd' },
+ { "anonymous", no_argument, NULL, 'A' },
/* encoding */
{ "z85-encode", no_argument, NULL, 'z' },
@@ -120,7 +122,7 @@ int main (int argc, char **argv) {
{ NULL, 0, NULL, 0 }
};
- while ((opt = getopt_long(argc, argv, "klLV:vdehsO:i:I:pSPRtEx:DzaZr:gcymf:b1F:0K",
+ while ((opt = getopt_long(argc, argv, "klLV:vdehsO:i:I:pSPRtEx:DzaZr:gcymf:b1F:0KA",
longopts, NULL)) != -1) {
switch (opt) {
@@ -185,6 +187,9 @@ int main (int argc, char **argv) {
case 'Z':
armor = 2;
break;
+ case 'A':
+ anon = 1;
+ break;
case 'F':
if(strncmp(optarg, "pbp", 3) == 0) {
exportformat = EXP_FORMAT_PBP;
@@ -475,11 +480,11 @@ int main (int argc, char **argv) {
if(useid == 1 && userec == 0) {
/* one dst, FIXME: make id a list as well */
id = pcp_normalize_id(keyid);
- pcpencrypt(id, infile, outfile, xpass, NULL, signcrypt, armor);
+ pcpencrypt(id, infile, outfile, xpass, NULL, signcrypt, armor, anon);
}
else if(useid == 0 && userec == 1) {
/* multiple dst */
- pcpencrypt(NULL, infile, outfile, xpass, recipient, signcrypt, armor);
+ pcpencrypt(NULL, infile, outfile, xpass, recipient, signcrypt, armor, anon);
}
else {
/* -i and -r specified */
@@ -547,7 +552,7 @@ int main (int argc, char **argv) {
break;
case PCP_MODE_ENCRYPT_ME:
- pcpencrypt(NULL, infile, outfile, xpass, NULL, 0, armor);
+ pcpencrypt(NULL, infile, outfile, xpass, NULL, 0, armor, 0);
break;
case PCP_MODE_TEXT:
diff --git a/tests/sample.c b/tests/sample.c
index 0ccdb60..db42b3d 100644
--- a/tests/sample.c
+++ b/tests/sample.c
@@ -34,7 +34,7 @@ int main() {
/* actually encrypt the message, don't sign it
Alice is the sender, Bob is the recipient */
- pcp_encrypt_stream(ptx, clear_in, crypt_out, alice, pubhash, 0);
+ pcp_encrypt_stream(ptx, clear_in, crypt_out, alice, pubhash, 0, 0);
/* now, print the encrypted result */
fprintf(stderr, "Alice encrypted %"FMT_SIZE_T" bytes for Bob:\n", (SIZE_T_CAST)strlen(message));
@@ -51,7 +51,7 @@ int main() {
pcphash_add(ptx, alicepub, alicepub->type);
/* try to decrypt the message */
- if(pcp_decrypt_stream(ptx, crypt_out, clear_out, bob, NULL, 0) == 0)
+ if(pcp_decrypt_stream(ptx, crypt_out, clear_out, bob, NULL, 0, 0) == 0)
fatals_ifany(ptx);
else {
/* and finally print out the decrypted message */
diff --git a/tests/unittests.cfg b/tests/unittests.cfg
index 3e03a95..913c96d 100644
--- a/tests/unittests.cfg
+++ b/tests/unittests.cfg
@@ -182,6 +182,7 @@ temporarily disabled
expect = /encrypted/
*/
+
#
# encryption tests
@@ -202,12 +203,23 @@ temporarily disabled
expect = /${idbobby} - Bobby/
+
+ cmd = $pcp -V va -e -A -i ${idbobby} -I testmessage -O testencryptedanon -x a
+ expect = /${idbobby} - Bobby/
+
+
# bobbys part
cmd = $pcp -V vb -K -I key-bobby-sec -x b
expect = /${idbobby}/
+
+ # decrypt anon, without knowing alicias key
+ cmd = $pcp -V vb -d -O testdecryptedanon -I testencryptedanon -x b
+ expect = /successfully/
+
+
cmd = $pcp -V vb -K -I key-alicia-pub
expect = /${idalicia}/
@@ -272,7 +284,7 @@ temporarily disabled
cmd = echo HALLO | $pcp -V vcl -e -O testencrypted -i ${idbobby}
- expect = /success/
+ expect = /Bobby/