(re-)added detached signature support, now with 32k-blockwise reading of files, enabled with -a.

This commit is contained in:
TLINDEN
2014-01-26 16:02:47 +01:00
parent 52a7509fe2
commit 78987a1d27
10 changed files with 218 additions and 42 deletions

View File

@@ -22,6 +22,12 @@
Armored signatures are calculated the same way but
output follows the pgp scheme instead.
Detached signatures are still supported as before,
for the user everything with them is as known, but
the commandline option -a (--detach) have to be
applied. Internally, however, inputs will be read in
32k blockwise as well. Detached signatures are now
z85 encoded always.
0.1.5 Fixed a segmentation fault when using pcp1 -t on a
public key. I added a double free() there by purpose

View File

@@ -53,6 +53,9 @@ unsigned char * pcp_ed_verify(unsigned char *signature, size_t siglen, pcp_pubke
sig only to the output */
size_t pcp_ed_sign_buffered(FILE *in, FILE *out, pcp_key_t *s, int z85);
unsigned char *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p);
pcp_pubkey_t *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p);
size_t pcp_ed_detachsign_buffered(FILE *in, FILE *out, pcp_key_t *s);
pcp_pubkey_t *pcp_ed_detachverify_buffered(FILE *in, FILE *sigfd, pcp_pubkey_t *p);
#endif // _HAVE_PCP_ED_H

View File

@@ -456,6 +456,4 @@ size_t pcp_decrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey) {
fclose(out);
return out_size;
}

View File

