- The post-quantum cryptography encryption and signing tool
(short of Codecrypt) is a general purpose encryption/decryption
signing/verification tool that uses only quantum-computer-resistant
- -h, --help
- Show a simple help with option listing.
- -V, --version
- Display only version information.
- -T, --test
- This option exists as a convenience for hackers - in this
case, ccr initializes itself, calls a test() function from source
file src/main.cpp (that is meant to be filled by testing stuff beforehand)
and terminates. In distribution packages, it will probably do nothing.
- -R, --in <file>
- Redirect standard input to be read from file instead
from stdin. You can still specify "-" to force reading from
- -o, --out <file>
- Redirect standard output to be written to file. You
can specify "-" to force writing to stdout.
- -E, --err <file>
- Redirect the standard error output to file. You can
specify "-" to force writing to stderr. Error output does not
carry any data, but provides useful error messages and metadata about what
is happening, e.g. the identity of message signer or details about why
decryption or verification fails.
- -a, --armor
- Where expecting input or output of data in codecrypt
communication format, use ascii-armoring.
Codecrypt otherwise usually generates raw binary data, that are very hard to
pass through e-mail or similar text communication channels.
- -y, --yes
- Assume the user knows what he is doing, and answer
"yes" to all questions.
- -s, --sign
- Produce a signed message from input.
- -v, --verify
- Take a signed message from input, verify whether the
signature is valid, and output message content if the verification
- -e, --encrypt
- Produce an encrypted message from input.
- -d, --decrypt
- Decrypt the message from input.
Note that the actions for signature/encryption and decryption/verification can
be easily combined into one command, simply by specifying both options usually
as "-se" or "-dv".
- -r, --recipient <keyspec>
- Specify that the message for encryption should be encrypted
so that only the owner of a private key paired with public key specified
by keyspec can decrypt it.
- -u, --user <keyspec>
- Specify a private key to use for signing the message.
- -C, --cleartext
- When working with signatures, produce/expect a cleartext
signature. The basic property of cleartext signature is that the message
it contains is easily readable by users, therefore it is a very popular
method to e.g. sign e-mails.
- -b, --detach-sign <file>
- On signing, produce a detached signature and save it to
file. When verifying, read the detached signature from file.
Note that files that is being signed or verified must be put into
program's input (potentially using "-R" option.
- -S, --symmetric <file>
- Use symmetric cryptography.
When doing "sign" or "verify" operation, do not sign
asymmetrically, but instead generate file with cryptographic hashes
that can later be used to verify if the contents of input was changed.
When doing "generate", "encrypt" or "decrypt"
operation, do not encrypt asymmetrically, but instead generate or use a
file with a key for specified symmetric cipher. Use "-g help" to
see available symmetric primitives. For symmetric encryption to work, at
least one stream cipher (marked with C) and at least one hash function
(marked with H, used to protect against malleability) separated by comma
need to be selected. Additionally, user can specify "longblock"
or "shortblock" keyword to manipulate size of internal
encryption block structure (longer blocks consume more RAM, but the
ciphertext doesn't grow very much); or the "longkey" flag which
creates larger symmetric key to provide more key material to the ciphers
(which can help to protect against low-quality random numbers, but is
generally unnecessary and even considered to be a bad practice). It is
also possible to combine more stream ciphers and hash functions.
Purpose of the --symmetric option is that symmetric cryptography is a
lot faster than asymmetric, and symmetric primitives usually work also on
very large files and data streams, as they don't need to be fully copied
into allocated memory for this purpose. Thus, if working with a large
file, process it symmetrically first, then sign/encrypt the (tiny)
symmetric file asymmetrically and send it along with the (possibly
encrypted) large file.
In Codecrypt, each public key has a KeyID, which is basically a hash of its
representation that is used to identify the key globally. Each public key is
stored along with a key name, which is a convenience tool for users who can
store arbitrary information about e.g. what is the key meant for or who it
belongs to. Public keys also have an algorithm identifier to specify how to
work with them, and sometimes also attached a private key to form a secret
Keys can be specified using several methods:
Using KeyID -- the key specification starts with @ and continues with several
first characters of the KeyID that identify a single key with that prefix.
Using a name -- key specification consists of a string, a key is then matched if
its name contains the specified string. Matching is case-insensitive.
- -g, --gen-key <algorithm>
- Generate a keypair for usage with specified algorithm. Use
"-g help" to get list of all algorithms available. Listing also
contains flags "S" and "E", meaning that algorithm can
be used for signatures or encryption, or "H" and "C"
for usage with symmetric hashes and ciphers. In asymmetric case (where the
algorithm names are long) the supplied algorithm name does not need to be
a full name, but must match only one available algorithm.
- -N, --name <keyname>
- Specify that affected keys (those being imported,
generated, exported or renamed) should be newly renamed to keyname.
- -F, --filter <keyspec>
- When listing, importing or exporting keys, only process
keys that match keyspec.
- -k, --list
- List available public keys.
- -K, --list-secret
- List available private keys (in keypairs).
- -i, --import
- Import public keys.
- -I, --import-secret
- Import private keypairs.
- -n, --no-action
- On import, do not really import the keys, but only print
what keys and names will be imported. This is useful for preventing
accepting unwanted private or public keys.
- -f, --fingerprint
- When printing keys, format full KeyIDs. Note that full
KeyIDs can be used in similar way as fingerprints known from other crypto
- -p, --export
- Export public keys in keyring format.
- -P, --export-secret
- Export private keys. (Do this carefully!)
- -x, --delete <keyspec>
- Remove matching keys from public keyring.
- -X, --delete-secret
- Remove matching keys from private keypairs.
- -m, --rename <keyspec>
- Rename matching public keys. Use "-N" to specify
a new name.
- -M, --rename-secret
- Rename matching private keys.
Codecrypt stores user data in a directory specified by environment variable
CCR_DIR, which defaults to "$HOME/.ccr". It contains the files
"pubkeys" and "secrets" which are sencode keyring
representations of user's public and private keyring.
Backups of user data (i.e. for each file the last state that was loaded
successfully) are, on each change, written to files "pubkeys~" and
When Codecrypt is running, it locks the ".ccr" directory using a
lockfile "lock" and applying flock(2) to it.
For seeding the random number generator, Codecrypt uses data from
"/dev/random" for generating keys and "/dev/urandom" for
everything else, e.g. nonces or envelopes. Both cases can be overridden at
once by specifying some other filename in environment variable
returns exit status 0 if there was no error and all cryptography went
fine, or 1 on generic errors. If the error was that a missing hash algorithm
or a public or private key was needed to complete the operation, 2 is
returned. If signature or hash verification fails (e.g. the signature is bad
or likely forged), the program returns 3.
Program offers several "algorithms" that can be used for signatures
and encryption. Use "ccr -g help" to get a list of supported
FMTSeq-named schemes are the Merkle-tree signature algorithms. The name
FMTSEQxxx-HASH1-HASH2 means, that the scheme provides attack complexity
("bit security") around 2^xxx, HASH1 is used as a message digest
algorithm, and HASH2 is used for construction of Merkle tree.
McEliece-based encryption schemes are formed from McEliece trapdoor running on
quasi-dyadic Goppa codes (the MCEQD- algorithms) and on quasi-cyclis
medium-density parity-check (QCMDPC- ones) with Fujisaki-Okamoto encryption
padding for CCA2. Algorithm name MCEQDxxxFO-HASH-CIPHER means that the
trapdoor is designed to provide attack complexity around 2^xxx, and HASH and
CIPHER are the hash and symmetric cipher functions that are used in
Fujisaki-Okamoto padding scheme.
As of November 2015, users are advised to deploy the 2^128-secure variants of
the algorithms -- running 2^128 operations would require around 10^22 years of
CPU time (of a pretty fast CPU), which is considered more than sufficient for
any reasonable setup and using stronger algorithms seems just completely
Note that using stronger algorithm variants does not come with any serious
performance drawback and protects the user from non-fatal attacks that
decrease the security of the scheme only by a small amount -- compare getting
an attack speedup of 2^20 on a scheme with 2^80 bit security (which is fatal)
with getting the same speedup on a scheme with 2^128 security (where the
resulting 2^108 is still strong).
For comparison with existing schemes, 2^128 security level is very roughly
equivalent to that of classical RSA with 3072bit modulus (which is,
accordingly to the best results available in June 2013 for general public,
reported to provide roughly 2^112 attack complexity).
For another comparison, a very good idea about the unbelievably insane amount of
energy that is actually needed for brute-forcing 2^256 operations can be
obtained from Wikipedia, which estimates the size of whole observable universe
(!) to around 2^270 atoms.
All algorithms are believed to be resistant to quantum-computer-specific
attacks, except for the generic case of Grover search which (in a very
idealized case and very roughly) halves the bit security (although the attack
remains exponential). Users who are aware of large quantum computers being
built are advised to use 2^192 or 2^256 bit security keys.
Codecrypt does not do much to prevent damage from mistakes of the user. Be
especially careful when managing your keyring, be aware that some operations
can rename or delete more keys at once. Used cryptography is relatively new,
therefore be sure to verify current state of cryptanalysis before you put your
data at risk.
In a fashion similar to aforementioned `new cryptography', the original
algebraic variant of quasi-dyadic McEliece that is still in codecrypt (MCEQD*
algorithms, kept for compatibility purposes) has been broken by an algebraic
attack. Security is greatly reduced. Use the QC-MDPC variant which dodges
Codecrypt is not very good for working directly with large files. Because of the
message format and code clarity, whole input files and messages are usually
loaded into memory before getting signed/encrypted. Fixing the problem
requires some deep structural changes in Codecrypt that would break most of
the achieved internal simplicity, therefore the fix is probably not going to
happen. You can easily workaround the whole problem using symmetric ciphers
(for encryption of large files) or hashfiles (for signatures of large files).
See the --symmetric
FMTSeq signatures are constructed from one-time signature scheme, for this
reason the private key changes after each signature, basically by increasing
some counter. IF THE PRIVATE KEY IS USED MORE THAN ONCE TO SIGN WITH THE SAME
COUNTER AND THE SIGNATURES GET PUBLISHED, SECURITY OF THE SCHEME IS SEVERELY
DAMAGED. Never use the same key on two places at once. If you backup the
private keys, be sure to backup it everytime after a signature is made.
If something goes wrong and you really need to use the key that has been, for
example, recovered from a backup, you can still "skip" the counter
by producing and discarding
some dummy signatures (ccr -s </dev/null
>/dev/null). If you plan to do that for some real purpose, for your own
safety be sure to understand inner workings of FMTSeq, especially how the
Diffie-Lamport signature scheme degrades after publishing more than one
FMTSeq can only produce a limited amount of signatures (but still a pretty large
number). When the remaining signature count starts to get low, Codecrypt will
print warning messages. In that case, users are advised to generate and
certify new keys.
Try to always use the "-n" option before you actually import keys --
blind import of keys can bring serious inconsistencies into your key naming
In a distant universe after much computation, KeyIDs can collide. If you find
someone who has a colliding KeyID, kiss him and generate another key.
Using CCR_RANDOM_SEED is slightly counterintuitive and dangerous, use it only
If your system does not have /dev/(u)random, make a port by choosing a safe
value in the source code instead of specifying the seed each time you invoke
If the seed source of your system can not be trusted, fix the system instead.
Q: I can't read/verify messages from versions 1.3.1 and older!
A: KeyID algorithm changed after that version. If you want, you can manually
rewrite the message sencode envelopes to contain new recipient/signer KeyIDs
and new message identificators, things should work perfectly after that.
Q: I can't read/verify messages from versions 1.7.4 and older!
A: There was a mistake with no security implications in Cubehash implementation.
Same advice as in previous case applies.
Q: Some signatures from version 1.5 and older fail to verify!
A: There was a slight mistake in padding of messages shorter than signature hash
function size (64 bytes in the 256-bit-secure signature types) with no
security implications. It was decided not to provide backward compatibility
for this minor use-case. If you really need to verify such signatures, edit
the msg_pad function in src/algos_sig.h so that the `load_key()' function is
called on empty vector instead of `out'.
Q: My Cubehash-based FMTSeq key produces invalid signatures after version 1.7.5!
A: Cubehash was corrected to obey standards in 1.7.5. It is possible to generate
a new public key that would work with your private key, but the general advice
is just to generate a new key.
Q: I want to sign/encrypt a large file but it took all my RAM and takes ages!
A: Use --symmetric
option. See the `CAVEATS' section for more details.
Q: How much `broken' is the original quasi-dyadic McEliece?
A: The private key of proposed dyadic variant by Misoczki and Barreto can be
derived from the public key with standard computer equipment pretty quickly.
Following commands roughly demonstrate command line usage of ccr
ccr -g help
ccr -g sig --name "John Doe" # your signature key
ccr -g enc --name "John Doe" # your encryption key
ccr -K #watch the generated keys
ccr -p -a -o my_pubkeys.asc -F Doe # export your pubkeys for friends
#see what people sent us
ccr -ina < friends_pubkeys.asc
#import Frank's key and rename it
ccr -ia -R friends_pubkeys.asc --name "Friendly Frank"
#send a nice message to Frank (you can also specify him by @12345 keyid)
ccr -se -r Frank < Document.doc > Message_to_frank.ccr
#receive a reply
ccr -dv -o Decrypted_verified_reply.doc <Reply_from_frank.ccr
#rename other's keys
ccr -m Frank -N "Unfriendly Frank"
#and delete pukeys of everyone who's Unfriendly
ccr -x Unfri
#create hashfile from a large file
ccr -sS hashfile.ccr < big_data.iso
#verify the hashfile
ccr -vS hashfile.ccr < the_same_big_data.iso
#create (ascii-armored) symmetric key and encrypt a large file
ccr -g sha256,chacha20 -aS symkey.asc
ccr -eaS symkey.asc -R big_data.iso -o big_data_encrypted.iso
#decrypt a large file
ccr -daS symkey.asc <big_data_encrypted.iso >big_data.iso
Used cryptography is relatively new. For this reason, codecrypt eats data. Use
it with caution.
Codecrypt was written by Mirek Kratochvil in 2013-2017.