diff --git a/autogen.sh b/autogen.sh index 727acf9..f16cc0e 100755 --- a/autogen.sh +++ b/autogen.sh @@ -51,6 +51,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography. cat man/footer.pod >> man/pcp1.pod pod2man -r "PCP `cat VERSION`" -c "USER CONTRIBUTED DOCUMENTATION" man/pcp1.pod > man/pcp1.1 + pod2html man/pcp1.pod > man/pcp1.html # generate the top level readme cat man/badges man/pcp.pod man/install.pod man/footer.pod > README.pod diff --git a/bindings/py/pypcp/raw.py b/bindings/py/pypcp/raw.py index 30e5611..364a426 100644 --- a/bindings/py/pypcp/raw.py +++ b/bindings/py/pypcp/raw.py @@ -602,58 +602,61 @@ void ucfree(void *d, size_t len); /*** ./gencffi.pl: from ../../include/pcp/mem.h:58 */ void sfree(void *d); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ Buffer *pcp_export_rfc_pub (PCPCTX *ptx, pcp_key_t *sk); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ Buffer *pcp_export_pbp_pub(pcp_key_t *sk); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ Buffer *pcp_export_secret(PCPCTX *ptx, pcp_key_t *sk, char *passphrase); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ Buffer *pcp_export_json_pub(PCPCTX *ptx, pcp_key_t *sk, byte *sig, size_t siglen); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ Buffer *pcp_export_json_secret(PCPCTX *ptx, pcp_key_t *sk, byte *nonce, byte *cipher, size_t clen); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ json_t *pcp_sk2json(pcp_key_t *sk, byte *sig,size_t siglen); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ json_t *pcp_pk2json(pcp_pubkey_t *pk); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_ks_bundle_t *pcp_import_pub_json(PCPCTX *ptx, byte *raw, size_t rawsize); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ +Buffer *pcp_import_secret_json(PCPCTX *ptx, Buffer *json); + +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_ks_bundle_t *pcp_import_pub(PCPCTX *ptx, byte *raw, size_t rawsize); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_ks_bundle_t *pcp_import_binpub(PCPCTX *ptx, byte *raw, size_t rawsize); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_ks_bundle_t *pcp_import_pub_rfc(PCPCTX *ptx, Buffer *blob); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_ks_bundle_t *pcp_import_pub_pbp(PCPCTX *ptx, Buffer *blob); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_key_t *pcp_import_binsecret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_key_t *pcp_import_secret(PCPCTX *ptx, byte *raw, size_t rawsize, char *passphrase); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ pcp_key_t *pcp_import_secret_native(PCPCTX *ptx, Buffer *cipher, char *passphrase); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ int _check_keysig_h(PCPCTX *ptx, Buffer *blob, rfc_pub_sig_h *h); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ int _check_hash_keysig(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, pcp_keysig_t *sk); -/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:294 */ +/*** ./gencffi.pl: from ../../include/pcp/mgmt.h:188 */ int _check_sigsubs(PCPCTX *ptx, Buffer *blob, pcp_pubkey_t *p, rfc_pub_sig_s *subheader); /*** ./gencffi.pl: from ../../include/pcp/pcpstream.h:291 */ @@ -861,15 +864,7 @@ uint8_t *zmq_z85_decode (uint8_t *dest, char *string); char *zmq_z85_encode (char *dest, uint8_t *data, size_t size);''' # ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_PK_HEADER = "----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ASYM_CIPHER_SIG = 24 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_SIG_START = "----- BEGIN ED25519 SIGNATURE -----" +PCP_SIG_END = "----- END ED25519 SIGNATURE -----" # ./gencffi.pl: from ../../include/pcp/defines.h:172 @@ -877,11 +872,11 @@ EXP_SIG_SUB_SIGEXPIRE = 3 # ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_BLOCK_SIZE = 32 * 1024 +PCP_ASYM_CIPHER = 5 # ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SIG_SUB_KEYFLAGS = 27 +PCP_SIG_HEADER = "----- BEGIN ED25519 SIGNED MESSAGE -----" # ./gencffi.pl: from ../../include/pcp/defines.h:172 @@ -889,31 +884,7 @@ EXP_PK_CIPHER = 0x21 # ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_SYM_CIPHER = 23 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_VAULT_ID = 14 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SIG_SUB_NOTATION = 20 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SIG_SUB_KEYEXPIRE = 9 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ZFILE_FOOTER = "----- END Z85 ENCODED FILE -----" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_PK_FOOTER = "----- END ED25519-CURVE29915 PUBLIC KEY -----" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_RFC_CIPHER = 0x21 +EXP_SIG_CIPHER = 0x23 # ./gencffi.pl: from ../../include/pcp/defines.h:172 @@ -921,51 +892,7 @@ PCP_CRYPTO_ADD = (32 - 16) # ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ME = "Pretty Curved Privacy" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SK_FOOTER = "----- END ED25519-CURVE29915 PRIVATE KEY -----" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SIG_CIPHER = 0x23 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ASYM_CIPHER_ANON = 6 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SIG_CIPHER_NAME = "ED25519" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ZFILE_HEADER = "----- BEGIN Z85 ENCODED FILE -----" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_HASH_NAME = "BLAKE2" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ENFILE_FOOTER = "\r\n----- END PCP ENCRYPTED FILE -----\r\n" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SK_HEADER = "----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SIG_TYPE = 0x1F - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ASYM_CIPHER = 5 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_SIGPREFIX = "\nnacl-" +EXP_FORMAT_NATIVE = 1 # ./gencffi.pl: from ../../include/pcp/defines.h:172 @@ -973,19 +900,11 @@ EXP_HASH_CIPHER = 0x22 # ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_PK_CIPHER_NAME = "CURVE25519-ED25519-POLY1305-SALSA20" +EXP_PK_FOOTER = "----- END ED25519-CURVE29915 PUBLIC KEY -----" # ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_SIG_END = "----- END ED25519 SIGNATURE -----" - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_SIG_SUB_CTIME = 2 - - -# ./gencffi.pl: from ../../include/pcp/defines.h:172 -EXP_FORMAT_NATIVE = 1 +PCP_ME = "Pretty Curved Privacy" # ./gencffi.pl: from ../../include/pcp/defines.h:172 @@ -993,11 +912,19 @@ PCP_ENFILE_HEADER = "----- BEGIN PCP ENCRYPTED FILE -----\r\n" # ./gencffi.pl: from ../../include/pcp/defines.h:172 -PBP_COMPAT_SALT = "qa~t](84z<1t<1oz:ik.@IRNyhG=8q(on9}4#!/_h#a7wqK{Nt$T?W>,mt8NqYq&6U,rSYI2GRDd:Bcm" +PCP_BLOCK_SIZE = 32 * 1024 # ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_ENCRYPT_MAC = 56 +PCP_SIGPREFIX = "\nnacl-" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_ZFILE_HEADER = "----- BEGIN Z85 ENCODED FILE -----" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_SIG_CIPHER_NAME = "ED25519" # ./gencffi.pl: from ../../include/pcp/defines.h:172 @@ -1005,4 +932,80 @@ EXP_FORMAT_PBP = 2 # ./gencffi.pl: from ../../include/pcp/defines.h:172 -PCP_SIG_HEADER = "----- BEGIN ED25519 SIGNED MESSAGE -----" +EXP_SIG_SUB_KEYFLAGS = 27 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_SIG_SUB_KEYEXPIRE = 9 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_SIG_SUB_CTIME = 2 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_VAULT_ID = 14 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_PK_HEADER = "----- BEGIN ED25519-CURVE29915 PUBLIC KEY -----" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_PK_CIPHER_NAME = "CURVE25519-ED25519-POLY1305-SALSA20" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_SK_FOOTER = "----- END ED25519-CURVE29915 PRIVATE KEY -----" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_ZFILE_FOOTER = "----- END Z85 ENCODED FILE -----" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_SK_HEADER = "----- BEGIN ED25519-CURVE29915 PRIVATE KEY -----" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_SYM_CIPHER = 23 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PBP_COMPAT_SALT = "qa~t](84z<1t<1oz:ik.@IRNyhG=8q(on9}4#!/_h#a7wqK{Nt$T?W>,mt8NqYq&6U,rSYI2GRDd:Bcm" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_ENFILE_FOOTER = "\r\n----- END PCP ENCRYPTED FILE -----\r\n" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_SIG_SUB_NOTATION = 20 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_ASYM_CIPHER_ANON = 6 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_SIG_START = "----- BEGIN ED25519 SIGNATURE -----" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_ENCRYPT_MAC = 56 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_HASH_NAME = "BLAKE2" + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_RFC_CIPHER = 0x21 + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +EXP_SIG_TYPE = 0x1F + + +# ./gencffi.pl: from ../../include/pcp/defines.h:172 +PCP_ASYM_CIPHER_SIG = 24 diff --git a/include/pcp/mgmt.h b/include/pcp/mgmt.h index 508fed7..7bdea69 100644 --- a/include/pcp/mgmt.h +++ b/include/pcp/mgmt.h @@ -78,87 +78,7 @@ /** RFC4880 alike public key export with some modifications. - RFC4880 alike public key export with the following modifications: - - - Key material is native to us and not specified in the - rfc for curve25519/ed25519. Therefore we're doing it like - so: mp|sp|cp - where mp = master keysigning public key (ed25519), 32 bytes - sp = signing public key (ed25519), 32 bytes - cp = encryption public key (curve25519), 32 bytes - - - The various cipher (algorithm) id's are unspecified for - our native ciphers. Therefore I created them, starting at - 33 (afaik 22 is the last officially assigned one). Once - those cipher numbers become official, I'll use them instead - of my own. - - - We use 64 bit integers for times everywhere (ctime, expire, etc), - to be year 2038 safe. Note, that this is a violation of the - RFC spec. However, said RFC have to be modified to fit 2038 - anc beyond anyways. This applies for the keyfile ctime as - well for the key sig sub fields containing time values. - - - The exported public key packet contains a signature. We're - filling out all required fields. A signature has a variable - number of sig sub packets. We use only these types: - - 2 = Signature Creation Time (8 byte) - 3 = Signature Expiration Time (8 byte) - 9 = Key Expiration Time (8 bytes) - 20 = Notation Data (4 byte flags, N bytes name+value) - 27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80 - - - We use 3 notation fields: - * "owner", which contains the owner name, if set - * "mail", which contains the emailaddress, if set - * "serial", which contains the 32bit serial number - - - The actual signature field consists of the blake2 hash of - (mp|sp|cp|keysig) followed by the nacl signature. However, we do - not put an extra 16byte value of the hash, since the nacl - signature already contains the full hash. So, an implementation - could simply pull the fist 16 bytes of said hash to get - the same result. - - - The mp keypair will be used for signing. The recipient can - verify the signature, since mp is included. - - - While we put expiration dates for the key and the signature - into the export as the rfc demands, we ignore them. Key expiring - is not implemented in PCP yet. - - 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. - - Unlike RC4880 public key exports, we're using Z85 encoding if - armoring have been requested by the user. Armored output has - a header and a footer line, however they are ignored by the - parser and are therefore optional. Newlines, if present, are - optional as well. - - http://tools.ietf.org/html/rfc4880#section-5.2.3 - - The key sig blob will be saved in the Vault if we import a public key - unaltered, so we can verify the signature at will anytime. When exporting - a foreign public key, we will just put out that key sig blob to the - export untouched. - - Currently PCP only support self-signed public key exports. - - We only support one key signature per key. However, it would be easily - possible to support foreign keysigs as well in the future. - + (Refer to the INTERNALS section of the pcp(1) manual page for details. \param sk a secret key structure of type pcp_key_t. The secret keys in there have to be already decrypted. @@ -185,36 +105,9 @@ Buffer *pcp_export_pbp_pub(pcp_key_t *sk); /** Export secret key. - Export a secret key. + Export a secret key. (refer to the INTERNALS section of the pcp(1) manual page for details). - Secret key are exported in proprietary format. - - The exported binary blob is symmetrically encrypted using the NACL - function crypto_secret(). The passphrase will be used to derive an - encryption key using the STAR function scrypt(). - - The binary data before encryption consists of: - - - ED25519 master signing secret - - Curve25519 encryption secret - - ED25519 signing secret - - ED25519 master signing public - - Curve25519 encryption public - - ED25519 signing public - - Optional notations, currently supported are the 'owner' and 'mail' attributes. - If an attribute is empty, the len field contains zero. - -# len(VAL) (2 byte uint) - -# VAL (string without trailing zero) - - 8 byte creation time (epoch) - - 4 byte key version - - 4 byte serial number - - The encrypted cipher will be prepended with the random nonce used - to encrypt the data and looks after encryption as such: - - Nonce | Cipher - - \param[in] ptx context. + \param[in] ptx context. \param sk a secret key structure of type pcp_key_t. The secret keys in there have to be already decrypted. diff --git a/man/details.pod b/man/details.pod index 13194f0..0ccf90b 100644 --- a/man/details.pod +++ b/man/details.pod @@ -51,7 +51,7 @@ Another example: As you can see, it is also possible to encrypt a message for multiple recipients. -=item B +=item B In anonymous mode a random generated keypair will be used on the sender side. This way the recipient doesn't have to have your public @@ -83,6 +83,8 @@ an encryption key will be derived using scrypt(). PCP doesn't validate the security of the passphrase. +Self mode can be explicitly enforced with B<-m>. + =back =head1 SIGNATURES @@ -236,7 +238,7 @@ Default vault file where all keys are stored. =head1 EXPERIMENTAL STATUS -Currently there are a couple of problems which are currently +Currently there are a couple of problems which are unsolved or in the process to be solved. =over @@ -254,7 +256,8 @@ to some key server because in order to encrypt a message, both the recipient AND the sender need to have the public key of each other. It would be possible to publish public keys, and attach the senders public key to the encrypted message, but -I'm not sure if such an aproach would be secure enough. +I'm not sure if such an aproach would be secure enough. Pcp +implements this scheme though (refer to the option -A). =item B @@ -267,10 +270,20 @@ ECC algorithms. While I, as the author of pcp1 totally trust D.J.Bernstein, this may not be the case for you. -In short, I'd suggest not to use it on critical systems yet. +=item B + +As with every crypto software, pcp has to undergo a couple rounds +of peer review (analysis) in order to be considered secure, trustable +and stable. No any such review has been undertaken on pcp yet. + +Pcp is a mere fun project aimed at teaching myself better C coding +and crypto. In fact I don't even trust the software myself and I +don't use it for anything remotely serious. =back +B + =head1 INTERNALS =head2 VAULT FORMAT @@ -319,7 +332,6 @@ The key header is followed by the actual key, see below. A secret key is a binary structure with the following format: - +---------------------------------------------------------+ | Field Size Description | +-------------+--------+----------------------------------+ @@ -390,12 +402,167 @@ Generate a Curve25519 encryption keypair from that seed. =back -So, while both secrets are stored in the sam PCP key, they +So, while both secrets are stored in the same PCP key, they are otherwise unrelated. If one of them leaks, the other cannot be recalculated from it. Take a look at the function B for details. +=head2 PUBLIC KEY EXPORT FORMAT + +Exported public and secret keys will be written in a portable +way. Pcp uses RFC4880 export format for public keys with some +slight modifications: + + + +=over + +=item + +Key material is native to libsodium/pcp and not specified in the +rfc for curve25519/ed25519. Therefore pcp encodes key material doing it like +this: mp|sp|cp + +where + + mp = master keysigning public key (ed25519), 32 bytes + sp = signing public key (ed25519), 32 bytes + cp = encryption public key (curve25519), 32 bytes + +=item + +The various cipher (algorithm) id's are unspecified for +libsodium/pcp native ciphers. Therefore they are proprietary to pcp, starting at +33 (22 is the last officially assigned one). Once +those cipher numbers become official, they will be used instead. + +=item + +Pcp uses 64 bit integers for timestamps everywhere (ctime, expire, etc), +to be year 2038 safe. Note, that this is a violation of the +RFC spec. However, said RFC have to be modified to fit 2038 +(and beyond) anyways. This applies for the keyfile ctime as +well for the key sig sub fields containing time values. + +=item + +The exported public key packet contains a signature. Pcp is +filling out all required fields. A signature has a variable +number of sig sub packets. Pcp uses only these types: + + 2 = Signature Creation Time (8 byte) + 3 = Signature Expiration Time (8 byte) + 9 = Key Expiration Time (8 bytes) + 20 = Notation Data (4 byte flags, N bytes name+value) + 27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80 + +=item + +Pcp uses 3 notation fields: + +=over + +=item "owner", which contains the owner name, if set + +=item "mail", which contains the emailaddress, if set + +=item "serial", which contains the 32bit serial number + +=back + +=item + +The actual signature field consists of the blake2 hash of +(mp|sp|cp|keysig) followed by the nacl signature. However, pcp +does not put an extra 16 byte value of the hash, since the nacl +signature already contains the full hash. So, an implementation +could simply pull the fist 16 bytes of said hash to get +the same result if desired. + +=item + +The mp keypair will be used for signing. The recipient can +verify the signature, since mp is included. + +=item + +While pcp puts expiration dates for the key and the signature +into the export as the rfc demands, it mostly ignores them (yet). +Key expiring is not implemented in PCP yet. + +=item + +We use big-endian always. + +=item + +Unlike RC4880 public key exports, pcp uses Z85 encoding if +armoring have been requested by the user. Armored output has +a header and a footer line, however they are ignored by the +parser and are therefore optional. Newlines, if present, are +optional as well. + +http://tools.ietf.org/html/rfc4880#section-5.2.3 + +=item + +The key sig blob will be saved in the Vault unaltered during +import, so pcp is able to verify the signature at will anytime. When exporting +a foreign public key, pcp just puts out that key sig blob to the +export untouched. + +=item + +Currently PCP only supports self-signed public key exports. + +=item + +Pcp only supports one key signature per key. However, it would be easily +possible to support foreign keysigs as well in the future. + +=back + +So, a full pubkey export looks like this + + version + ctime + cipher + 3 x raw keys \ + sigheader > calculate hash from this + sigsubs (header+data) / + hash + signature + +=head2 SECRET KEY EXPORT FORMAT + +Secret keys are exported in a proprietary format. + +The exported binary blob is symmetrically encrypted using the NACL +function crypto_secret(). The passphrase will be used to derive an +encryption key using the STAR function scrypt(). + +The binary data before encryption consists of: + + ED25519 master signing secret + Curve25519 encryption secret + ED25519 signing secret + ED25519 master signing public + Curve25519 encryption public + ED25519 signing public + Optional notations, currently supported are the 'owner' and 'mail' attributes. + If an attribute is empty, the len field is zero. + -# len(VAL) (2 byte uint) + -# VAL (string without trailing zero) + 8 byte creation time (epoch) + 4 byte key version + 4 byte serial number + +The encrypted cipher will be prepended with the random nonce used +to encrypt the data and looks after encryption as such: + + Nonce | Cipher + =head2 ENCRYPTED OUTPUT FORMAT The encryption protocol used by PCP uses mostly standard @@ -645,3 +812,143 @@ files and signatures - at least their binary versions - should be exchangable. H this is a work in progress and might not work under all circumstances. Also there's currently no shared key format between pbp and pcp. However, it is possible to export and import pbp keys from/to pcp. + +=head1 JSON ENCODING SUPPORT + +If pcp have been compiled with B<--with-json> (which requires the libjansson +library), then it supports JSON objects as input and output with the following +functions: + +=over + +=item public key export + +=item secret key export + +=item whole vault export + +=item public key import + +=item secret key import + +=back + +JSON support can be used either with the commandline tool B or programmatically +using the C, C++ or Python API. + +=head2 USING JSON FROM THE C API + +In order to use JSON all you've got to do is to switch a context flag: + + PCPCTX *ptx = ptx_new(); + ptx->json = 1; + +That all to it. Now any function normally used for key import and export works +with JSON, just fill the B object with a JSON string for imports or +fetch the Buffer content of an export function as a string. + +=head2 USING JSON FROM THE COMMANDLINE + +In order to use JSON on the commandline, add B<-j>. This can be used in +conjunction with the following options: + +=over + +=item B<-p> + +Public key export. + +=item B<-s> + +Secret key export. + +=item B<-K> + +Public and secret key import. + +=item B<-t> + +Text view mode (aka inspect mode). + +=back + +The B<-z> and B<-Z> options are ignored in JSON mode. + +=head2 JSON OBJECT STRUCTURE + +=head3 JSON PUBLIC KEY (pcp1 -p -j) + +The JSON object for a public key looks like this: + + { + "id": "6BF2980419E0986A", + "owner": "tom", + "mail": "tom@local", + "ctime": 1436170865, + "expire": 1467706865, + "version": 6, + "serial": 1509801135, + "type": "public", + "cipher": "CURVE25519-ED25519-POLY1305-SALSA20", + "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01", + "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2", + "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e", + "signature": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45[..]" + } + +Actually the field B contains the whole encoded public key. + +Fields containing byte arrays are hex encoded. + +Numbers are represented as literal integers. + +=head3 JSON SECRET KEY (pcp1 -s -j) + +The JSON object for a public key looks like this: + + { + "id": "6BF2980419E0986A", + "owner": "tom", + "mail": "tom@local", + "ctime": 1436170865, + "expire": 1467706865, + "version": 6, + "serial": 1509801135, + "type": "secret", + "cipher": "CURVE25519-ED25519-POLY1305-SALSA20", + "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01", + "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2", + "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e", + "secrets": "ad5ce150f3cd7bffa299d4db5bf3d26ae56c3808ccba7[..]", + "nonce": "858ef9870fc8f39903cfb281d697ca29a935d2ae929fa4ea" +} + +As you can see that's pretty identical to a public key json object beside the +B and B fields. The B field contains the encrypted +secret key material. Pcp does not support exporting a secret key unencrypted. + +The B is required for a later import and shall not be changed or +decoupled from B. This may change in the future. + +=head3 JSON VAULT (pcp1 -t) + +The JSON object for the vault looks like this: + + { + "keyvaultfile": "/home/tom/.pcpvault", + "version": 2, + "checksum": "27b583dc2dacf5ccc874b7be3a39748d107c6b9e9f9d473f1c716a94561ef793", + "secretkeys": 1, + "publickey": 3, + "keys": [] + } + +The field B is an array containing one or more of the already +described key objects. + +=head3 JSON PROGRAM OUTPUT + +Currently pcp does not support JSON program output, that is, success or +error messages on STDERR are not encoded as json. This may change in the future. + + diff --git a/man/pcp1.1 b/man/pcp1.1 index d5040e7..e107f7e 100644 --- a/man/pcp1.1 +++ b/man/pcp1.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "PCP1 1" -.TH PCP1 1 "2015-07-08" "PCP 0.2.6" "USER CONTRIBUTED DOCUMENTATION" +.TH PCP1 1 "2015-07-10" "PCP 0.2.6" "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 @@ -172,7 +172,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography. \& \-K \-\-import Import a secret or public key. \& \-F \-\-export\-format Specify exportformat, either \*(Aqpbp\*(Aq or \*(Aqpcp\*(Aq. \& \*(Aqpcp\*(Aq is the default if unspecified. -\& \-j \-\-json Enable JSON output (with \-t, \-p and \-s). +\& \-j \-\-json Enable JSON output (with \-t, \-p, \-s and \-K). \& \& Encryption Options: \& \-e \-\-encrypt Asym\-Encrypt a message. If none of \-i or \-r @@ -261,6 +261,7 @@ Pretty Curved Privacy \- File encryption using eliptic curve cryptography. \& Currently supported: pcp and pbp. \& \-j \-\-json enable JSON output. Can be used with info \& output (\-t) and key export (\-p and \-s). +\& and import (\-K). \& \& Encryption Options: \& \-e \-\-encrypt Asym\-Encrypt a message. Read from stdin or @@ -495,8 +496,8 @@ Another example: .Sp As you can see, it is also possible to encrypt a message for multiple recipients. -.IP "\fBAonymous public key encryption\fR" 4 -.IX Item "Aonymous public key encryption" +.IP "\fBAnonymous public key encryption\fR" 4 +.IX Item "Anonymous public key encryption" In anonymous mode a random generated keypair will be used on the sender side. This way the recipient doesn't have to have your public key. @@ -529,6 +530,8 @@ operates in self mode encryption. It will ask you for a passphrase, from which an encryption key will be derived using \fIscrypt()\fR. .Sp \&\s-1PCP\s0 doesn't validate the security of the passphrase. +.Sp +Self mode can be explicitly enforced with \fB\-m\fR. .SH "SIGNATURES" .IX Header "SIGNATURES" There are 3 modes for digital signatures available on pcp1: @@ -667,7 +670,7 @@ Pcp may return one of several error codes if it encounters problems. Default vault file where all keys are stored. .SH "EXPERIMENTAL STATUS" .IX Header "EXPERIMENTAL STATUS" -Currently there are a couple of problems which are currently +Currently there are a couple of problems which are unsolved or in the process to be solved. .IP "\fBNo secure native key exchange for store-and-forward systems\fR" 4 .IX Item "No secure native key exchange for store-and-forward systems" @@ -682,7 +685,8 @@ to some key server because in order to encrypt a message, both the recipient \s-1AND\s0 the sender need to have the public key of each other. It would be possible to publish public keys, and attach the senders public key to the encrypted message, but -I'm not sure if such an aproach would be secure enough. +I'm not sure if such an aproach would be secure enough. Pcp +implements this scheme though (refer to the option \-A). .IP "\fBCurve25519 not widely adopted\fR" 4 .IX Item "Curve25519 not widely adopted" At the time of this writing the \s-1ECC\s0 algorithm Curve25519 @@ -693,8 +697,17 @@ been done the kind of exessive crypto analysis as with other .Sp While I, as the author of pcp1 totally trust D.J.Bernstein, this may not be the case for you. +.IP "\fBUnreviewed yet\fR" 4 +.IX Item "Unreviewed yet" +As with every crypto software, pcp has to undergo a couple rounds +of peer review (analysis) in order to be considered secure, trustable +and stable. No any such review has been undertaken on pcp yet. .Sp -In short, I'd suggest not to use it on critical systems yet. +Pcp is a mere fun project aimed at teaching myself better C coding +and crypto. In fact I don't even trust the software myself and I +don't use it for anything remotely serious. +.PP +\&\fBIn short: don \s-1NOT\s0 use this software for production purposes!\fR .SH "INTERNALS" .IX Header "INTERNALS" .SS "\s-1VAULT FORMAT\s0" @@ -808,11 +821,147 @@ Generate a random seed (32 bytes). .IP "\(bu" 4 Generate a Curve25519 encryption keypair from that seed. .PP -So, while both secrets are stored in the sam \s-1PCP\s0 key, they +So, while both secrets are stored in the same \s-1PCP\s0 key, they are otherwise unrelated. If one of them leaks, the other cannot be recalculated from it. .PP Take a look at the function \fB\f(BIpcp_keypairs()\fB\fR for details. +.SS "\s-1PUBLIC KEY EXPORT FORMAT\s0" +.IX Subsection "PUBLIC KEY EXPORT FORMAT" +Exported public and secret keys will be written in a portable +way. Pcp uses \s-1RFC4880\s0 export format for public keys with some +slight modifications: +.IP "\(bu" 4 +Key material is native to libsodium/pcp and not specified in the +rfc for curve25519/ed25519. Therefore pcp encodes key material doing it like +this: mp|sp|cp +.Sp +where +.Sp +.Vb 3 +\& mp = master keysigning public key (ed25519), 32 bytes +\& sp = signing public key (ed25519), 32 bytes +\& cp = encryption public key (curve25519), 32 bytes +.Ve +.IP "\(bu" 4 +The various cipher (algorithm) id's are unspecified for +libsodium/pcp native ciphers. Therefore they are proprietary to pcp, starting at +33 (22 is the last officially assigned one). Once +those cipher numbers become official, they will be used instead. +.IP "\(bu" 4 +Pcp uses 64 bit integers for timestamps everywhere (ctime, expire, etc), +to be year 2038 safe. Note, that this is a violation of the +\&\s-1RFC\s0 spec. However, said \s-1RFC\s0 have to be modified to fit 2038 +(and beyond) anyways. This applies for the keyfile ctime as +well for the key sig sub fields containing time values. +.IP "\(bu" 4 +The exported public key packet contains a signature. Pcp is +filling out all required fields. A signature has a variable +number of sig sub packets. Pcp uses only these types: +.Sp +.Vb 5 +\& 2 = Signature Creation Time (8 byte) +\& 3 = Signature Expiration Time (8 byte) +\& 9 = Key Expiration Time (8 bytes) +\& 20 = Notation Data (4 byte flags, N bytes name+value) +\& 27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80 +.Ve +.IP "\(bu" 4 +Pcp uses 3 notation fields: +.RS 4 +.ie n .IP """owner"", which contains the owner name, if set" 4 +.el .IP "``owner'', which contains the owner name, if set" 4 +.IX Item "owner, which contains the owner name, if set" +.PD 0 +.ie n .IP """mail"", which contains the emailaddress, if set" 4 +.el .IP "``mail'', which contains the emailaddress, if set" 4 +.IX Item "mail, which contains the emailaddress, if set" +.ie n .IP """serial"", which contains the 32bit serial number" 4 +.el .IP "``serial'', which contains the 32bit serial number" 4 +.IX Item "serial, which contains the 32bit serial number" +.RE +.RS 4 +.RE +.IP "\(bu" 4 +.PD +The actual signature field consists of the blake2 hash of +(mp|sp|cp|keysig) followed by the nacl signature. However, pcp +does not put an extra 16 byte value of the hash, since the nacl +signature already contains the full hash. So, an implementation +could simply pull the fist 16 bytes of said hash to get +the same result if desired. +.IP "\(bu" 4 +The mp keypair will be used for signing. The recipient can +verify the signature, since mp is included. +.IP "\(bu" 4 +While pcp puts expiration dates for the key and the signature +into the export as the rfc demands, it mostly ignores them (yet). +Key expiring is not implemented in \s-1PCP\s0 yet. +.IP "\(bu" 4 +We use big-endian always. +.IP "\(bu" 4 +Unlike \s-1RC4880\s0 public key exports, pcp uses Z85 encoding if +armoring have been requested by the user. Armored output has +a header and a footer line, however they are ignored by the +parser and are therefore optional. Newlines, if present, are +optional as well. +.Sp +http://tools.ietf.org/html/rfc4880#section\-5.2.3 +.IP "\(bu" 4 +The key sig blob will be saved in the Vault unaltered during +import, so pcp is able to verify the signature at will anytime. When exporting +a foreign public key, pcp just puts out that key sig blob to the +export untouched. +.IP "\(bu" 4 +Currently \s-1PCP\s0 only supports self-signed public key exports. +.IP "\(bu" 4 +Pcp only supports one key signature per key. However, it would be easily +possible to support foreign keysigs as well in the future. +.PP +So, a full pubkey export looks like this +.PP +.Vb 8 +\& version +\& ctime +\& cipher +\& 3 x raw keys \e +\& sigheader > calculate hash from this +\& sigsubs (header+data) / +\& hash +\& signature +.Ve +.SS "\s-1SECRET KEY EXPORT FORMAT\s0" +.IX Subsection "SECRET KEY EXPORT FORMAT" +Secret keys are exported in a proprietary format. +.PP +The exported binary blob is symmetrically encrypted using the \s-1NACL\s0 +function \fIcrypto_secret()\fR. The passphrase will be used to derive an +encryption key using the \s-1STAR\s0 function \fIscrypt()\fR. +.PP +The binary data before encryption consists of: +.PP +.Vb 10 +\& ED25519 master signing secret +\& Curve25519 encryption secret +\& ED25519 signing secret +\& ED25519 master signing public +\& Curve25519 encryption public +\& ED25519 signing public +\& Optional notations, currently supported are the \*(Aqowner\*(Aq and \*(Aqmail\*(Aq attributes. +\& If an attribute is empty, the len field is zero. +\& \-# len(VAL) (2 byte uint) +\& \-# VAL (string without trailing zero) +\& 8 byte creation time (epoch) +\& 4 byte key version +\& 4 byte serial number +.Ve +.PP +The encrypted cipher will be prepended with the random nonce used +to encrypt the data and looks after encryption as such: +.PP +.Vb 1 +\& Nonce | Cipher +.Ve .SS "\s-1ENCRYPTED OUTPUT FORMAT\s0" .IX Subsection "ENCRYPTED OUTPUT FORMAT" The encryption protocol used by \s-1PCP\s0 uses mostly standard @@ -1080,6 +1229,142 @@ files and signatures \- at least their binary versions \- should be exchangable. this is a work in progress and might not work under all circumstances. Also there's currently no shared key format between pbp and pcp. However, it is possible to export and import pbp keys from/to pcp. +.SH "JSON ENCODING SUPPORT" +.IX Header "JSON ENCODING SUPPORT" +If pcp have been compiled with \fB\-\-with\-json\fR (which requires the libjansson +library), then it supports \s-1JSON\s0 objects as input and output with the following +functions: +.IP "public key export" 4 +.IX Item "public key export" +.PD 0 +.IP "secret key export" 4 +.IX Item "secret key export" +.IP "whole vault export" 4 +.IX Item "whole vault export" +.IP "public key import" 4 +.IX Item "public key import" +.IP "secret key import" 4 +.IX Item "secret key import" +.PD +.PP +\&\s-1JSON\s0 support can be used either with the commandline tool \fBpcp1\fR or programmatically +using the C, \*(C+ or Python \s-1API.\s0 +.SS "\s-1USING JSON FROM THE C API\s0" +.IX Subsection "USING JSON FROM THE C API" +In order to use \s-1JSON\s0 all you've got to do is to switch a context flag: +.PP +.Vb 2 +\& PCPCTX *ptx = ptx_new(); +\& ptx\->json = 1; +.Ve +.PP +That all to it. Now any function normally used for key import and export works +with \s-1JSON,\s0 just fill the \fBBuffer\fR object with a \s-1JSON\s0 string for imports or +fetch the Buffer content of an export function as a string. +.SS "\s-1USING JSON FROM THE COMMANDLINE\s0" +.IX Subsection "USING JSON FROM THE COMMANDLINE" +In order to use \s-1JSON\s0 on the commandline, add \fB\-j\fR. This can be used in +conjunction with the following options: +.IP "\fB\-p\fR" 4 +.IX Item "-p" +Public key export. +.IP "\fB\-s\fR" 4 +.IX Item "-s" +Secret key export. +.IP "\fB\-K\fR" 4 +.IX Item "-K" +Public and secret key import. +.IP "\fB\-t\fR" 4 +.IX Item "-t" +Text view mode (aka inspect mode). +.PP +The \fB\-z\fR and \fB\-Z\fR options are ignored in \s-1JSON\s0 mode. +.SS "\s-1JSON OBJECT STRUCTURE\s0" +.IX Subsection "JSON OBJECT STRUCTURE" +\fI\s-1JSON PUBLIC KEY \s0(pcp1 \-p \-j)\fR +.IX Subsection "JSON PUBLIC KEY (pcp1 -p -j)" +.PP +The \s-1JSON\s0 object for a public key looks like this: +.PP +.Vb 10 +\& { +\& "id": "6BF2980419E0986A", +\& "owner": "tom", +\& "mail": "tom@local", +\& "ctime": 1436170865, +\& "expire": 1467706865, +\& "version": 6, +\& "serial": 1509801135, +\& "type": "public", +\& "cipher": "CURVE25519\-ED25519\-POLY1305\-SALSA20", +\& "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01", +\& "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2", +\& "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e", +\& "signature": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45[..]" +\& } +.Ve +.PP +Actually the field \fBsignature\fR contains the whole encoded public key. +.PP +Fields containing byte arrays are hex encoded. +.PP +Numbers are represented as literal integers. +.PP +\fI\s-1JSON SECRET KEY \s0(pcp1 \-s \-j)\fR +.IX Subsection "JSON SECRET KEY (pcp1 -s -j)" +.PP +The \s-1JSON\s0 object for a public key looks like this: +.PP +.Vb 10 +\& { +\& "id": "6BF2980419E0986A", +\& "owner": "tom", +\& "mail": "tom@local", +\& "ctime": 1436170865, +\& "expire": 1467706865, +\& "version": 6, +\& "serial": 1509801135, +\& "type": "secret", +\& "cipher": "CURVE25519\-ED25519\-POLY1305\-SALSA20", +\& "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01", +\& "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2", +\& "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e", +\& "secrets": "ad5ce150f3cd7bffa299d4db5bf3d26ae56c3808ccba7[..]", +\& "nonce": "858ef9870fc8f39903cfb281d697ca29a935d2ae929fa4ea" +\&} +.Ve +.PP +As you can see that's pretty identical to a public key json object beside the +\&\fBsecrets\fR and \fBnonce\fR fields. The \fBsecrets\fR field contains the encrypted +secret key material. Pcp does not support exporting a secret key unencrypted. +.PP +The \fBnonce\fR is required for a later import and shall not be changed or +decoupled from \fBsecrets\fR. This may change in the future. +.PP +\fI\s-1JSON VAULT \s0(pcp1 \-t)\fR +.IX Subsection "JSON VAULT (pcp1 -t)" +.PP +The \s-1JSON\s0 object for the vault looks like this: +.PP +.Vb 8 +\& { +\& "keyvaultfile": "/home/tom/.pcpvault", +\& "version": 2, +\& "checksum": "27b583dc2dacf5ccc874b7be3a39748d107c6b9e9f9d473f1c716a94561ef793", +\& "secretkeys": 1, +\& "publickey": 3, +\& "keys": [] +\& } +.Ve +.PP +The field \fBkeys\fR is an array containing one or more of the already +described key objects. +.PP +\fI\s-1JSON PROGRAM OUTPUT\s0\fR +.IX Subsection "JSON PROGRAM OUTPUT" +.PP +Currently pcp does not support \s-1JSON\s0 program output, that is, success or +error messages on \s-1STDERR\s0 are not encoded as json. This may change in the future. .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2013\-2015 by T.v.Dein diff --git a/man/pcp1.html b/man/pcp1.html new file mode 100644 index 0000000..c1d20ee --- /dev/null +++ b/man/pcp1.html @@ -0,0 +1,1218 @@ + + + + + + + + + + + + + + + +

