mirror of
https://codeberg.org/scip/pcp.git
synced 2025-12-17 12:00:56 +01:00
continue new pk-expoert format
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2014 T.v.Dein.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -69,7 +69,10 @@ void buffer_resize(Buffer *b, size_t len);
|
|||||||
/* get some chunk of data from the buffer, starting from offset til len,
|
/* get some chunk of data from the buffer, starting from offset til len,
|
||||||
it doesn't allocate the returned data (void *buf, the 2nd argument).
|
it doesn't allocate the returned data (void *buf, the 2nd argument).
|
||||||
*/
|
*/
|
||||||
size_t buffer_get(Buffer *b, void *buf, size_t len);
|
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len);
|
||||||
|
|
||||||
|
/* return the whole buffer contents */
|
||||||
|
unsigned char *buffer_get(Buffer *b);
|
||||||
|
|
||||||
/* same as buffer_get() but fetch some data chunk from somewhere
|
/* same as buffer_get() but fetch some data chunk from somewhere
|
||||||
in the middle of the buffer */
|
in the middle of the buffer */
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2014 T.v.Dein.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -38,7 +38,6 @@
|
|||||||
#include "uthash.h"
|
#include "uthash.h"
|
||||||
#include "jenhash.h"
|
#include "jenhash.h"
|
||||||
#include "scrypt.h"
|
#include "scrypt.h"
|
||||||
#include "buffer.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PCP private key structure. Most fields are self explanatory.
|
PCP private key structure. Most fields are self explanatory.
|
||||||
@@ -143,75 +142,6 @@ typedef struct _pcp_rec_t pcp_rec_t;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* RFC4880 alike public key export with some simplifications:
|
|
||||||
|
|
||||||
In sig subpackets we're using fixed sized fields instead
|
|
||||||
of the mess they use in rfc4880. Sorry. We use only these types:
|
|
||||||
|
|
||||||
2 = Signature Creation Time (4 byte)
|
|
||||||
3 = Signature Expiration Time (4 byte)
|
|
||||||
9 = Key Expiration Time (4 bytes)
|
|
||||||
20 = Notation Data (4 byte flags, N bytes name+value)
|
|
||||||
27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80
|
|
||||||
|
|
||||||
The actual signature field doesn't contain the 1st 16 bits
|
|
||||||
of the hash, since crypto_sign() created signatures consist
|
|
||||||
of the hash+signature anyway.
|
|
||||||
|
|
||||||
So, a full pubkey export looks like this
|
|
||||||
|
|
||||||
version
|
|
||||||
ctime
|
|
||||||
cipher
|
|
||||||
3 x raw keys \
|
|
||||||
sigheader > calc hash from this
|
|
||||||
sigsubs (header+data) /
|
|
||||||
hash
|
|
||||||
signature
|
|
||||||
|
|
||||||
We use big-endian always.
|
|
||||||
|
|
||||||
http://tools.ietf.org/html/rfc4880#section-5.2.3
|
|
||||||
|
|
||||||
*/
|
|
||||||
struct _pcp_rfc_pubkey_header_t {
|
|
||||||
uint8_t version;
|
|
||||||
uint32_t ctime;
|
|
||||||
uint8_t cipher;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _pcp_rfc_pubkey_0x21_t {
|
|
||||||
byte sig_ed25519_pub[crypto_sign_PUBLICKEYBYTES];
|
|
||||||
byte ed25519_pub[crypto_sign_PUBLICKEYBYTES];
|
|
||||||
byte curve25519_pub[crypto_box_PUBLICKEYBYTES];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _pcp_rfc_pubkey_sigheader_0x21_t {
|
|
||||||
uint8_t version;
|
|
||||||
uint8_t type; /* 0x1F only, self signed */
|
|
||||||
uint8_t pkcipher;
|
|
||||||
uint8_t hashcipher;
|
|
||||||
uint16_t numsubs;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _pcp_rfc_pubkey_sigsub_0x21_t {
|
|
||||||
uint32_t size;
|
|
||||||
uint8_t type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct _pcp_rfc_pubkey_sig_0x21_t {
|
|
||||||
byte signature[crypto_generichash_BYTES_MAX + crypto_sign_BYTES];
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct _pcp_rfc_pubkey_header_t rfc_pub_h;
|
|
||||||
typedef struct _pcp_rfc_pubkey_0x21_t rfc_pub_k;
|
|
||||||
typedef struct _pcp_rfc_pubkey_sigheader_0x21_t rfc_pub_sig_h;
|
|
||||||
typedef struct _pcp_rfc_pubkey_sigsub_0x21_t rfc_pub_sig_s;
|
|
||||||
typedef struct _pcp_rfc_pubkey_sig_0x21_t rfc_pub_sig;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void pcp_cleanhashes();
|
void pcp_cleanhashes();
|
||||||
pcp_key_t *pcpkey_new ();
|
pcp_key_t *pcpkey_new ();
|
||||||
@@ -256,4 +186,5 @@ int pcp_sanitycheck_pub(pcp_pubkey_t *key);
|
|||||||
int pcp_sanitycheck_key(pcp_key_t *key);
|
int pcp_sanitycheck_key(pcp_key_t *key);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* _HAVE_PCP_KEYPAIR_H */
|
#endif /* _HAVE_PCP_KEYPAIR_H */
|
||||||
|
|||||||
134
include/pcp/mgmt.h
Normal file
134
include/pcp/mgmt.h
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
|
Copyright (C) 2014 T.v.Dein.
|
||||||
|
|
||||||
|
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: <tom AT vondein DOT org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _HAVE_PCP_MGMT_H
|
||||||
|
#define _HAVE_PCP_MGMT_H
|
||||||
|
|
||||||
|
#include <sodium.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
|
#include "platform.h"
|
||||||
|
#include "mem.h"
|
||||||
|
#include "ed.h"
|
||||||
|
#include "key.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* RFC4880 alike public key export with some simplifications:
|
||||||
|
|
||||||
|
In sig subpackets we're using fixed sized fields instead
|
||||||
|
of the mess they use in rfc4880. Sorry. We use only these types:
|
||||||
|
|
||||||
|
2 = Signature Creation Time (4 byte)
|
||||||
|
3 = Signature Expiration Time (4 byte)
|
||||||
|
9 = Key Expiration Time (4 bytes)
|
||||||
|
20 = Notation Data (4 byte flags, N bytes name+value)
|
||||||
|
27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80
|
||||||
|
|
||||||
|
The actual signature field doesn't contain the 1st 16 bits
|
||||||
|
of the hash, since crypto_sign() created signatures consist
|
||||||
|
of the hash+signature anyway.
|
||||||
|
|
||||||
|
So, a full pubkey export looks like this
|
||||||
|
|
||||||
|
version
|
||||||
|
ctime
|
||||||
|
cipher
|
||||||
|
3 x raw keys \
|
||||||
|
sigheader > calc hash from this
|
||||||
|
sigsubs (header+data) /
|
||||||
|
hash
|
||||||
|
signature
|
||||||
|
|
||||||
|
We use big-endian always.
|
||||||
|
|
||||||
|
http://tools.ietf.org/html/rfc4880#section-5.2.3
|
||||||
|
|
||||||
|
*/
|
||||||
|
struct _pcp_rfc_pubkey_header_t {
|
||||||
|
uint8_t version;
|
||||||
|
uint32_t ctime;
|
||||||
|
uint8_t cipher;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _pcp_rfc_pubkey_0x21_t {
|
||||||
|
byte sig_ed25519_pub[crypto_sign_PUBLICKEYBYTES];
|
||||||
|
byte ed25519_pub[crypto_sign_PUBLICKEYBYTES];
|
||||||
|
byte curve25519_pub[crypto_box_PUBLICKEYBYTES];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _pcp_rfc_pubkey_sigheader_0x21_t {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t pkcipher;
|
||||||
|
uint8_t hashcipher;
|
||||||
|
uint16_t numsubs;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _pcp_rfc_pubkey_sigsub_0x21_t {
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _pcp_rfc_pubkey_sig_0x21_t {
|
||||||
|
byte signature[crypto_generichash_BYTES_MAX + crypto_sign_BYTES];
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _pcp_rfc_pubkey_header_t rfc_pub_h;
|
||||||
|
typedef struct _pcp_rfc_pubkey_0x21_t rfc_pub_k;
|
||||||
|
typedef struct _pcp_rfc_pubkey_sigheader_0x21_t rfc_pub_sig_h;
|
||||||
|
typedef struct _pcp_rfc_pubkey_sigsub_0x21_t rfc_pub_sig_s;
|
||||||
|
typedef struct _pcp_rfc_pubkey_sig_0x21_t rfc_pub_sig;
|
||||||
|
|
||||||
|
#define EXP_PK_CIPHER 0x21
|
||||||
|
#define EXP_PK_CIPHER_NAME "CURVE25519-ED25519-POLY1305-SALSA20"
|
||||||
|
|
||||||
|
#define EXP_HASH_CIPHER 0x22
|
||||||
|
#define EXP_HASH_NAME "BLAKE2"
|
||||||
|
|
||||||
|
#define EXP_SIG_CIPHER 0x23
|
||||||
|
#define EXP_SIG_CIPHER_NAME "ED25519"
|
||||||
|
|
||||||
|
#define EXP_SIG_VERSION 0x01
|
||||||
|
#define EXP_SIG_TYPE 0x1F /* self signed */
|
||||||
|
|
||||||
|
/* sig sub notiation we support */
|
||||||
|
#define EXP_SIG_SUB_CTIME 2
|
||||||
|
#define EXP_SIG_SUB_SIGEXPIRE 3
|
||||||
|
#define EXP_SIG_SUB_KEYEXPIRE 9
|
||||||
|
#define EXP_SIG_SUB_NOTATION 20
|
||||||
|
#define EXP_SIG_SUB_KEYFLAGS 27
|
||||||
|
|
||||||
|
/* in armored mode, we're using the usual head+foot */
|
||||||
|
#define EXP_PK_HEADER "-----BEGIN ED25519-CURVE29915 PUBLIC KEY-----"
|
||||||
|
#define EXP_PK_FOOTER "------END ED25519-CURVE29915 PUBLICKEY------"
|
||||||
|
|
||||||
|
|
||||||
|
/* export public key */
|
||||||
|
Buffer *pcp_get_rfc_pub (pcp_pubkey_t *key, pcp_key_t *sk);
|
||||||
|
|
||||||
|
#endif // _HAVE_PCP_MGMT_H
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2014 T.v.Dein.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -65,7 +65,14 @@ void buffer_resize(Buffer *b, size_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t buffer_get(Buffer *b, void *buf, size_t len) {
|
unsigned char *buffer_get(Buffer *b) {
|
||||||
|
if(b->end > 0)
|
||||||
|
return b->buf;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t buffer_get_chunk(Buffer *b, void *buf, size_t len) {
|
||||||
if(len > b->end - b->offset || len == 0) {
|
if(len > b->end - b->offset || len == 0) {
|
||||||
fatal("[buffer %s] attempt to read %ld data from buffer with size %ld %p at offset %ld",
|
fatal("[buffer %s] attempt to read %ld data from buffer with size %ld %p at offset %ld",
|
||||||
len, b->size, b->offset);
|
len, b->size, b->offset);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2013 T.Linden.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
You can contact me by mail: <tlinden AT cpan DOT org>.
|
You can contact me by mail: <tom AT vondein DOT org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
71
libpcp/key.c
71
libpcp/key.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of Pretty Curved Privacy (pcp1).
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
Copyright (C) 2013 T.Linden.
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
You can contact me by mail: <tlinden AT cpan DOT org>.
|
You can contact me by mail: <tom AT vondein DOT org>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -394,70 +394,3 @@ int pcp_sanitycheck_key(pcp_key_t *key) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pcp_get_rfc_pub (pcp_pubkey_t *key) {
|
|
||||||
Buffer *out = buffer_new(1024, "bo1");
|
|
||||||
Buffer *raw = buffer_new(1024, "bs1");
|
|
||||||
|
|
||||||
/* add the header */
|
|
||||||
buffer_add8(out, PCP_KEY_VERSION);
|
|
||||||
buffer_add32(out, key->ctime);
|
|
||||||
buffer_add8(out, PCP_RFC_CIPHER);
|
|
||||||
|
|
||||||
/* add the keys */
|
|
||||||
buffer_add(raw, key->edpub, 32);
|
|
||||||
buffer_add(raw, key->edpub, 32);
|
|
||||||
buffer_add(raw, key->pub, 32);
|
|
||||||
|
|
||||||
/* add the sig header */
|
|
||||||
buffer_add8(raw, PCP_KEY_VERSION);
|
|
||||||
buffer_add8(raw, 0x1F); // FIXME: define
|
|
||||||
buffer_add8(raw, PCP_RFC_CIPHER);
|
|
||||||
buffer_add8(raw, PCP_RFC_CIPHER);
|
|
||||||
buffer_add16(raw, 5);
|
|
||||||
|
|
||||||
/* add sig ctime */
|
|
||||||
buffer_add32be(raw, 4);
|
|
||||||
buffer_add8(raw, 2);
|
|
||||||
buffer_add32be(raw, time(0));
|
|
||||||
|
|
||||||
/* add sig expire time */
|
|
||||||
buffer_add32be(raw, 4);
|
|
||||||
buffer_add8(raw, 3);
|
|
||||||
buffer_add32be(raw, time(0) + 31536000);
|
|
||||||
|
|
||||||
/* add key expire time */
|
|
||||||
buffer_add32be(raw, 4);
|
|
||||||
buffer_add8(raw, 9);
|
|
||||||
buffer_add32be(raw, key->ctime);
|
|
||||||
|
|
||||||
/* add name */
|
|
||||||
size_t notation_size = strlen(key->owner) + 4 + 5;
|
|
||||||
buffer_add32be(raw, notation_size);
|
|
||||||
buffer_add8(raw, 20);
|
|
||||||
buffer_add16be(raw, 5);
|
|
||||||
buffer_add16be(raw, strlen(key->owner));
|
|
||||||
buffer_add(raw, "owner", 5);
|
|
||||||
buffer_add(raw, key->owner, strlen(key->owner));
|
|
||||||
|
|
||||||
/* add mail */
|
|
||||||
notation_size = strlen(key->mail) + 4 + 4;
|
|
||||||
buffer_add32be(raw, notation_size);
|
|
||||||
buffer_add8(raw, 20);
|
|
||||||
buffer_add16be(raw, 4);
|
|
||||||
buffer_add16be(raw, strlen(key->mail));
|
|
||||||
buffer_add(raw, "mail", 4);
|
|
||||||
buffer_add(raw, key->mail, strlen(key->mail));
|
|
||||||
|
|
||||||
/* add key flags */
|
|
||||||
buffer_add32be(raw, 1);
|
|
||||||
buffer_add8(raw, 27);
|
|
||||||
buffer_add8(raw, 0x02 & 0x08 & 0x80);
|
|
||||||
|
|
||||||
/* FIXME:
|
|
||||||
Now, calculate the signature from the raw buffer,
|
|
||||||
add it to the output buffer, add the sig to the
|
|
||||||
output buffer and finally return it. */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|||||||
110
libpcp/mgmt.c
Normal file
110
libpcp/mgmt.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Pretty Curved Privacy (pcp1).
|
||||||
|
|
||||||
|
Copyright (C) 2013-2014 T.v.Dein.
|
||||||
|
|
||||||
|
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: <tom AT vondein DOT org>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "mgmt.h"
|
||||||
|
|
||||||
|
|
||||||
|
Buffer *pcp_get_rfc_pub (pcp_pubkey_t *key, pcp_key_t *sk) {
|
||||||
|
Buffer *out = buffer_new(320, "bo1");
|
||||||
|
Buffer *raw = buffer_new(256, "bs1");
|
||||||
|
|
||||||
|
/* add the header */
|
||||||
|
buffer_add8(out, PCP_KEY_VERSION);
|
||||||
|
buffer_add32(out, key->ctime);
|
||||||
|
buffer_add8(out, EXP_PK_CIPHER);
|
||||||
|
|
||||||
|
/* add the keys */
|
||||||
|
buffer_add(raw, key->edpub, 32);
|
||||||
|
buffer_add(raw, key->edpub, 32);
|
||||||
|
buffer_add(raw, key->pub, 32);
|
||||||
|
|
||||||
|
/* add the sig header */
|
||||||
|
buffer_add8(raw, EXP_SIG_VERSION);
|
||||||
|
buffer_add8(raw, EXP_SIG_TYPE);
|
||||||
|
buffer_add8(raw, EXP_SIG_CIPHER);
|
||||||
|
buffer_add8(raw, EXP_HASH_CIPHER);
|
||||||
|
buffer_add16(raw, 5); /* we add 5 sub sigs always */
|
||||||
|
|
||||||
|
/* add sig ctime */
|
||||||
|
buffer_add32be(raw, 4);
|
||||||
|
buffer_add8(raw, EXP_SIG_SUB_CTIME);
|
||||||
|
buffer_add32be(raw, time(0));
|
||||||
|
|
||||||
|
/* add sig expire time */
|
||||||
|
buffer_add32be(raw, 4);
|
||||||
|
buffer_add8(raw, EXP_SIG_SUB_SIGEXPIRE);
|
||||||
|
buffer_add32be(raw, time(0) + 31536000);
|
||||||
|
|
||||||
|
/* add key expire time */
|
||||||
|
buffer_add32be(raw, 4);
|
||||||
|
buffer_add8(raw, EXP_SIG_SUB_KEYEXPIRE);
|
||||||
|
buffer_add32be(raw, key->ctime + 31536000);
|
||||||
|
|
||||||
|
/* add name notation sub*/
|
||||||
|
size_t notation_size = strlen(key->owner) + 4 + 5;
|
||||||
|
buffer_add32be(raw, notation_size);
|
||||||
|
buffer_add8(raw, EXP_SIG_SUB_NOTATION);
|
||||||
|
buffer_add16be(raw, 5);
|
||||||
|
buffer_add16be(raw, strlen(key->owner));
|
||||||
|
buffer_add(raw, "owner", 5);
|
||||||
|
buffer_add(raw, key->owner, strlen(key->owner));
|
||||||
|
|
||||||
|
/* add mail notation sub */
|
||||||
|
notation_size = strlen(key->mail) + 4 + 4;
|
||||||
|
buffer_add32be(raw, notation_size);
|
||||||
|
buffer_add8(raw, EXP_SIG_SUB_NOTATION);
|
||||||
|
buffer_add16be(raw, 4);
|
||||||
|
buffer_add16be(raw, strlen(key->mail));
|
||||||
|
buffer_add(raw, "mail", 4);
|
||||||
|
buffer_add(raw, key->mail, strlen(key->mail));
|
||||||
|
|
||||||
|
/* add key flags */
|
||||||
|
buffer_add32be(raw, 1);
|
||||||
|
buffer_add8(raw, 27);
|
||||||
|
buffer_add8(raw, 0x02 & 0x08 & 0x80);
|
||||||
|
|
||||||
|
/* create a hash from the PK material and the raw signature packet */
|
||||||
|
crypto_generichash_state *st = ucmalloc(sizeof(crypto_generichash_state));
|
||||||
|
unsigned char *hash = ucmalloc(crypto_generichash_BYTES_MAX);
|
||||||
|
|
||||||
|
crypto_generichash_init(st, NULL, 0, 0);
|
||||||
|
crypto_generichash_update(st, buffer_get(raw), buffer_size(raw));
|
||||||
|
crypto_generichash_final(st, hash, crypto_generichash_BYTES_MAX);
|
||||||
|
|
||||||
|
/* sign the hash */
|
||||||
|
unsigned char *sig = pcp_ed_sign(hash, crypto_generichash_BYTES_MAX, sk->secret);
|
||||||
|
|
||||||
|
/* append the signature packet to the output */
|
||||||
|
buffer_add(out, buffer_get(raw), buffer_size(raw));
|
||||||
|
|
||||||
|
/* append the signed hash */
|
||||||
|
buffer_add(out, sig, crypto_generichash_BYTES_MAX + crypto_generichash_BYTES_MAX);
|
||||||
|
|
||||||
|
/* and that's it. wasn't that easy? :) */
|
||||||
|
buffer_free(raw);
|
||||||
|
memset(hash, 0, crypto_generichash_BYTES_MAX);
|
||||||
|
free(hash);
|
||||||
|
memset(sig, 0, crypto_generichash_BYTES_MAX + crypto_generichash_BYTES_MAX);
|
||||||
|
free(sig);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
@@ -336,7 +336,7 @@ int pcp_importsecret (vault_t *vault, FILE *in) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(clen != PCP_RAW_KEYSIZE) {
|
if(clen != PCP_RAW_KEYSIZE) {
|
||||||
fatal("Error: decoded input didn't result to a proper sized key! (got %d bytes)\n", clen);
|
fatal("Error: decoded input didn't result to a proper sized key! (got %ld bytes, expected %ld)\n", clen, PCP_RAW_KEYSIZE);
|
||||||
free(z85decoded);
|
free(z85decoded);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -624,3 +624,69 @@ char *pcp_find_id_byrec(char *recipient) {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Experimental RFC4880-alike public key export. Once stable and
|
||||||
|
flexible enough, this will become the PCP default, I hope. */
|
||||||
|
void pcp_exportpublic2(char *passwd, char *outfile, int armor) {
|
||||||
|
pcp_pubkey_t *key = NULL;
|
||||||
|
|
||||||
|
pcp_key_t *s = NULL;
|
||||||
|
s = pcp_find_primary_secret();
|
||||||
|
if(s == NULL) {
|
||||||
|
fatal("There's no primary secret key in the vault %s!\n", vault->filename);
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
key = pcpkey_pub_from_secret(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(key != NULL) {
|
||||||
|
FILE *out;
|
||||||
|
if(outfile == NULL) {
|
||||||
|
out = stdout;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if((out = fopen(outfile, "wb+")) == NULL) {
|
||||||
|
fatal("Could not create output file %s", outfile);
|
||||||
|
out = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(out != NULL) {
|
||||||
|
pcp_key_t *sk = pcp_find_primary_secret();
|
||||||
|
if(sk != NULL) {
|
||||||
|
char *passphrase;
|
||||||
|
pcp_readpass(&passphrase, "Enter passphrase to decrypt your secret key for signing the export", NULL, 1);
|
||||||
|
|
||||||
|
sk = pcpkey_decrypt(sk, passphrase);
|
||||||
|
if(sk != NULL) {
|
||||||
|
Buffer *exported_pk = pcp_get_rfc_pub(key, sk);
|
||||||
|
if(exported_pk != NULL) {
|
||||||
|
if(armor == 1) {
|
||||||
|
size_t zlen;
|
||||||
|
char *z85 = pcp_z85_encode(buffer_get(exported_pk), buffer_size(exported_pk), &zlen);
|
||||||
|
fprintf(out, "%s\r\n%s\r\n%s\r\n", EXP_PK_HEADER, z85, EXP_PK_FOOTER);
|
||||||
|
free(z85);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fwrite(buffer_get(exported_pk), 1, buffer_size(exported_pk), out);
|
||||||
|
|
||||||
|
fclose(out);
|
||||||
|
if(debug) {
|
||||||
|
buffer_dump(exported_pk);
|
||||||
|
buffer_info(exported_pk);
|
||||||
|
pcp_dumppubkey(key);
|
||||||
|
}
|
||||||
|
buffer_free(exported_pk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(passphrase);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -40,6 +40,8 @@
|
|||||||
#include "keyhash.h"
|
#include "keyhash.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "base85.h"
|
#include "base85.h"
|
||||||
|
#include "buffer.h"
|
||||||
|
#include "mgmt.h"
|
||||||
|
|
||||||
#define _WITH_GETLINE
|
#define _WITH_GETLINE
|
||||||
|
|
||||||
@@ -58,4 +60,7 @@ int pcp_importsecret (vault_t *vault, FILE *in);
|
|||||||
void pcpdelete_key(char *keyid);
|
void pcpdelete_key(char *keyid);
|
||||||
char *pcp_find_id_byrec(char *recipient);
|
char *pcp_find_id_byrec(char *recipient);
|
||||||
|
|
||||||
|
/* Experimental: new rfc4880 style pk export */
|
||||||
|
void pcp_exportpublic2(char *passwd, char *outfile, int armor);
|
||||||
|
|
||||||
#endif /* _HAVE_KEYMGMT_H */
|
#endif /* _HAVE_KEYMGMT_H */
|
||||||
|
|||||||
38
src/pcp.c
38
src/pcp.c
@@ -46,7 +46,7 @@ char *default_vault() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main (int argc, char **argv) {
|
int main (int argc, char **argv) {
|
||||||
int opt, mode, usevault, useid, userec, lo, armor, detach, signcrypt, pbpcompat;
|
int opt, mode, usevault, useid, userec, lo, armor, detach, signcrypt, pbpcompat, rfc;
|
||||||
char *vaultfile = default_vault();
|
char *vaultfile = default_vault();
|
||||||
char *outfile = NULL;
|
char *outfile = NULL;
|
||||||
char *infile = NULL;
|
char *infile = NULL;
|
||||||
@@ -70,6 +70,7 @@ int main (int argc, char **argv) {
|
|||||||
detach = 0;
|
detach = 0;
|
||||||
signcrypt = 0;
|
signcrypt = 0;
|
||||||
pbpcompat = 0;
|
pbpcompat = 0;
|
||||||
|
rfc = 0;
|
||||||
|
|
||||||
static struct option longopts[] = {
|
static struct option longopts[] = {
|
||||||
/* generics */
|
/* generics */
|
||||||
@@ -92,6 +93,7 @@ int main (int argc, char **argv) {
|
|||||||
{ "edit-key", no_argument, NULL, 'E' },
|
{ "edit-key", no_argument, NULL, 'E' },
|
||||||
{ "export-yaml", no_argument, NULL, 'y' },
|
{ "export-yaml", no_argument, NULL, 'y' },
|
||||||
{ "pbpcompat", no_argument, NULL, 'b' },
|
{ "pbpcompat", no_argument, NULL, 'b' },
|
||||||
|
{ "rfc-format", no_argument, NULL, '1' }, /* no short option */
|
||||||
|
|
||||||
/* crypto */
|
/* crypto */
|
||||||
{ "encrypt", no_argument, NULL, 'e' },
|
{ "encrypt", no_argument, NULL, 'e' },
|
||||||
@@ -114,7 +116,7 @@ int main (int argc, char **argv) {
|
|||||||
{ NULL, 0, NULL, 0 }
|
{ NULL, 0, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gcymf:b",
|
while ((opt = getopt_long(argc, argv, "klV:vdehsO:i:I:pSPRtEx:DzZr:gcymf:b1",
|
||||||
longopts, NULL)) != -1) {
|
longopts, NULL)) != -1) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
@@ -151,6 +153,9 @@ int main (int argc, char **argv) {
|
|||||||
mode += PCP_MODE_IMPORT_SECRET;
|
mode += PCP_MODE_IMPORT_SECRET;
|
||||||
usevault = 1;
|
usevault = 1;
|
||||||
break;
|
break;
|
||||||
|
case '1':
|
||||||
|
rfc = 1;
|
||||||
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
mode += PCP_MODE_DELETE_KEY;
|
mode += PCP_MODE_DELETE_KEY;
|
||||||
usevault = 1;
|
usevault = 1;
|
||||||
@@ -372,19 +377,24 @@ int main (int argc, char **argv) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case PCP_MODE_EXPORT_PUBLIC:
|
case PCP_MODE_EXPORT_PUBLIC:
|
||||||
if(useid) {
|
if(rfc) {
|
||||||
id = pcp_normalize_id(keyid);
|
pcp_exportpublic2(xpass, outfile, armor);
|
||||||
if(id == NULL)
|
}
|
||||||
break;
|
else {
|
||||||
|
if(useid) {
|
||||||
|
id = pcp_normalize_id(keyid);
|
||||||
|
if(id == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (recipient != NULL)
|
||||||
|
pcp_exportpublic(id, recipient->value, xpass, outfile, pbpcompat);
|
||||||
|
else
|
||||||
|
pcp_exportpublic(id, NULL, xpass, outfile, pbpcompat);
|
||||||
|
if(xpass != NULL)
|
||||||
|
free(xpass);
|
||||||
|
if(recipient != NULL)
|
||||||
|
free(recipient);
|
||||||
}
|
}
|
||||||
if (recipient != NULL)
|
|
||||||
pcp_exportpublic(id, recipient->value, xpass, outfile, pbpcompat);
|
|
||||||
else
|
|
||||||
pcp_exportpublic(id, NULL, xpass, outfile, pbpcompat);
|
|
||||||
if(xpass != NULL)
|
|
||||||
free(xpass);
|
|
||||||
if(recipient != NULL)
|
|
||||||
free(recipient);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PCP_MODE_IMPORT_PUBLIC:
|
case PCP_MODE_IMPORT_PUBLIC:
|
||||||
|
|||||||
Reference in New Issue
Block a user