added signature support (doesn't work yet)

This commit is contained in:
git@daemon.de
2013-11-08 09:40:51 +01:00
parent a2c55c96b4
commit e6733e5e56
15 changed files with 497 additions and 39 deletions

View File

@@ -14,6 +14,7 @@ PCPEXPORT = pcp.h \
pcp/vault.h \
pcp/version.h \
pcp/z85.h \
pcp/zmq_z85.h
pcp/zmq_z85.h \
pcp/ed.h
nobase_include_HEADERS = $(PCPEXPORT)

View File

@@ -233,7 +233,8 @@ PCPEXPORT = pcp.h \
pcp/vault.h \
pcp/version.h \
pcp/z85.h \
pcp/zmq_z85.h
pcp/zmq_z85.h \
pcp/ed.h
nobase_include_HEADERS = $(PCPEXPORT)
all: all-am

View File

@@ -8,6 +8,7 @@ extern "C" {
#include "pcp/crypto.h"
#include "pcp/defines.h"
#include "pcp/digital_crc32.h"
#include "pcp/ed.h"
#include "pcp/getpass.h"
#include "pcp/jenhash.h"
#include "pcp/key.h"

View File

@@ -40,6 +40,9 @@ typedef unsigned int qbyte; // Quad byte = 32 bits
#define PCP_ZFILE_HEADER "----- BEGIN Z85 ENCODED FILE -----"
#define PCP_ZFILE_FOOTER "------ END Z85 ENCODED FILE ------"
#define PCP_SIG_HEADER "----- BEGIN PCP SIGNATURE FILE -----"
#define PCP_SIG_FOOTER "------ END PCP SIGNATURE FILE ------"
#define PCP_ME "Pretty Curved Privacy"
#define PCP_KEY_VERSION 0x00000001U
@@ -59,6 +62,9 @@ typedef unsigned int qbyte; // Quad byte = 32 bits
#define PCP_VAULT_ID 0xC4
#define PCP_VAULT_VERSION 0x01
// sigs
#define PCP_SIG_VERSION 0x01
char *PCP_ERR;
byte PCP_ERRSET;
int PCP_EXIT;

62
include/pcp/ed.h Normal file
View File

@@ -0,0 +1,62 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_PCP_ED_H
#define _HAVE_PCP_ED_H
#ifdef __cplusplus
extern "C" {
#endif
#include <sodium.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include "defines.h"
#include "platform.h"
#include "mem.h"
#include "key.h"
struct _pcp_sig_t {
char id[17];
long ctime;
uint32_t version;
byte edsig[crypto_hash_sha256_BYTES + crypto_sign_BYTES];
};
typedef struct _pcp_sig_t pcp_sig_t;
int pcp_ed_verify(unsigned char *input, size_t inputlen, pcp_sig_t *sig, pcp_pubkey_t *p);
pcp_sig_t *pcp_ed_sign(unsigned char *message,
size_t messagesize, pcp_key_t *s);
pcp_sig_t *sig2native(pcp_sig_t *k);
pcp_sig_t *sig2be(pcp_sig_t *k);
pcp_sig_t *pcp_ed_newsig(unsigned char *hash, char *id);
#ifdef __cplusplus
}
#endif
#endif // _HAVE_PCP_ED_H

View File

@@ -25,6 +25,6 @@ lib_LTLIBRARIES = libpcp1.la
libpcp1_la_SOURCES = mac.c mem.c pad.c version.c \
z85.c zmq_z85.c key.c randomart.c \
vault.c fatal.c jenhash.c digital_crc32.c \
crypto.c
crypto.c ed.c
include_HEADERS = ../include/pcp.h

View File

@@ -99,7 +99,7 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libpcp1_la_LIBADD =
am_libpcp1_la_OBJECTS = mac.lo mem.lo pad.lo version.lo z85.lo \
zmq_z85.lo key.lo randomart.lo vault.lo fatal.lo jenhash.lo \
digital_crc32.lo crypto.lo
digital_crc32.lo crypto.lo ed.lo
libpcp1_la_OBJECTS = $(am_libpcp1_la_OBJECTS)
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
@@ -264,7 +264,7 @@ lib_LTLIBRARIES = libpcp1.la
libpcp1_la_SOURCES = mac.c mem.c pad.c version.c \
z85.c zmq_z85.c key.c randomart.c \
vault.c fatal.c jenhash.c digital_crc32.c \
crypto.c
crypto.c ed.c
include_HEADERS = ../include/pcp.h
all: config.h
@@ -362,6 +362,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crypto.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/digital_crc32.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ed.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fatal.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jenhash.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Plo@am__quote@

86
libpcp/ed.c Normal file
View File

@@ -0,0 +1,86 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#include "ed.h"
int pcp_ed_verify(unsigned char *input, size_t inputlen, pcp_sig_t *sig, pcp_pubkey_t *p) {
unsigned char *hash = ucmalloc(crypto_hash_sha256_BYTES + crypto_sign_BYTES); // from sig
unsigned char *check = ucmalloc(crypto_hash_sha256_BYTES); // from file
size_t mlen = 0;
if(crypto_sign_open(hash, &mlen, sig->edsig, crypto_hash_sha256_BYTES + crypto_sign_BYTES, p->public) != 0) {
fatal("Failed to open the signature using the public key 0x%s!\n", p->id);
goto errve1;
}
crypto_hash_sha256(check, input, inputlen);
if(memcmp(check, hash, crypto_hash_sha256_BYTES) != 0) {
fatal("Failed to verify the signature, hashes differ!\n");
goto errve1;
}
free(hash);
free(check);
return 0;
errve1:
free(hash);
free(check);
return 1;
}
pcp_sig_t *pcp_ed_sign(unsigned char *message, size_t messagesize, pcp_key_t *s) {
unsigned char *hash = ucmalloc(crypto_hash_sha256_BYTES);
size_t slen = crypto_hash_sha256_BYTES + crypto_sign_BYTES;
unsigned char *signature = ucmalloc(slen);
crypto_hash_sha256(hash, message, messagesize);
crypto_sign(signature, &slen, hash, crypto_hash_sha256_BYTES, s->secret);
pcp_sig_t *sig = pcp_ed_newsig(signature, s->id);
return sig;
}
pcp_sig_t *pcp_ed_newsig(unsigned char *hash, char *id) {
pcp_sig_t *sig = ucmalloc(sizeof(pcp_sig_t));
sig->version = PCP_SIG_VERSION;
sig->ctime = (long)time(0);
memcpy(sig->edsig, hash, crypto_hash_sha256_BYTES + crypto_sign_BYTES);
memcpy(sig->id, id, 17);
return sig;
}
pcp_sig_t *sig2native(pcp_sig_t *s) {
s->version = be32toh(s->version);
s->ctime = be64toh(s->ctime);
return s;
}
pcp_sig_t *sig2be(pcp_sig_t *s) {
s->version = htobe32(s->version);
s->ctime = htobe64(s->ctime);
return s;
}

View File

@@ -124,7 +124,7 @@
.\" ========================================================================
.\"
.IX Title "PCP1 1"
.TH PCP1 1 "2013-11-07" "PCP 0.1.2" "USER CONTRIBUTED DOCUMENTATION"
.TH PCP1 1 "2013-11-08" "PCP 0.1.2" "USER CONTRIBUTED DOCUMENTATION"
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l

View File

@@ -25,5 +25,6 @@ AM_CFLAGS = -I../include/pcp -Wall -g
bin_PROGRAMS = pcp1
pcp1_LDADD = ../libpcp/.libs/libpcp1.a
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c readpass.c encryption.c z85util.c
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c readpass.c \
encryption.c z85util.c signature.c

View File

@@ -90,7 +90,8 @@ CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
am_pcp1_OBJECTS = pcp.$(OBJEXT) keymgmt.$(OBJEXT) keyprint.$(OBJEXT) \
readpass.$(OBJEXT) encryption.$(OBJEXT) z85util.$(OBJEXT)
readpass.$(OBJEXT) encryption.$(OBJEXT) z85util.$(OBJEXT) \
signature.$(OBJEXT)
pcp1_OBJECTS = $(am_pcp1_OBJECTS)
pcp1_DEPENDENCIES = ../libpcp/.libs/libpcp1.a
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/libpcp
@@ -231,7 +232,9 @@ top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CFLAGS = -I../include/pcp -Wall -g
pcp1_LDADD = ../libpcp/.libs/libpcp1.a
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c readpass.c encryption.c z85util.c
pcp1_SOURCES = pcp.c keymgmt.c keyprint.c readpass.c \
encryption.c z85util.c signature.c
all: all-am
.SUFFIXES:
@@ -327,6 +330,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keyprint.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pcp.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readpass.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signature.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/z85util.Po@am__quote@
.c.o:

View File

@@ -44,10 +44,11 @@ char *default_vault() {
}
int main (int argc, char **argv) {
int opt, mode, usevault, useid, userec;
int opt, mode, usevault, useid, userec, lo;
char *vaultfile = default_vault();
char *outfile = NULL;
char *infile = NULL;
char *sigfile = NULL;
char *keyid = NULL;
char *id = NULL;
char *xpass = NULL;
@@ -64,43 +65,54 @@ int main (int argc, char **argv) {
static struct option longopts[] = {
// generics
{ "vault", required_argument, NULL, 'V' },
{ "outfile", required_argument, NULL, 'O' },
{ "infile", required_argument, NULL, 'I' },
{ "keyid", required_argument, NULL, 'i' },
{ "text", required_argument, NULL, 't' },
{ "xpass", required_argument, NULL, 'x' },
{ "recipient", required_argument, NULL, 'r' },
{ "vault", required_argument, NULL, 'V' },
{ "outfile", required_argument, NULL, 'O' },
{ "infile", required_argument, NULL, 'I' },
{ "keyid", required_argument, NULL, 'i' },
{ "text", required_argument, NULL, 't' },
{ "xpass", required_argument, NULL, 'x' },
{ "recipient", required_argument, NULL, 'r' },
// key management
{ "keygen", no_argument, NULL, 'k' },
{ "listkeys", no_argument, NULL, 'l' },
{ "export-secret", no_argument, NULL, 's' },
{ "export-public", no_argument, NULL, 'p' },
{ "import-secret", no_argument, NULL, 'S' },
{ "import-public", no_argument, NULL, 'P' },
{ "remove-key", no_argument, NULL, 'R' },
{ "edit-key", no_argument, NULL, 'E' },
{ "keygen", no_argument, NULL, 'k' },
{ "listkeys", no_argument, NULL, 'l' },
{ "export-secret", no_argument, NULL, 's' },
{ "export-public", no_argument, NULL, 'p' },
{ "import-secret", no_argument, NULL, 'S' },
{ "import-public", no_argument, NULL, 'P' },
{ "remove-key", no_argument, NULL, 'R' },
{ "edit-key", no_argument, NULL, 'E' },
// crypto
{ "encrypt", no_argument, NULL, 'e' },
{ "decrypt", no_argument, NULL, 'd' },
{ "encrypt", no_argument, NULL, 'e' },
{ "decrypt", no_argument, NULL, 'd' },
// encoding
{ "z85-encode", no_argument, NULL, 'z' },
{ "z85-decode", no_argument, NULL, 'Z' },
{ "z85-encode", no_argument, NULL, 'z' },
{ "z85-decode", no_argument, NULL, 'Z' },
// globals
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'f' },
{ "debug", no_argument, NULL, 'D' },
{ NULL, 0, NULL, 0 }
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'f' },
{ "debug", no_argument, NULL, 'D' },
// signing
{ "sign", no_argument, NULL, 'g' },
{ "check-signature", required_argument, NULL, 'c' },
{ NULL, 0, NULL, 0 }
};
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:",
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gc:",
longopts, NULL)) != -1) {
switch (opt) {
case 0:
switch(lo) {
case 's':
printf("sign\n");
break;
}
break;
case 'k':
mode += PCP_MODE_KEYGEN;
@@ -153,7 +165,16 @@ int main (int argc, char **argv) {
case 'Z':
mode += PCP_MODE_ZDECODE;
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 'V':
strncpy(vaultfile, optarg, 1024);
@@ -348,6 +369,16 @@ int main (int argc, char **argv) {
free(xpass);
break;
case PCP_MODE_SIGN:
pcpsign(infile, outfile, xpass);
break;
case PCP_MODE_VERIFY:
pcpverify(infile, sigfile);
break;
default:
//
goto ELSEMODE;

View File

@@ -44,6 +44,7 @@
#include "keymgmt.h"
#include "usage.h"
#include "encryption.h"
#include "signature.h"
// operation modi
// perl -e '$x=0; while ($x<100000) { $x++; $x *= 1.7; printf "0x%08X: %d\n", $x, $x }'
@@ -60,10 +61,9 @@
#define PCP_MODE_DECRYPT 0x0000033D
#define PCP_MODE_ZENCODE 0x00000584
#define PCP_MODE_ZDECODE 0x00000962
#define PCP_MODE_SIGN 0x00000FF6
#define PCP_MODE_VERIFY 0x00001B25
/*
0x00000962
0x00000FF6
0x00001B25
0x00002E27
0x00004E77

224
src/signature.c Normal file
View File

@@ -0,0 +1,224 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#include "signature.h"
#include "defines.h"
int pcpsign(char *infile, char *outfile, char *passwd) {
FILE *in = NULL;
FILE *out = NULL;
pcp_key_t *secret = NULL;
secret = pcp_find_primary_secret();
if(secret == NULL) {
fatal("Could not find a secret key in vault %s!\n", vault->filename);
goto errs1;
}
if(infile == NULL)
in = stdin;
else {
if((in = fopen(infile, "rb")) == NULL) {
fatal("Could not open input file %s\n", infile);
goto errs2;
}
}
if(outfile == NULL)
out = stdout;
else {
if((out = fopen(outfile, "wb+")) == NULL) {
fatal("Could not open output file %s\n", outfile);
goto errs2;
}
}
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(secret, passphrase);
if(secret == NULL)
goto errs3;
}
unsigned char *input = NULL;
size_t inputBufSize = 0;
unsigned char byte[1];
while(!feof(in)) {
if(!fread(&byte, 1, 1, in))
break;
unsigned char *tmp = realloc(input, inputBufSize + 1);
input = tmp;
memmove(&input[inputBufSize], byte, 1);
inputBufSize ++;
}
fclose(in);
if(inputBufSize == 0) {
fatal("Input file is empty!\n");
goto errs4;
}
size_t zlen;
pcp_sig_t *signature = pcp_ed_sign(input, inputBufSize, secret);
if(signature == NULL)
goto errs5;
sig2be(signature);
char *encoded = pcp_z85_encode((unsigned char *)signature, sizeof(pcp_sig_t), &zlen);
if(encoded == NULL)
goto errs6;
fprintf(out, "%s\n%s\n%s\n", PCP_SIG_HEADER, encoded, PCP_SIG_FOOTER);
if(ferror(out) != 0) {
fatal("Failed to write encrypted output!\n");
goto errs7;
}
fprintf(stderr, "Signed %d bytes successfully\n",
(int)inputBufSize);
fclose(out);
free(encoded);
free(signature);
return 0;
errs7:
free(encoded);
errs6:
free(signature);
errs5:
errs4:
free(input);
errs3:
errs2:
errs1:
return 1;
}
int pcpverify(char *infile, char *sigfile) {
FILE *in = NULL;
FILE *sigin = NULL;
pcp_pubkey_t *public = NULL;
if(infile == NULL)
in = stdin;
else {
if((in = fopen(infile, "rb")) == NULL) {
fatal("Could not open input file %s\n", infile);
goto errv1;
}
}
if((sigin = fopen(sigfile, "rb")) == NULL) {
fatal("Could not open signature file %s\n", sigfile);
goto errv1;
}
char *encoded = pcp_readz85file(sigin);
if(encoded == NULL)
goto errv1;
size_t clen;
unsigned char *decoded = pcp_z85_decode((char *)encoded, &clen);
if(decoded == NULL)
goto errv2;
if(clen != sizeof(pcp_sig_t)) {
fatal("Error: decoded signature file didn't result to a proper sized sig! (got %d bytes)\n", clen);
goto errv2;
}
pcp_sig_t *sig = (pcp_sig_t *)decoded;
sig2native(sig);
HASH_FIND_STR(pcppubkey_hash, sig->id, public);
if(public == NULL) {
fatal("Could not find a usable public key in vault %s!\n",
vault->filename);
goto errv3;
}
unsigned char *input = NULL;
size_t inputBufSize = 0;
unsigned char byte[1];
while(!feof(in)) {
if(!fread(&byte, 1, 1, in))
break;
unsigned char *tmp = realloc(input, inputBufSize + 1);
input = tmp;
memmove(&input[inputBufSize], byte, 1);
inputBufSize ++;
}
fclose(in);
if(inputBufSize == 0) {
fatal("Input file is empty!\n");
goto errv4;
}
if(pcp_ed_verify(input, inputBufSize, sig, public) == 0) {
fprintf(stderr, "Signature verified.\n");
}
free(decoded);
free(encoded);
free(sig);
free(input);
return 0;
errv4:
free(input);
errv3:
free(decoded);
free(sig);
errv2:
// free(encoded); why???
errv1:
return 1;
}

40
src/signature.h Normal file
View File

@@ -0,0 +1,40 @@
/*
This file is part of Pretty Curved Privacy (pcp1).
Copyright (C) 2013 T.Linden.
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact me by mail: <tlinden AT cpan DOT org>.
*/
#ifndef _HAVE_SIGNATURE_H
#define _HAVE_SIGNATURE_H
#include <stdio.h>
#include <string.h>
#include "defines.h"
#include "key.h"
#include "ed.h"
#include "pcp.h"
#include "uthash.h"
#include "z85.h"
int pcpsign(char *infile, char *outfile, char *passwd);
int pcpverify(char *infile, char *sigfile);
#endif // _HAVE_SIGNATURE_H