NAME

+ +

Pretty Curved Privacy - File encryption using eliptic curve cryptography.

+ +

SYNOPSIS

+ +
  Usage: pcp1 [ --help          | --version ]
+              [ --keygen        | --listkeys      | --remove-key | --edit-key ]
+              [ --export-public | --export-secret | --import ]
+              [ --encrypt       | --decrypt       ]
+              [ --sign          | --check-signature ]
+              [ arguments ]
+  
+  General Options:
+  -h --help                 Print this help message.
+     --version              Print program version.
+  -D --debug                Enable debug output.
+  -v --verbose              Enable verbose output.
+  -V --vault <vaultfile>    Specify an alternate vault file.
+  -O --outfile <file>       Output file. STDOUT if unspecified.
+  -I --infile <file>        Input file. STDIN if unspecified.
+  -X --password-file <file> Read passphrase from <file>.
+  -i --keyid <id>           Specify a key id for various operations.
+  -r --recipient <string>   Specify a recpipient, multiple allowed.
+  -t --text                 Print textual representation of ojects.
+  
+  Keymanagement Options:
+  -k --keygen               Generate new key pair.
+  -l --listkeys             List all keys stored in your vault.
+  -R --remove-key           Remove a key from the vault.
+  -s --export-secret        Export a secret key.
+  -p --export-public        Export a public key.
+  -K --import               Import a secret or public key.
+  -F --export-format <fmt>  Specify exportformat, either 'pbp' or 'pcp'.
+                            'pcp' is the default if unspecified.
+  -j --json                 Enable JSON output (with -t, -p, -s and -K).
+  
+  Encryption Options:
+  -e --encrypt              Asym-Encrypt a message. If none of -i or -r
+                            has been given, encrypt the message symetrically.
+  -A --anonymous            Use anonymous sender key pair.
+  -M --add-myself           Add you primary pub key to list of recipients.
+  -m --encrypt-sym          Symetrically encrypt a message.
+  -d --decrypt              Decrypt a message.
+  
+  Signature Options:
+  -g --sign                 Create a signature of a file.
+  -c --check-signature      Verify a signature of a file.
+  -f --sigfile <file>       Write or check a detached signature file.
+  
+  Encoding Options:
+  -z --z85-encode           Armor with Z85 encoding.
+  
+  Arguments:
+  Extra arguments after options are treated as filenames or
+  recipients, depending on operation mode.
+=head1 OPTIONS
+ 
+ Usage: pcp1 [options]
+ 
+ General Options:
+ -V --vault <vaultfile>    Specify an alternate vault file.
+                           The deault vault is ~/.pcpvault.
+ -O --outfile <file>       Output file. If not specified, stdout
+                           will be used.
+ -I --infile <file>        Input file. If not specified, stdin
+                           will be used.
+ -X --password-file <file> Read passphrase from <file>. If <file>
+                           is -, read from stdin. This takes
+                           precedence over other uses of stdin
+                           elsewhere, see below for more details.
+ -i --keyid <id>           Specify a key id to import/export.
+ -r --recipient <string>   Specify a recpipient, used for public
+                           key export and encryption.
+ -t --text                 Print textual representation of some
+                           item. Specify -V to get info about a
+                           vault, -i to get info about a key id
+                           installed in the vault or -I in which
+                           case it determines itself what kind of
+                           file it is.
+ -h --help                 Print this help message.
+    --version              Print program version.
+ -D --debug                Enable debug output.
+ -v --verbose              Enable verbose output.
+
+ Keymanagement Options:
+ -k --keygen               Generate a CURVE25519 secret key. If
+                           the generated key is the first one in
+                           your vault, it will become the primary
+                           secret key. If an output file (-O) has
+                           been specified, don't store the generated
+                           key to the vault but export it to the
+                           file instead. You will be asked for
+                           an owner, mail and a passphrase. If you
+                           leave the passphrase empty, the key will
+                           be stored unencrypted.
+ -l --listkeys             List all keys currently stored in your
+                           vault. Only the key id's and some info
+                           about the keys will be printed, not the
+                           actual keys.
+ -L --listkeys-verbose     Display a more verbose key listing
+ -l -v                     including signature fingerprint, key
+                           fingerprint, checksum and the like.
+ -R --remove-key           Remove a key from the vault. Requires
+                           option -i <keyid>.
+ -s --export-secret        Export a secret key. If your vault only
+                           contains one secret key, this one will
+                           be exported. If a key id have been
+                           specified (-i), this one will be used.
+                           If there are more than one secret keys
+                           in the vault and no key id has been
+                           given, export the primary secret key.
+                           Use -O to export to a file.
+ -p --export-public        Export a public key. If no key id have
+    --export               been specified, the public part of your
+                           primary secret key will be exported.
+                           Use -O to export to a file.
+ -K --import               Import a key. pcp determines automatically
+    --import-key           the key type and encodingg. Use -I to import
+                           from a file.
+ -F --format               Export the key in a particular format.
+                           Currently supported: pcp and pbp.
+ -j --json                 enable JSON output. Can be used with info
+                           output (-t) and key export (-p and -s).
+                           and import (-K).
+ 
+ Encryption Options:
+ -e --encrypt              Asym-Encrypt a message. Read from stdin or
+                           specified via -I. Output will be written
+                           to stdout or the file given with -O.
+                           If a keyid (-i) has been
+                           given, use that public key for encryption.
+                           If one or more recipient (-r) has been given,
+                           encrypt the message for all recipients
+                           asymetrically, given there are matching
+                           public keys installed in the vault for them.
+                           If none of -i or -r has been given, encrypt
+                           the message symetrically. This is the same
+                           as -m (self-encryption mode).
+                           Add -z to ascii armor the output using Z85.
+ -A --anonymous            Use anonymous sender key pair instead of
+                           your own primary key pair. In this mode the
+                           recipient doesn't need to have your public
+                           key.
+ -m --encrypt-sym          Sym-Encrypt a message. Specify -I and/or
+                           -O for input/output file. You will be asked
+                           for a passphrase. No key material will
+                           be used. Same as -e without -r and -i.
+ -M --add-myself           Add yourself to list of recipients in asymmetric
+                           encryption mode, so that you can decrypt it as
+                           well.
+ -d --decrypt              Decrypt a message. Read from stdin or
+                           specified via -I. Output to stdout or
+                           written to the file specified via -O.
+                           The primary secret key will be used for
+                           decryption, if there is no primary and
+                           just one secret key in the vault, this
+                           one will be used. Otherwise you'll have
+                           to specify the keyid (-i) of the key.
+                           You need to have the public key of the
+                           sender installed in your vault.
+                           If the input is self-encrypted (symetrically)
+                           a passphrase will be requested.
+ 
+ Signature Options:
+ -g --sign                 Create a signature of file specified with
+                           -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.
+ -f --sigfile <file>       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 -f <sigfile>).
+ 
+ Encoding Options:
+ -z --z85-encode           Encode (armor) something to Z85 encoding.
+ -a --armor                If used with encryption or singing operation
+    --textmode             encode its output. Otherwise encode a plain
+                           file. Use -I and -O respectively, otherwise it
+                           uses stdin/stdout.
+ -Z --z85-decode           Decode (dearmor) something from Z85 encoding.
+                           Use -I and -O respectively, otherwise it
+                           uses stdin/stdout
+ 
+ +