@@ -99,7 +99,7 @@ size_t pcp_ed_sign_buffered(FILE *in, FILE *out, pcp_key_t *s, int z85) {
return outsize;
}
unsigned char *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p) {
pcp_pubkey_t *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p) {
unsigned char in_buf[PCP_BLOCK_SIZE/2];
unsigned char in_next[PCP_BLOCK_SIZE/2];
unsigned char in_full[PCP_BLOCK_SIZE];
@@ -236,8 +236,6 @@ unsigned char *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p) {
if(z85block == NULL)
goto errvb1;
fprintf(stderr, "<%s>\n", z85block);
size_t dstlen;
unsigned char *z85decoded = pcp_z85_decode(z85block, &dstlen);
if(dstlen != mlen) {
@@ -272,7 +270,7 @@ unsigned char *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p) {
return NULL;
}
return verifiedhash;
return p;
errvb1:
@@ -280,3 +278,139 @@ unsigned char *pcp_ed_verify_buffered(FILE *in, pcp_pubkey_t *p) {
return NULL;
}
size_t pcp_ed_detachsign_buffered(FILE *in, FILE *out, pcp_key_t *s) {
unsigned char in_buf[PCP_BLOCK_SIZE];
size_t cur_bufsize = 0;
size_t outsize = 0;
crypto_generichash_state *st = ucmalloc(sizeof(crypto_generichash_state));
unsigned char hash[crypto_generichash_BYTES_MAX];
crypto_generichash_init(st, NULL, 0, 0);
while(!feof(in)) {
cur_bufsize = fread(&in_buf, 1, PCP_BLOCK_SIZE, in);
if(cur_bufsize <= 0)
break;
outsize += cur_bufsize;
crypto_generichash_update(st, in_buf, cur_bufsize);
}
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
unsigned char *signature = pcp_ed_sign(hash, crypto_generichash_BYTES_MAX, s);
size_t mlen = + crypto_sign_BYTES + crypto_generichash_BYTES_MAX;
fprintf(out, "\n%s\n Version: PCP v%d.%d.%d\n\n",
PCP_SIG_START, PCP_VERSION_MAJOR, PCP_VERSION_MINOR, PCP_VERSION_PATCH);
size_t zlen;
char *z85encoded = pcp_z85_encode((unsigned char*)signature, mlen, &zlen);
fprintf(out, "%s\n%s\n", z85encoded, PCP_SIG_END);
if(fileno(in) != 0)
fclose(in);
if(fileno(out) != 1)
fclose(out);
free(st);
return outsize;
}
pcp_pubkey_t *pcp_ed_detachverify_buffered(FILE *in, FILE *sigfd, pcp_pubkey_t *p) {
unsigned char in_buf[PCP_BLOCK_SIZE];
size_t cur_bufsize = 0;
size_t outsize = 0;
crypto_generichash_state *st = ucmalloc(sizeof(crypto_generichash_state));
unsigned char hash[crypto_generichash_BYTES_MAX];
size_t mlen = + crypto_sign_BYTES + crypto_generichash_BYTES_MAX;
crypto_generichash_init(st, NULL, 0, 0);
while(!feof(in)) {
cur_bufsize = fread(&in_buf, 1, PCP_BLOCK_SIZE, in);
if(cur_bufsize <= 0)
break;
outsize += cur_bufsize;
crypto_generichash_update(st, in_buf, cur_bufsize);
}
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
// read the sig
unsigned char *sig = NULL;
size_t inputBufSize = 0;
unsigned char byte[1];
while(!feof(sigfd)) {
if(!fread(&byte, 1, 1, sigfd))
break;
unsigned char *tmp = realloc(sig, inputBufSize + 1);
sig = tmp;
memmove(&sig[inputBufSize], byte, 1);
inputBufSize ++;
}
fclose(sigfd);
if(sig == NULL) {
fatal("Invalid detached signature\n");
goto errdea1;
}
char *z85block = pcp_readz85string(sig, inputBufSize);
if(z85block == NULL)
goto errdea2;
size_t clen;
unsigned char *sighash = pcp_z85_decode(z85block, &clen);
if(sighash == NULL)
goto errdea3;
if(clen != mlen) {
fatal("z85 decoded signature didn't result in a proper signed hash(got: %ld, expected: %ld)\n", clen, mlen);
goto errdea4;
}
unsigned char *verifiedhash = NULL;
if(p == NULL) {
pcphash_iteratepub(p) {
verifiedhash = pcp_ed_verify(sighash, mlen, p);
if(verifiedhash != NULL)
break;
}
}
else {
verifiedhash = pcp_ed_verify(sighash, mlen, p);
}
if(verifiedhash == NULL)
goto errdea4;
if(memcmp(verifiedhash, hash, crypto_generichash_BYTES_MAX) != 0) {
// sig verified, but the hash doesn't
fatal("signed hash doesn't match actual hash of signed file content\n");
goto errdea5;
}
free(verifiedhash);
free(sighash);
free(z85block);
free(sig);
return p;
errdea5:
free(verifiedhash);
errdea4:
free(sighash);
errdea3:
free(z85block);
errdea2:
free(sig);
errdea1:
return NULL;
}

View File

@@ -259,7 +259,7 @@ int pcpencrypt(char *id, char *infile, char *outfile, char *passwd, plist_t *rec
size_t clen = 0;
if(self == 1)
pcp_encrypt_file_sym(in, out, symkey, 0);
clen = pcp_encrypt_file_sym(in, out, symkey, 0);
else
clen = pcp_encrypt_file(in, out, secret, pubhash);

View File

@@ -44,10 +44,11 @@ char *default_vault() {
}
int main (int argc, char **argv) {
int opt, mode, usevault, useid, userec, lo, armor;
int opt, mode, usevault, useid, userec, lo, armor, detach;
char *vaultfile = default_vault();
char *outfile = NULL;
char *infile = NULL;
char *sigfile = NULL;
char *keyid = NULL;
char *id = NULL;
char *xpass = NULL;
@@ -63,6 +64,7 @@ int main (int argc, char **argv) {
userec = 0;
lo = 0;
armor = 0;
detach = 0;
static struct option longopts[] = {
// generics
@@ -101,11 +103,12 @@ int main (int argc, char **argv) {
// signing
{ "sign", no_argument, NULL, 'g' },
{ "check-signature", no_argument, NULL, 'c' },
{ "check-signature", required_argument, NULL, 'c' },
{ "detach", no_argument, NULL, 'a' },
{ NULL, 0, NULL, 0 }
};
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gcym",
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gc:yma",
longopts, NULL)) != -1) {
switch (opt) {
@@ -171,12 +174,17 @@ int main (int argc, char **argv) {
case 'Z':
armor = 1;
break;
case 'a':
detach = 1;
break;
case 'g':
mode += PCP_MODE_SIGN;
usevault = 1;
break;
case 'c':
mode += PCP_MODE_VERIFY;
sigfile = ucmalloc(strlen(optarg)+1);
strncpy(sigfile, optarg, strlen(optarg)+1);
usevault = 1;
break;
case 'y':
@@ -372,19 +380,19 @@ int main (int argc, char **argv) {
break;
case PCP_MODE_SIGN:
pcpsign(infile, outfile, xpass, armor);
pcpsign(infile, outfile, xpass, armor, detach);
break;
case PCP_MODE_VERIFY:
if(useid) {
id = pcp_normalize_id(keyid);
if(id != NULL) {
pcpverify(infile, id);
pcpverify(infile, sigfile, id, detach);
free(id);
}
}
else {
pcpverify(infile, NULL);
pcpverify(infile, sigfile, NULL, detach);
}
break;

View File

@@ -23,7 +23,8 @@
#include "signature.h"
#include "defines.h"
int pcpsign(char *infile, char *outfile, char *passwd, int z85) {
int pcpsign(char *infile, char *outfile, char *passwd, int z85, int detach) {
FILE *in = NULL;
FILE *out = NULL;
pcp_key_t *secret = NULL;
@@ -70,7 +71,11 @@ int pcpsign(char *infile, char *outfile, char *passwd, int z85) {
goto errs1;
}
size_t sigsize = pcp_ed_sign_buffered(in, out, secret, z85);
size_t sigsize;
if(detach == 1)
sigsize = pcp_ed_detachsign_buffered(in, out, secret);
else
sigsize = pcp_ed_sign_buffered(in, out, secret, z85);
if(sigsize == 0)
goto errs1;
@@ -83,10 +88,10 @@ int pcpsign(char *infile, char *outfile, char *passwd, int z85) {
return 1;
}
int pcpverify(char *infile, char *id) {
int pcpverify(char *infile, char *sigfile, char *id, int detach) {
FILE *in = NULL;
FILE *sigfd = NULL;
pcp_pubkey_t *pub = NULL;
unsigned char *message = NULL;
if(infile == NULL)
in = stdin;
@@ -97,27 +102,24 @@ int pcpverify(char *infile, char *id) {
}
}
if(sigfile != NULL) {
if((sigfd = fopen(sigfile, "rb")) == NULL) {
fatal("Could not open signature file %s\n", sigfile);
goto errv1;
}
}
if(id != NULL)
HASH_FIND_STR(pcppubkey_hash, id, pub);
if(pub != NULL) {
message = pcp_ed_verify_buffered(in, pub);
if(message != NULL) {
fprintf(stderr, "Signature verified (signed by %s <%s>).\n", pub->owner, pub->mail);
}
}
else {
// put public key as pub, so verify iterates over our keys
message = pcp_ed_verify_buffered(in, pub);
if(message != NULL) {
fprintf(stderr, "Signature verified (signed by %s <%s>).\n", pub->owner, pub->mail);
}
}
if(detach)
pub = pcp_ed_detachverify_buffered(in, sigfd, pub);
else
pub = pcp_ed_verify_buffered(sigfd, pub);
if(pub != NULL)
fprintf(stderr, "Signature verified (signed by %s <%s>).\n", pub->owner, pub->mail);
if(message != NULL) {
free(message);
return 0;
}
errv4:

View File

@@ -32,8 +32,8 @@
#include "uthash.h"
#include "z85.h"
int pcpsign(char *infile, char *outfile, char *passwd, int z85);
int pcpverify(char *infile, char *id);
int pcpsign(char *infile, char *outfile, char *passwd, int z85, int detach);
int pcpverify(char *infile, char *sigfile, char *id, int detach);

View File

@@ -92,11 +92,15 @@ Signature Options:
-I (or from stdin) using your primary
secret key. If -r has been given, a derived
secret key will be used for signing.
-c --check-signature <file> Verify a signature in file <file> against
the file specified with -I (or stdin).
The public key required for this must
exist in your vault file.
-a --detach Write a detached signature file, which doesn't
contain the original content. Output will be
z85 encoded always. To verify, you need to
specify the original file to be verified
against using -I as well (plus -a).
Encoding Options:
-z --z85-encode Encode something to Z85 encoding. Use

View File

@@ -210,13 +210,31 @@ dxmorg@florida.cops.gov
</test>
#
# signature test
<test check-sign-to-bobby>
# signature tests
<test check-sign-detached-to-bobby>
cmd = $pcp -V va -g -I README -O testsig -x a -a
expect-file testsig
</test>
<test check-verify-detached-signature>
cmd = $pcp -V vb -c testsig -I README -i $idalicia -a
expect = /verified/
</test>
<test check-sign-armored-to-bobby>
prepare = rm -f testsig
cmd = $pcp -V va -g -I README -O testsig -x a -z
expect-file testsig
</test>
<test check-verify-armored-signature>
cmd = $pcp -V vb -c testsig -i $idalicia -z
expect = /verified/
</test>
<test check-sign-bin-to-bobby>
prepare = rm -f testsig
cmd = $pcp -V va -g -I README -O testsig -x a
expect-file testsig
</test>
<test check-verify-signature>
cmd = $pcp -V vb -c -I testsig -i $idalicia
<test check-verify-bin-signature>
cmd = $pcp -V vb -c testsig -i $idalicia
expect = /verified/
</test>
@@ -332,12 +350,15 @@ dxmorg@florida.cops.gov
</test>
*/
/*
* Disabled, since z85 standalone mode currently disabled
<test check-if-catch-nokey-behind-z85>
prepare = ./jot 30 | while read ignore; do echo XXXXX; done \
| $pcp -z > testfile-nokey
cmd = $pcp -V $vault -P -I testfile-nokey
expect = /result to a proper sized key/
</test>
*/
<test check-if-sanity-catch-nosecret>
cmd = $pcp -V $vault -S -I bart.pub