mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 03:50:57 +01:00
(re-)added detached signature support, now with 32k-blockwise reading of files, enabled with -a.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -456,6 +456,4 @@ size_t pcp_decrypt_file_sym(FILE *in, FILE* out, unsigned char *symkey) {
|
||||
fclose(out);
|
||||
|
||||
return out_size;
|
||||
|
||||
|
||||
}
|
||||
|
||||
142
libpcp/ed.c
142
libpcp/ed.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
20
src/pcp.c
20
src/pcp.c
@@ -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;
|
||||
|
||||
|
||||
@@ -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(message != NULL) {
|
||||
free(message);
|
||||
return 0;
|
||||
}
|
||||
if(pub != NULL)
|
||||
fprintf(stderr, "Signature verified (signed by %s <%s>).\n", pub->owner, pub->mail);
|
||||
|
||||
|
||||
errv4:
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user