DESCRIPTION

+ +

Pretty Curved Privacy (pcp1) is a commandline utility which can be used to encrypt files. pcp1 uses eliptc curve cryptography for encryption (CURVE25519 by Dan J. Bernstein). While CURVE25519 is no worldwide accepted standard it hasn't been compromised by the NSA - which might be better, depending on your point of view.

+ +

Caution: since CURVE25519 is no accepted standard, pcp1 has to be considered as experimental software. In fact, I wrote it just to learn about the curve and see how it works.

+ +

Beside some differences it works like GNUPG. So, if you already know how to use gpg, you'll feel almost home.

+ +

QUICKSTART

+ +

Lets say, Alicia and Bobby want to exchange encrypted messages. Here's what the've got to do.

+ +

First, both have create a secret key:

+ +
 Alicia                             Bobby
+ pcp1 -k                            pcp1 -k
+ +

After entering their name, email address and a passphrase to protect the key, it will be stored in their vault file (by default ~/.pcpvault).

+ +

Now, both of them have to export the public key, which has to be imported by the other one. With pcp you can export the public part of your primary key, but the better solution is to export a derived public key especially for the recipient:

+ +
 Alicia                             Bobby
+ pcp1 -p -r Bobby -O alicia.pub     pcp1 -p -r Alicia -O bobby.pub
+ +

