added anonymous sender key (-A) support

This commit is contained in:
git@daemon.de
2014-08-11 15:45:47 +02:00
parent e022a9e842
commit 298e6b1469
11 changed files with 131 additions and 69 deletions

View File

@@ -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.

View File

@@ -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);

View File

@@ -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.

View File

@@ -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

View File

@@ -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))

View File

@@ -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
if(anon) {
/* step 2, sender's pubkey */
cur_bufsize = ps_read(in, &in_buf, crypto_box_PUBLICKEYBYTES);
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,6 +248,23 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
}
recmatch = 0;
if(anon) {
/* anonymous sender */
byte *recipient;
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);
@@ -258,6 +276,8 @@ size_t pcp_decrypt_stream(PCPCTX *ptx, Pcpstream *in, Pcpstream* out, pcp_key_t
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
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;
#endif
}
/* step 3, len recipients, big endian */
lenrec = recipient_count;

View File

@@ -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,9 +238,10 @@ 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
if(anon) {
secret = pcpkey_new();
#else
}
else {
secret = pcp_find_primary_secret();
if(secret == NULL) {
fatal(ptx, "Could not find a secret key in vault %s!\n", id, vault->filename);
@@ -259,7 +264,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
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) {

View File

@@ -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 */

View File

@@ -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:

View File

@@ -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 */

View File

@@ -182,6 +182,7 @@ temporarily disabled
expect = /encrypted/
</test>
*/
#
# encryption tests
<test check-crypto-alicia-2-bobby>
@@ -202,12 +203,23 @@ temporarily disabled
expect = /${idbobby} - Bobby/
</test>
<test check-crypto-alicia-encrypt-anonymous>
cmd = $pcp -V va -e -A -i ${idbobby} -I testmessage -O testencryptedanon -x a
expect = /${idbobby} - Bobby/
</test>
# bobbys part
<test check-crypto-bobby-import-secret>
cmd = $pcp -V vb -K -I key-bobby-sec -x b
expect = /${idbobby}/
</test>
<test check-crypto-bobby-decrypt-anonymous>
# decrypt anon, without knowing alicias key
cmd = $pcp -V vb -d -O testdecryptedanon -I testencryptedanon -x b
expect = /successfully/
</test>
<test check-crypto-alicia-import-alicias-key>
cmd = $pcp -V vb -K -I key-alicia-pub
expect = /${idalicia}/
@@ -272,7 +284,7 @@ temporarily disabled
<test check-vcl-crypto-unencrypted-secret-message>
cmd = echo HALLO | $pcp -V vcl -e -O testencrypted -i ${idbobby}
expect = /success/
expect = /Bobby/
</test>
<test check-vcl-crypto-unencrypted-secret-read>