They've to exchange the public key somehow (which is not my problem at the moment, use ssh, encrypted mail, whatever). Once exchanged, they have to import it:

+ +
 Alicia                             Bobby
+ pcp1 -K -I bobby.pub               pcp1 -K -I alicia.pub
+ +

They will see a response as this when done:

+ +
 key 0x29A323A2C295D391 added to .pcpvault.
+ +

Now, Alicia finally writes the secret message, encrypts it and sends it to Bobby, who in turn decrypts it:

+ +
 Alicia                             Bobby
+ echo "Love you, honey" > letter
+ pcp1 -e -r Bobby -I letter -O letter.asc
+ cat letter.asc | mail bobby@foo.bar
+
+                                    pcp1 -d -I letter.asc | less
+ +

And that's it.

+ +

Please note the big difference to GPG though: both Alicia AND Bobby have to enter the passphrase for their secret key! That's the way CURVE25519 works: you encrypt a message using your secret key and the recipients public key and the recipient does the opposite, he uses his secret key and your public key to actually decrypt the message.

+ +

Oh - and if you're wondering why I named them Alicia and Bobby: I was just sick of Alice and Bob. We're running NSA-free, so we're using other sample names as well.

+ +

FILES AND PIPES

+ +

Pcp behaves like any other unix tool. If not otherwise specified it will read input from standard input (STDIN) and print output to standard output (STDOUT). For instance:

+ +
 pcp1 -e -O output
+ +

will read the text to be encrypted from standard input, because -I has not been specified. It works the same with -O:

+ +
 pcp1 -e -I myfile
+ +

In this case the encrypted result will be written to standard output.

+ +

Therefore it is possible to use pcp within pipes. Another more realistic example:

+ +
 ssh remote cat file | pcp1 -ez | mailx -s 'as requested' bob@somewhere
+ +

here we encrypt a file symmetrically without downloading it from a remote ssh server and sending the encrypted result via email to someone.

+ +

The behavior is the same with any other functionality where files are involved like importing or exporting keys. However, there's one exception: If the option -X (--password-file) has been used and is set to -, then this will take precedence over any other possible use of standard input. So if you want to encrypt something and don't specify an input file you cannot use -X -, and vice versa. IF you use -X - the passphrase will be read from standard input, which then can't be used further for input files elsewhere. Pcp will exit with an error in such a case.

+ +

PCP1 KEYS

+ +

pcp1 keys are stored in a binary file, called the vault. It's by default located in ~/.pcpvault but you can of course specify another location using the -V option.

+ +

There are two kinds of keys: secret and public keys. In reality a secret key always includes its public key. Both types of keys can be exported to files and transfered to other people who can then import them. You should usually only do this with public keys though.

+ +

There is a primary secret key which will always used for operations when no keyid has been specified. However, you may have as many secret keys in your vault as you like.

+ +

Each key can be identified using its keyid which looks like this:

+ +
 0xD49119E85266509F
+ +

A public key exported from a secret key will have the same keyid as the secret key.

+ +

If you just want to know details about a key or the vault, use the -t option.

+ +

ENCRYPTION

+ +

There are 3 modes of encryption available in pcp1:

+ +
+ +
Standard public key encryption
+
+ +

In this mode, which is the default, a public key as specified with -i or -r and your primary secret key will be used for encryption.

+ +

Example command:

+ +
 pcp1 -e -i 0x2BD734B15CE2722D -I message.txt -O message.asc
+ +

Here we didn't specify a recipient. Therefore the public key given with -i will be used directly.

+ +

Another example:

+ +
 pcp1 -e -r Bobby -r McCoy -I message.txt -O message.asc
+ +

As you can see, it is also possible to encrypt a message for multiple recipients.

+ +
+
Anonymous public key encryption
+
+ +

In anonymous mode a random generated keypair will be used on the sender side. This way the recipient doesn't have to have your public key.

+ +

Example command:

+ +
 pcp1 -r -r Bobby -A -I message.txt -O message.asc
+ +

The public key part of the generated key pair will be included in the output, which potentiall lessens security. Use with care and avoid this mode when possible.

+ +
+
Self encryption mode
+
+ +

You can also encrypt a file symetrically. No public key material will be used in this mode.

+ +

While this works, the security of it totally depends on the strength of the passphrase used for encryption.

+ +

Example command:

+ +
 pcp1 -e -I message.txt -O cipher.z85
+ +

As you can see we didn't specify any recipients (-i or -r) and therefore pcp1 operates in self mode encryption. It will ask you for a passphrase, from which an encryption key will be derived using scrypt().

+ +

PCP doesn't validate the security of the passphrase.

+ +

Self mode can be explicitly enforced with -m.

+ +
+
+ +

SIGNATURES

+ +

There are 3 modes for digital signatures available on pcp1:

+ +
+ +
Standard NACL binary signatures
+
+ +

In this mode, which is the default, an ED25519 signature will be calculated from a BLAKE2 hash of the input file content. Both the original file content plus the signature will be written to the output file.

+ +

Example:

+ +
 pcp1 -g -I message.txt -O message.asc -g
+ +

You will be asked for the passphrase to access your primary secret key. The output file will be a binary file.

+ +
+
Armored NACL signatures
+
+ +

While this mode does the very same calculations, the output slightly differs. The output file will be marked as a signature file, the signature itself will be appended with its own headers and Z85 encoded.

+ +

Example:

+ +
 pcp1 -g -I message.txt -O message.asc -g -z
+ +

You will be asked for the passphrase to access your primary secret key. The output file will be a text file.

+ +
+
Detached NACL signatures
+
+ +

In some cases you will need to have the signature separated from the original input file, e.g. to sign download files. You can generate detached signatures for such purposes. Still, the signature will be calculated the same way as in standard signatures but put out into a separate file. A detached signature file will always be Z85 encoded.

+ +

Example:

+ +
 pcp1 -g -I message.txt -O -g --sigfile message.sig
+ +

Verification by recipient:

+ +
 pcp -c -f message.sig -I message.txt
+ +
+
+ +

SIGNED ENCRYPTION

+ +

Beside pure encryption and signatures pcp1 also supports signed encryption. In this mode an input file will be encrypted and a signature of the encrypted content and encrypted recipients with your primary secret key will be appended.

+ +

The signature is encrypted as well.

+ +

Example:

+ +
 pcp1 -e -g -r Bobby -I README.txt -O README.asc
+ +

Please note the additional -g parameter. The recipient can decrypt and verify the so created data like this:

+ +
 pcp1 -d -I README.asc -o README.txt
+ +

If decryption works, the output file will be written. If signature verification fails you will be informed, but the decrypted output will be left untouched. It is up to you how to react on an invalid signature.

+ +

ALTERNATIVE COMMANDLINES

+ +

You can save typing if you supply additional arguments to pcp after commandline options. Such arguments are treated as filenames or recipients, depending what options you already specified.

+ +

Here is a list of commandlines and their possible alternatives:

+ +
 ORIGINAL                    ALTERNATIVE               DESCRIPTION
+
+ pcp -e -I message -r Bob    pcp -e -r Bob message     use 'message' as inputfile.
+                             pcp -e -I message Bob     use 'Bob' as recipient,
+                                                       multiple recipients supported.
+
+ pcp -d -I crypted           pcp -d crypted            use 'crypted' as inputfile.
+
+ pcp -g -I message           pcp -g message            use 'message' as inputfile.
+
+ pcp -g -I msg -O sig        pcp -g -I msg sig         use 'sig' as outputfile.
+
+ pcp -p -O key.pcp           pcp -p key.pcp            use 'key.pcp' as outputfile.
+
+ pcp -p -O key.pcp -r Bob    pcp -p -O key.pcp Bob     use 'Bob' as recipient.
+
+ pcp -s -O key.pcp           pcp -s key.pcp            use 'key.pcp' as outputfile.
+
+ pcp -s -O key.pcp -r Bob    pcp -s -O key.pcp Bob     use 'Bob' as recipient.
+
+ pcp -K -I alice.pcp         pcp -K alice.pcp          use 'alice.pcp' as keyfile.
+ +

ENVIRONMENT VARIABLES

+ +

pcp respects the following environment variables:

+ +
+ +
PCP_VAULT
+
+ +

Use an alternative vaultfile. The default is ~/.pcpvault and can be overridden with the -V commandline option. If PCP_VAULT is set, this one will be used instead.

+ +
+
PCP_DEBUG
+
+ +

Enable debugging output, where supported. Same as -D.

+ +
+
+ +

EXIT STATUS

+ +

Pcp may return one of several error codes if it encounters problems.

+ +
+ +
0 No problems occurred.
+
+ +
+
1 Generic error code.
+
+ +
+
+ +

FILES

+ +
+ +
~/.pcpvault
+
+ +

Default vault file where all keys are stored.

+ +
+
+ +

EXPERIMENTAL STATUS

+ +

Currently there are a couple of problems which are unsolved or in the process to be solved.

+ +
+ +
No secure native key exchange for store-and-forward systems
+
+ +

Pretty Curved Privacy is a store-and-forward system, it works on files and can't use any cool key exchange protocols therefore. For example there would be CurveCP which guarantees a secure key exchange. But CurveCP cannot be used offline.

+ +

Users have to find other means to exchange keys. That's a pity since with Curve25519 you can't just publish your public key to some key server because in order to encrypt a message, both the recipient AND the sender need to have the public key of each other. It would be possible to publish public keys, and attach the senders public key to the encrypted message, but I'm not sure if such an aproach would be secure enough. Pcp implements this scheme though (refer to the option -A).

+ +
+
Curve25519 not widely adopted
+
+ +

At the time of this writing the ECC algorithm Curve25519 is only rarely used, in most cases by experimental software (such as Pretty Curved Privacy). As far as I know there haven't been done the kind of exessive crypto analysis as with other ECC algorithms.

+ +

While I, as the author of pcp1 totally trust D.J.Bernstein, this may not be the case for you.

+ +
+
Unreviewed yet
+
+ +

As with every crypto software, pcp has to undergo a couple rounds of peer review (analysis) in order to be considered secure, trustable and stable. No any such review has been undertaken on pcp yet.

+ +

Pcp is a mere fun project aimed at teaching myself better C coding and crypto. In fact I don't even trust the software myself and I don't use it for anything remotely serious.

+ +
+
+ +

In short: don NOT use this software for production purposes!

+ +

INTERNALS

+ +

VAULT FORMAT

+ +

The vault file contains all public and secret keys. It's a portable binary file.

+ +

The file starts with a header:

+ +
 +-------------------------------------------+
+ | Field        Size   Description           |
+ +-------------------------------------------+
+ | File ID    |    1 | Vault Identifier 0xC4 |
+ +-------------------------------------------+
+ | Version    |    4 | Big endian, version   |
+ +-------------------------------------------+
+ | Checksum   |   32 | SHA256 Checksum       |
+ +-------------------------------------------+
+ +

The checksum is a checksum of all keys.

+ +

The header is followed by the keys. Each key is preceded by a key header which looks like this:

+ +
 +--------------------------------------------+
+ | Field        Size   Description            |
+ +--------------------------------------------+
+ | Type       |    1 | Key type (S,P,M)       |
+ +--------------------------------------------+
+ | Size       |    4 | Big endian, keysize    |
+ +--------------------------------------------+
+ | Version    |    4 | Big endian, keyversion |
+ +--------------------------------------------+
+ | Checksum   |   32 | SHA256 Key Checksum    |
+ +--------------------------------------------+
+ +

Type can be one of:

+ +
 PCP_KEY_TYPE_MAINSECRET 0x01
+ PCP_KEY_TYPE_SECRET     0x02
+ PCP_KEY_TYPE_PUBLIC     0x03
+ +

The key header is followed by the actual key, see below.

+ +

SECRET KEY FORMAT

+ +

A secret key is a binary structure with the following format:

+ +
 +---------------------------------------------------------+
+ | Field         Size      Description                     |
+ +-------------+--------+----------------------------------+
+ | Public      |     32 | Curve25519 Public Key Part       |
+ +-------------|--------|----------------------------------+
+ | Secret      |     32 | Curve25519 Secret Key Unencrypted|
+ +-------------|--------|----------------------------------+
+ | ED25519 Pub |     32 | ED25519 Public Key Part          |
+ +-------------|--------|----------------------------------+
+ | ED25519 Sec |     64 | ED25519 Secret Key Unencrypted   |
+ +-------------|--------|----------------------------------+
+ | Nonce       |     24 | Nonce for secret key encryption  |
+ +-------------|--------|----------------------------------+
+ | Encrypted   |     48 | Encrypted Curve25519 Secret Key  |
+ +-------------|--------|----------------------------------+
+ | Owner       |    255 | String, Name of Owner            |
+ +-------------|--------|----------------------------------+
+ | Mail        |    255 | String, Email Address            |
+ +-------------|--------|----------------------------------+
+ | ID          |     17 | String, Key ID                   |
+ +-------------|--------|----------------------------------+
+ | Ctime       |      4 | Creation time, sec since epoch   |
+ +-------------|--------|----------------------------------+
+ | Version     |      4 | Key version                      |
+ +-------------|--------|----------------------------------+
+ | Serial      |      4 | Serial Number                    |
+ +-------------|--------|----------------------------------+
+ | Type        |      1 | Key Type                         |
+ +-------------+--------+----------------------------------+
+ +

Some notes:

+ +

The secret key fields will be filled with random data if the key is encrypted. The first byte of it will be set to 0 in that case.

+ +

The key id is a computed JEN Hash of the secret and public key concatenated, put into hex, as a string.

+ +

The key version is a static value, currently 0x2. If the key format changes in the future, this version number will be increased to distinguish old from new keys.

+ +

Exported keys will be encoded in Z85 encoding. When such an exported key is imported, only the actual Z85 encoded data will be used. Header lines and lines starting with whitespace will be ignored. They are only there for convenience.

+ +

Key generation works like this:

+ +
    + +
  • Generate a random seed (32 bytes).

    + +
  • +
  • Generate a ED25519 sigining keypair from that seed.

    + +
  • +
  • Generate a random seed (32 bytes).

    + +
  • +
  • Generate a Curve25519 encryption keypair from that seed.

    + +
  • +
+ +

So, while both secrets are stored in the same PCP key, they are otherwise unrelated. If one of them leaks, the other cannot be recalculated from it.

+ +

Take a look at the function pcp_keypairs() for details.

+ +

PUBLIC KEY EXPORT FORMAT

+ +

Exported public and secret keys will be written in a portable way. Pcp uses RFC4880 export format for public keys with some slight modifications:

+ +
    + +
  • Key material is native to libsodium/pcp and not specified in the rfc for curve25519/ed25519. Therefore pcp encodes key material doing it like this: mp|sp|cp

    + +

    where

    + +
     mp = master keysigning public key (ed25519), 32 bytes
    + sp = signing public key (ed25519), 32 bytes
    + cp = encryption public key (curve25519), 32 bytes
    + +
  • +
  • The various cipher (algorithm) id's are unspecified for libsodium/pcp native ciphers. Therefore they are proprietary to pcp, starting at 33 (22 is the last officially assigned one). Once those cipher numbers become official, they will be used instead.

    + +
  • +
  • Pcp uses 64 bit integers for timestamps everywhere (ctime, expire, etc), to be year 2038 safe. Note, that this is a violation of the RFC spec. However, said RFC have to be modified to fit 2038 (and beyond) anyways. This applies for the keyfile ctime as well for the key sig sub fields containing time values.

    + +
  • +
  • The exported public key packet contains a signature. Pcp is filling out all required fields. A signature has a variable number of sig sub packets. Pcp uses only these types:

    + +
      2 = Signature Creation Time     (8 byte)
    +  3 = Signature Expiration Time   (8 byte)
    +  9 = Key Expiration Time         (8 bytes)
    + 20 = Notation Data               (4 byte flags, N bytes name+value)
    + 27 = Key Flags                   (1 byte, use 0x02, 0x08 and 0x80
    + +
  • +
  • Pcp uses 3 notation fields:

    + +
    + +
    "owner", which contains the owner name, if set
    +
    + +
    +
    "mail", which contains the emailaddress, if set
    +
    + +
    +
    "serial", which contains the 32bit serial number
    +
    + +
    +
    + +
  • +
  • The actual signature field consists of the blake2 hash of (mp|sp|cp|keysig) followed by the nacl signature. However, pcp does not put an extra 16 byte value of the hash, since the nacl signature already contains the full hash. So, an implementation could simply pull the fist 16 bytes of said hash to get the same result if desired.

    + +
  • +
  • The mp keypair will be used for signing. The recipient can verify the signature, since mp is included.

    + +
  • +
  • While pcp puts expiration dates for the key and the signature into the export as the rfc demands, it mostly ignores them (yet). Key expiring is not implemented in PCP yet.

    + +
  • +
  • We use big-endian always.

    + +
  • +
  • Unlike RC4880 public key exports, pcp uses Z85 encoding if armoring have been requested by the user. Armored output has a header and a footer line, however they are ignored by the parser and are therefore optional. Newlines, if present, are optional as well.

    + +

    http://tools.ietf.org/html/rfc4880#section-5.2.3

    + +
  • +
  • The key sig blob will be saved in the Vault unaltered during import, so pcp is able to verify the signature at will anytime. When exporting a foreign public key, pcp just puts out that key sig blob to the export untouched.

    + +
  • +
  • Currently PCP only supports self-signed public key exports.

    + +
  • +
  • Pcp only supports one key signature per key. However, it would be easily possible to support foreign keysigs as well in the future.

    + +
  • +
+ +

So, a full pubkey export looks like this

+ +
    version
+    ctime
+    cipher
+    3 x raw keys             \
+    sigheader                 > calculate hash from this
+       sigsubs (header+data) /
+    hash
+    signature
+ +

SECRET KEY EXPORT FORMAT

+ +

Secret keys are exported in a proprietary format.

+ +

The exported binary blob is symmetrically encrypted using the NACL function crypto_secret(). The passphrase will be used to derive an encryption key using the STAR function scrypt().

+ +

The binary data before encryption consists of:

+ +
 ED25519 master signing secret
+ Curve25519 encryption secret
+ ED25519 signing secret
+ ED25519 master signing public
+ Curve25519 encryption public
+ ED25519 signing public
+ Optional notations, currently supported are the 'owner' and 'mail' attributes.
+  If an attribute is empty, the len field is zero.
+  -# len(VAL) (2 byte uint)
+  -# VAL (string without trailing zero)
+ 8 byte creation time (epoch)
+ 4 byte key version
+ 4 byte serial number
+ +

The encrypted cipher will be prepended with the random nonce used to encrypt the data and looks after encryption as such:

+ +
  Nonce | Cipher
+ +

ENCRYPTED OUTPUT FORMAT

+ +

The encryption protocol used by PCP uses mostly standard libsodium facilities with the exception that PCP uses counter mode (CTR-Mode) for stream encryption.

+ +
 Detailed description:
+ +
+ +
generate a random ephemeral 32 byte key S
+
+ +
+
encrypt it asymetrically for each recipient using a unique nonce (R)
+
+ +
+
encrypt the input file 32k blockwise using the ephemeral key
+
+ +
+ +
for each input block with a size of 32k bytes:
+
+ +
+
generate a random nonce N
+
+ +
+
put the current counter size into the first byte of the nonce
+
+ +
+
put the current counter (starting with 1) into the following byte(s), if larger than 1 byte, in big endian mode
+
+ +
+
encrypt the 32k block using crypto_secretbox() with the nonce N and the ephemeral key S
+
+ +
+
+ +
+
+ +

Symetric encryption works the very same without the recipient stuff.

+ +

Formal format description, asymetric encrypted files:

+ +
 +-----------------------------------------------------------+
+ | Field         Size      Description                       |
+ +-------------+--------+------------------------------------+
+ | Type        |      1 | Filetype, 5=ASYM, 23=SYM, 6=ANON   |
+ +-------------|--------|------------------------------------+
+ | Anon PUB *  |     32 | anon pubkey, only used with type 6 |
+ +-------------|--------|------------------------------------+
+ | Len R *     |      4 | Number of recipients         (*)   |
+ +-------------|--------|------------------------------------+
+ | Recipients *|   R*72 | C(recipient)|C(recipient)... (*)   |
+ +-------------|--------|------------------------------------+
+ | Encrypted   |      ~ | The actual encrypted data          |
+ +-------------|--------|------------------------------------+
+ +

*) not included when doing symetric encryption.

+ +

Recipient field format:

+ +
 +---------------------------------------------------------+
+ | Field         Size      Description                     |
+ +-------------+--------+----------------------------------+
+ | Nonce       |     24 | Random Nonce, one per R          |
+ +-------------|--------|----------------------------------+
+ | Cipher      |     48 | S encrypted with PK or R         |
+ +-------------|--------|----------------------------------+
+ +

R is generated using crypto_box() with the senders secret key, the recipients public key and a random nonce.

+ +

Pseudocode:

+ +
 R = foreach P: N | crypto_box(S, N, P, SK)
+ L = len(R)
+ T = 5
+ write (T | L | R)
+ foreach I: write (N | crypto_secret_box(I, N, S))
+ +

where P is the public key of a recipient, SK is the senders secret key, R is the recipient list, L is the number of recipients, T is the filetype header, I is a block of input with a size of 32k, N is a nonce (new per block) and S the symmetric key.

+ +

If using anonymous encryption, the sender generates a ephemeral key pair, uses the secret part of it to generate R. The public part will be included with the output (right after the file type. In this mode a recipient is not required to have the public key of the sender.

+ +

The encrypted output maybe Z85 encoded. In this case the Z85 encoding will be done blockwise with blocks of 16k bytes. The decoded content inside will be as described above.

+ +

SIGNATURE FORMAT

+ +

There are different signature formats. Standard binary NACL signatures have the following format:

+ +
 +---------------------------------------------------------+
+ | Field         Size      Description                     |
+ +-------------+--------+----------------------------------+
+ | Content     |      ~ | Original file content            |
+ +-------------|--------|----------------------------------+
+ | \nnacl-     |      6 | Offset separator                 |
+ +-------------|--------|----------------------------------+
+ | Hash        |     64 | BLAKE2 hash of the content       |
+ +-------------|--------|----------------------------------+
+ | Signature   |     64 | ED25519 signature of BLAKE2 Hash |
+ +-------------|--------|----------------------------------+
+ +

The actual signature is not a signature over the whole content of an input file but of a BLAKE2 hash of the content.

+ +

Pseudo code:

+ +
 H = crypto_generichash(C)
+ C | O | H | crypto_sign(H, S)
+ +

where C is the message (content), H is the blake2 hash, O is the offset separator and S is the secret signing key of the sender.

+ +

Armored signatures have the following format:

+ +
 ----- BEGIN ED25519 SIGNED MESSAGE -----
+ Hash: Blake2
+ 
+ MESSAGE
+ 
+ ----- BEGIN ED25519 SIGNATURE -----
+  Version: PCP v0.2.0
+ 
+ 195j%-^/G[cVo4dSk7hU@D>NT-1rBJ]VbJ678H4I!%@-)bzi>zOba5$KSgz7b@R]A0!kL$m
+ MTQ-1DW(e1mma(<jH=QGA(VudgAMXaKF5AGo65Zx7-5fuMZt&:6IL:n2N{KMto*KQ$:J+]d
+ dp1{3}Ju*M&+Vk7=:a=J0}B
+ ------ END ED25519 SIGNATURE ------
+ +

The Z85 encoded signature at the end contains the same signature contents as the binary signature outlined above (hash+sig).

+ +

SIGNED ENCRYPTION FORMAT

+ +

Signed encrypted files are in binary form only. The first part is the standard encrypted file as described in ENCRYPTED OUTPUT FORMAT followed by the binary encrypted signature described in SIGNATURE FORMAT without the offset separator.

+ +

However, not only the hash of the file content will be signed but the recipient list described in ENCRYPTED OUTPUT FORMAT as well. A valid recipient is therefore not able to re-encrypt the decrypted message, append the original signature and send it to other recipients. The signature would not match since the recipient list differs and so recipients know that the signature is forged.

+ +

Formal file description of sign+encrypt format:

+ +
 +---------------------------------------------------------+
+ | Field         Size      Description                     |
+ +-------------+--------+----------------------------------+
+ | Type        |      1 | Filetype, 5=ASYM, 23=SYM         |
+ +-------------|--------|----------------------------------+
+ | Len R       |      4 | Number of recipients         (*) |
+ +-------------|--------|----------------------------------+
+ | Recipients  |   R*72 | C(recipient)|C(recipient)... (*) |
+ +-------------|--------|----------------------------------+
+ | Encrypted   |      ~ | The actual encrypted data        |
+ +-------------|--------|----------------------------------+
+ | Signature   |      ~ | Encrypted signature(*)           |
+ +-------------|--------|----------------------------------+
+ +

As usual the encrypted signature consists of a nonce and the actual cipher, which is computed symmetrically (see above) from the following clear signature.

+ +

Before encryption the signature format is:

+ +
 +---------------------------------------------------------+
+ | Field         Size      Description                     |
+ +-------------+--------+----------------------------------+
+ | Hash        |     64 | BLAKE2 hash of content+R (*)     |
+ +-------------|--------|----------------------------------+
+ | Signature   |     64 | ED25519 signature of BLAKE2 Hash |
+ +-------------|--------|----------------------------------+
+ +

where R is: C(recipient)|C(recipient)... (see ENCRYPTED OUTPUT FORMAT).

+ +

Pseudocode:

+ +
 N | crypto_secret_box( crypto_sign( crypto_generichash( M + R, SK ) ), N, S)
+ +

where N is the nonce, M the message, R the recipient list, SK is the senders secret signing key and S the symmetric key.

+ +

Z85 ENCODING

+ +

pcp1 uses Z85 to encode binary data (if requested with -z) such as encrypted data, exported keys or armored signatures.

+ +

Encoded data is always enclosed by a header and a footer and may have any number of comments. Example:

+ +
 ----- PCP ENCRYPTED FILE -----
+ Version: PCP 0.2.1
+ 246ge]+yn={<I&&Z%(pm[09lc5[dx4TZALi/6cjVe)Kx5S}7>}]Xi3*N3Xx34Y^0rz:r.5j
+ v#6Sh/m3XKwy?VlA+h8ks]9:kVj{D[fd7]NA]T-(ne+xo!W5X5-gIUWqM
+ ----- END PCP ENCRYPTED FILE -----
+ +

However, the parser tries to be as tolerant as possible. It also accepts Z85 encoded data without headers or without newlines, empty lines or lines containing a space are ignored as well as comments. Empty comments are not allowed.

+ +

Z85 PADDING

+ +

PCP uses a custom padding scheme. Z85 input data size must be a multiple of 4. To fulfill this requirement, PCP padds the input with zeros as neccessary. To tell the decoder if padding took place and how much zeros have been added, PCP adds another 4 bytes after each Z85 encoded block, from the last one which contains the number of zeros used for padding, even if the input hasn't been padded.

+ +

Z85 BACKGROUND

+ +

The Z85 encoding format is described here: http://rfc.zeromq.org/spec:32. It's part of ZeroMQ (http://zeromq.org). Z85 is based on ASCII85 with a couple of modifications (portability, readability etc).

+ +

To fulfil the requirements of the ZeroMQ Z85 functions, pcp1 does some additional preparations of raw input before actually doing the encoding, since the input for zmq_z85_encode() must be divisible by 4. Therefore we pad the input with zeroes and remove them after decoding.

+ +

Trying to use another tool to decode an Z85 encoded string produced by z85, might not work therefore, unless the tool takes the padding scheme outlined above into account.

+ +

Z85 encoding and decoding can be used separately as well to work with files. Examples:

+ +

Encode some file to Z85 encoding:

+ +

pcp1 -z -I file -O file.z85

+ +

Reverse the process:

+ +

pcp1 -Z -I file.z85 -O file

+ +

PBP COMPATIBILITY

+ +

PCP tries to be fully compatible with PBP (https://github.com/stef/pbp). Encrypted files and signatures - at least their binary versions - should be exchangable. However, this is a work in progress and might not work under all circumstances. Also there's currently no shared key format between pbp and pcp. However, it is possible to export and import pbp keys from/to pcp.

+ +

JSON ENCODING SUPPORT

+ +

If pcp have been compiled with --with-json (which requires the libjansson library), then it supports JSON objects as input and output with the following functions:

+ +
+ +
public key export
+
+ +
+
secret key export
+
+ +
+
whole vault export
+
+ +
+
public key import
+
+ +
+
secret key import
+
+ +
+
+ +

JSON support can be used either with the commandline tool pcp1 or programmatically using the C, C++ or Python API.

+ +

USING JSON FROM THE C API

+ +

In order to use JSON all you've got to do is to switch a context flag:

+ +
 PCPCTX *ptx = ptx_new();
+ ptx->json = 1;
+ +

That all to it. Now any function normally used for key import and export works with JSON, just fill the Buffer object with a JSON string for imports or fetch the Buffer content of an export function as a string.

+ +

USING JSON FROM THE COMMANDLINE

+ +

In order to use JSON on the commandline, add -j. This can be used in conjunction with the following options:

+ +
+ +
-p
+
+ +

Public key export.

+ +
+
-s
+
+ +

Secret key export.

+ +
+
-K
+
+ +

Public and secret key import.

+ +
+
-t
+
+ +

Text view mode (aka inspect mode).

+ +
+
+ +

The -z and -Z options are ignored in JSON mode.

+ +

JSON OBJECT STRUCTURE

+ +

JSON PUBLIC KEY (pcp1 -p -j)

+ +

The JSON object for a public key looks like this:

+ +
 {
+    "id": "6BF2980419E0986A",
+    "owner": "tom",
+    "mail": "tom@local",
+    "ctime": 1436170865,
+    "expire": 1467706865,
+    "version": 6,
+    "serial": 1509801135,
+    "type": "public",
+    "cipher": "CURVE25519-ED25519-POLY1305-SALSA20",
+    "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01",
+    "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2",
+    "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e",
+    "signature": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45[..]"
+ }
+ +

Actually the field signature contains the whole encoded public key.

+ +

Fields containing byte arrays are hex encoded.

+ +

Numbers are represented as literal integers.

+ +

JSON SECRET KEY (pcp1 -s -j)

+ +

The JSON object for a public key looks like this:

+ +
 {
+    "id": "6BF2980419E0986A",
+    "owner": "tom",
+    "mail": "tom@local",
+    "ctime": 1436170865,
+    "expire": 1467706865,
+    "version": 6,
+    "serial": 1509801135,
+    "type": "secret",
+    "cipher": "CURVE25519-ED25519-POLY1305-SALSA20",
+    "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01",
+    "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2",
+    "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e",
+    "secrets": "ad5ce150f3cd7bffa299d4db5bf3d26ae56c3808ccba7[..]",
+    "nonce": "858ef9870fc8f39903cfb281d697ca29a935d2ae929fa4ea"
+}
+ +

As you can see that's pretty identical to a public key json object beside the secrets and nonce fields. The secrets field contains the encrypted secret key material. Pcp does not support exporting a secret key unencrypted.

+ +

The nonce is required for a later import and shall not be changed or decoupled from secrets. This may change in the future.

+ +

JSON VAULT (pcp1 -t)

+ +

The JSON object for the vault looks like this:

+ +
  {
+    "keyvaultfile": "/home/tom/.pcpvault",
+    "version": 2,
+    "checksum": "27b583dc2dacf5ccc874b7be3a39748d107c6b9e9f9d473f1c716a94561ef793",
+    "secretkeys": 1,
+    "publickey": 3,
+    "keys": []
+ }
+ +

The field keys is an array containing one or more of the already described key objects.

+ +

JSON PROGRAM OUTPUT

+ +

Currently pcp does not support JSON program output, that is, success or error messages on STDERR are not encoded as json. This may change in the future.

+ +

COPYRIGHT

+ +

Copyright (c) 2013-2015 by T.v.Dein <tom AT vondein DOT org>

+ +

ADDITIONAL COPYRIGHTS

+ +
+ +
ZeroMQ Z85 encoding routine
+
+ +
 Copyright (c) 2007-2013 iMatix Corporation
+ Copyright (c) 2009-2011 250bpm s.r.o.
+ Copyright (c) 2010-2011 Miru Limited
+ Copyright (c) 2011 VMware, Inc.
+ Copyright (c) 2012 Spotify AB
+ +
+
Tarsnap readpass helpers
+
+ +
 Copyright 2009 Colin Percival
+ +
+
jen_hash() hash algorithm
+
+ +
 Bob Jenkins, Public Domain.
+ +
+
UTHASH hashing macros
+
+ +
 Copyright (c) 2003-2013, Troy D. Hanson
+ +
+
Random art image from OpenSSH keygen
+
+ +
 Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
+
+ Comitted by Alexander von Gernler in rev 1.7.
+ +
+
+ +

Every incorporated source code is opensource and licensed under the GPL as well.

+ +

AUTHORS

+ +

T.v.Dein <tom AT vondein DOT org>

+ +

LICENSE

+ +

Licensed under the GNU GENERAL PUBLIC LICENSE version 3.

+ +

HOME

+ +

The homepage of Pretty Curved Privacy can be found on http://www.daemon.de/PrettyCurvedPrivacy. The source is on Github: https://github.com/TLINDEN/pcp

+ + + + + + + diff --git a/man/pcp1.pod b/man/pcp1.pod index 42c6932..a2207af 100644 --- a/man/pcp1.pod +++ b/man/pcp1.pod @@ -35,7 +35,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography. -K --import Import a secret or public key. -F --export-format Specify exportformat, either 'pbp' or 'pcp'. 'pcp' is the default if unspecified. - -j --json Enable JSON output (with -t, -p and -s). + -j --json Enable JSON output (with -t, -p, -s and -K). Encryption Options: -e --encrypt Asym-Encrypt a message. If none of -i or -r @@ -124,6 +124,7 @@ Pretty Curved Privacy - File encryption using eliptic curve cryptography. Currently supported: pcp and pbp. -j --json enable JSON output. Can be used with info output (-t) and key export (-p and -s). + and import (-K). Encryption Options: -e --encrypt Asym-Encrypt a message. Read from stdin or @@ -346,7 +347,7 @@ Another example: As you can see, it is also possible to encrypt a message for multiple recipients. -=item B +=item B In anonymous mode a random generated keypair will be used on the sender side. This way the recipient doesn't have to have your public @@ -378,6 +379,8 @@ an encryption key will be derived using scrypt(). PCP doesn't validate the security of the passphrase. +Self mode can be explicitly enforced with B<-m>. + =back =head1 SIGNATURES @@ -531,7 +534,7 @@ Default vault file where all keys are stored. =head1 EXPERIMENTAL STATUS -Currently there are a couple of problems which are currently +Currently there are a couple of problems which are unsolved or in the process to be solved. =over @@ -549,7 +552,8 @@ to some key server because in order to encrypt a message, both the recipient AND the sender need to have the public key of each other. It would be possible to publish public keys, and attach the senders public key to the encrypted message, but -I'm not sure if such an aproach would be secure enough. +I'm not sure if such an aproach would be secure enough. Pcp +implements this scheme though (refer to the option -A). =item B @@ -562,10 +566,20 @@ ECC algorithms. While I, as the author of pcp1 totally trust D.J.Bernstein, this may not be the case for you. -In short, I'd suggest not to use it on critical systems yet. +=item B + +As with every crypto software, pcp has to undergo a couple rounds +of peer review (analysis) in order to be considered secure, trustable +and stable. No any such review has been undertaken on pcp yet. + +Pcp is a mere fun project aimed at teaching myself better C coding +and crypto. In fact I don't even trust the software myself and I +don't use it for anything remotely serious. =back +B + =head1 INTERNALS =head2 VAULT FORMAT @@ -614,7 +628,6 @@ The key header is followed by the actual key, see below. A secret key is a binary structure with the following format: - +---------------------------------------------------------+ | Field Size Description | +-------------+--------+----------------------------------+ @@ -685,12 +698,167 @@ Generate a Curve25519 encryption keypair from that seed. =back -So, while both secrets are stored in the sam PCP key, they +So, while both secrets are stored in the same PCP key, they are otherwise unrelated. If one of them leaks, the other cannot be recalculated from it. Take a look at the function B for details. +=head2 PUBLIC KEY EXPORT FORMAT + +Exported public and secret keys will be written in a portable +way. Pcp uses RFC4880 export format for public keys with some +slight modifications: + + + +=over + +=item + +Key material is native to libsodium/pcp and not specified in the +rfc for curve25519/ed25519. Therefore pcp encodes key material doing it like +this: mp|sp|cp + +where + + mp = master keysigning public key (ed25519), 32 bytes + sp = signing public key (ed25519), 32 bytes + cp = encryption public key (curve25519), 32 bytes + +=item + +The various cipher (algorithm) id's are unspecified for +libsodium/pcp native ciphers. Therefore they are proprietary to pcp, starting at +33 (22 is the last officially assigned one). Once +those cipher numbers become official, they will be used instead. + +=item + +Pcp uses 64 bit integers for timestamps everywhere (ctime, expire, etc), +to be year 2038 safe. Note, that this is a violation of the +RFC spec. However, said RFC have to be modified to fit 2038 +(and beyond) anyways. This applies for the keyfile ctime as +well for the key sig sub fields containing time values. + +=item + +The exported public key packet contains a signature. Pcp is +filling out all required fields. A signature has a variable +number of sig sub packets. Pcp uses only these types: + + 2 = Signature Creation Time (8 byte) + 3 = Signature Expiration Time (8 byte) + 9 = Key Expiration Time (8 bytes) + 20 = Notation Data (4 byte flags, N bytes name+value) + 27 = Key Flags (1 byte, use 0x02, 0x08 and 0x80 + +=item + +Pcp uses 3 notation fields: + +=over + +=item "owner", which contains the owner name, if set + +=item "mail", which contains the emailaddress, if set + +=item "serial", which contains the 32bit serial number + +=back + +=item + +The actual signature field consists of the blake2 hash of +(mp|sp|cp|keysig) followed by the nacl signature. However, pcp +does not put an extra 16 byte value of the hash, since the nacl +signature already contains the full hash. So, an implementation +could simply pull the fist 16 bytes of said hash to get +the same result if desired. + +=item + +The mp keypair will be used for signing. The recipient can +verify the signature, since mp is included. + +=item + +While pcp puts expiration dates for the key and the signature +into the export as the rfc demands, it mostly ignores them (yet). +Key expiring is not implemented in PCP yet. + +=item + +We use big-endian always. + +=item + +Unlike RC4880 public key exports, pcp uses Z85 encoding if +armoring have been requested by the user. Armored output has +a header and a footer line, however they are ignored by the +parser and are therefore optional. Newlines, if present, are +optional as well. + +http://tools.ietf.org/html/rfc4880#section-5.2.3 + +=item + +The key sig blob will be saved in the Vault unaltered during +import, so pcp is able to verify the signature at will anytime. When exporting +a foreign public key, pcp just puts out that key sig blob to the +export untouched. + +=item + +Currently PCP only supports self-signed public key exports. + +=item + +Pcp only supports one key signature per key. However, it would be easily +possible to support foreign keysigs as well in the future. + +=back + +So, a full pubkey export looks like this + + version + ctime + cipher + 3 x raw keys \ + sigheader > calculate hash from this + sigsubs (header+data) / + hash + signature + +=head2 SECRET KEY EXPORT FORMAT + +Secret keys are exported in a proprietary format. + +The exported binary blob is symmetrically encrypted using the NACL +function crypto_secret(). The passphrase will be used to derive an +encryption key using the STAR function scrypt(). + +The binary data before encryption consists of: + + ED25519 master signing secret + Curve25519 encryption secret + ED25519 signing secret + ED25519 master signing public + Curve25519 encryption public + ED25519 signing public + Optional notations, currently supported are the 'owner' and 'mail' attributes. + If an attribute is empty, the len field is zero. + -# len(VAL) (2 byte uint) + -# VAL (string without trailing zero) + 8 byte creation time (epoch) + 4 byte key version + 4 byte serial number + +The encrypted cipher will be prepended with the random nonce used +to encrypt the data and looks after encryption as such: + + Nonce | Cipher + =head2 ENCRYPTED OUTPUT FORMAT The encryption protocol used by PCP uses mostly standard @@ -941,6 +1109,146 @@ this is a work in progress and might not work under all circumstances. Also ther no shared key format between pbp and pcp. However, it is possible to export and import pbp keys from/to pcp. +=head1 JSON ENCODING SUPPORT + +If pcp have been compiled with B<--with-json> (which requires the libjansson +library), then it supports JSON objects as input and output with the following +functions: + +=over + +=item public key export + +=item secret key export + +=item whole vault export + +=item public key import + +=item secret key import + +=back + +JSON support can be used either with the commandline tool B or programmatically +using the C, C++ or Python API. + +=head2 USING JSON FROM THE C API + +In order to use JSON all you've got to do is to switch a context flag: + + PCPCTX *ptx = ptx_new(); + ptx->json = 1; + +That all to it. Now any function normally used for key import and export works +with JSON, just fill the B object with a JSON string for imports or +fetch the Buffer content of an export function as a string. + +=head2 USING JSON FROM THE COMMANDLINE + +In order to use JSON on the commandline, add B<-j>. This can be used in +conjunction with the following options: + +=over + +=item B<-p> + +Public key export. + +=item B<-s> + +Secret key export. + +=item B<-K> + +Public and secret key import. + +=item B<-t> + +Text view mode (aka inspect mode). + +=back + +The B<-z> and B<-Z> options are ignored in JSON mode. + +=head2 JSON OBJECT STRUCTURE + +=head3 JSON PUBLIC KEY (pcp1 -p -j) + +The JSON object for a public key looks like this: + + { + "id": "6BF2980419E0986A", + "owner": "tom", + "mail": "tom@local", + "ctime": 1436170865, + "expire": 1467706865, + "version": 6, + "serial": 1509801135, + "type": "public", + "cipher": "CURVE25519-ED25519-POLY1305-SALSA20", + "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01", + "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2", + "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e", + "signature": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45[..]" + } + +Actually the field B contains the whole encoded public key. + +Fields containing byte arrays are hex encoded. + +Numbers are represented as literal integers. + +=head3 JSON SECRET KEY (pcp1 -s -j) + +The JSON object for a public key looks like this: + + { + "id": "6BF2980419E0986A", + "owner": "tom", + "mail": "tom@local", + "ctime": 1436170865, + "expire": 1467706865, + "version": 6, + "serial": 1509801135, + "type": "secret", + "cipher": "CURVE25519-ED25519-POLY1305-SALSA20", + "cryptpub": "0fdf0f7269f901b7f0fba989a1fddbf576c7cc148a2e5987fdeea3523978fe01", + "sigpub": "6980b76e17170194626b49cbab1ab35369a0635f52fe1a7cf39cc5421fb5c0c2", + "masterpub": "947a49f29e9cb0e92b61e2a1dea95f8ec81a24baed78e85c1b52cc3714f5e45e", + "secrets": "ad5ce150f3cd7bffa299d4db5bf3d26ae56c3808ccba7[..]", + "nonce": "858ef9870fc8f39903cfb281d697ca29a935d2ae929fa4ea" +} + +As you can see that's pretty identical to a public key json object beside the +B and B fields. The B field contains the encrypted +secret key material. Pcp does not support exporting a secret key unencrypted. + +The B is required for a later import and shall not be changed or +decoupled from B. This may change in the future. + +=head3 JSON VAULT (pcp1 -t) + +The JSON object for the vault looks like this: + + { + "keyvaultfile": "/home/tom/.pcpvault", + "version": 2, + "checksum": "27b583dc2dacf5ccc874b7be3a39748d107c6b9e9f9d473f1c716a94561ef793", + "secretkeys": 1, + "publickey": 3, + "keys": [] + } + +The field B is an array containing one or more of the already +described key objects. + +=head3 JSON PROGRAM OUTPUT + +Currently pcp does not support JSON program output, that is, success or +error messages on STDERR are not encoded as json. This may change in the future. + + + =head1 COPYRIGHT Copyright (c) 2013-2015 by T.v.Dein