cf Code
Status: Beta
Brought to you by:
dchouinard
| File | Date | Author | Commit |
|---|---|---|---|
| AUTHORS | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| COPYING | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| Makefile | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| README | 2009-09-10 | dchouinard | [r3] Added missing open error check. |
| aes.h | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| aescrypt.c | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| aeskey.c | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| aeslib.c | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| aeslib.h | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| aesopt.h | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| aestab.c | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
| cf.c | 2009-09-10 | dchouinard | [r3] Added missing open error check. |
| uitypes.h | 2009-09-08 | dchouinard | [r1] First import, version 14.1 |
CF version 14 Copyright 2008, Danny Chouinard
Sourceforge Project Page: http://sourceforge.net/projects/cfdist
Freshmeat page: http://freshmeat.net/projects/cf
CF manual, table of contents.
1. CF's purpose.
2. Installation
3. Using CF.
4. Advanced usage.
5. The Master password and multiple users.
6. File locking.
7. How secure is CF?
1. CF's purpose.
CF is an encryption utility useful for keeping sensitive information, such
as account information and passwords in files so that they're easily
manipulated, from the command line. Information stored in CF files can be
accessed by any number of users because it permits multiple passwords
and does basic file locking to prevent edit collisions.
If you only need to use one password for an encrypted file, you might
use vim instead; it has simple encryption with its -x option. If, however,
you want to use multiple passwords, read on!
2. Installation.
Installation is quite simple. You've surely extracted the archive since
you're reading this. The provided Makefile should work fine on Linux and
Solaris 10, so just type "make" to produce the cf executable. It should
probably work on most Unix-like systems, as long as they have a
/dev/urandom character device, for a good random data source.
Lastly, copy cf in a directory pointed by your $PATH. /usr/local/bin or
some such.
That's it for installation. There's no man page yet.
3. Using CF.
Here we'll introduce CF functionality by example. If you're in a hurry
and think you can figure it out for yourself, type "cf -h". Otherwise,
read on!
CF is used mainly for managing CF-formatted encrypted files. So the first
thing to do is to create a CF file, like so:
(Don't type the $, it's the prompt)
$ cf -a somefile.cf
CF will warn you that it's creating 'somefile.cf', then ask you
for an "owner's name" with a default in parenthesis. If the default
is acceptable, just type enter on that prompt. The default is taken
from the $LOGNAME environment variable, which is usually set at login. If
you wish, you may enter another name, up to 16 characters.
CF will then ask you for a password, and then to confirm it.
somefile.cf is created. It contains little information at that point, but
we can list it like so:
B$ cf -l somefile.cf
(CF prompts for a password)
Key Owner Created Modified
--- ---------------- ------------------------ ------------------------
0 Danny Wed Sep 2 10:29:39 2009 Never
--- ---------------- ------------------------ ------------------------
Version: CF V14 AES-128, Password length: 16
Header : 16
Keys : 141 (141x1)
Marker : 1
Text : 0
ls -l : -rw-r--r-- 1 danny humans 158 Sep 2 10:29 somefile.cf
Here we see that "Danny" is owner of key 0, when the key was created and
some information about the data stored in the file. A "Key" is a
user-password-and-related-information block.
We can add a second user to that file with the -a option again:
$ cf -a somefile.cf
(CF prompts for a password)
Key owner's name (danny): Bruno
Please enter new password for Bruno.
(CF prompts for Bruno's password)
(CF prompts for a confirmation)
And if we list the file, we get:
$ cf -l somefile.cf
(Here CF asks for a password. Either will work)
Key Owner Created Modified
--- ---------------- ------------------------ ------------------------
0 Danny Wed Sep 2 10:29:39 2009 Never
1 Bruno Wed Sep 2 10:37:35 2009 Never
--- ---------------- ------------------------ ------------------------
Version: CF V14 AES-128, Password length: 16
Header : 16
Keys : 282 (141x2)
Marker : 1
Text : 0
ls -l : -rw-r--r-- 1 danny humans 299 Sep 2 10:37 somefile.cf
Any number of users can be given access to the file this way. Any valid
user can add other users.
Notice that the file is encrypted right from the start:
$ od -c somefile.cf
0000000 C F V 1 4 A E S - 1 2 8 \0 \0
0000020 Y 277 J y 345 315 311 377 G 022 231 B c 215 022 a
0000040 u 243 021 266 355 021 357 204 253 ^ % 250 263 h . 200
0000060 225 323 233 2 q 023 N \f 226 254 204 > 364 $ ! 3
0000100 006 370 316 K 221 241 q 251 W 261 312 z 315 003 E r
0000120 f 353 d + 3 240 327 k 003 307 322 ( 222 343 347 243
0000140 } 227 E 365 r 0 343 004 255 265 265 v 245 W T 325
0000160 V z 300 \b 272 314 \v > \v ? 250 h 205 214 $ c
0000200 @ 355 ( 001 236 250 033 202 8 025 315 237 006 360 234
0000220 274 373 } 266 206 204 w \f 310 z 275 ( 356 Y k .
0000240 307 333 202 021 = 323 z K ] 343 214 036 4 5 } 0
0000260 & m 307 342 247 8 L 357 ~ ' C 314 231 B 260
0000300 % 026 274 266 234 ! R 372 332 ^ 250 270 333 353 { \f
0000320 002 245 240 m ~ 213 267 222 200 % [ 267 214 333 , W
0000340 254 023 221 206 365 232 e ! 016 220 342 334 342 017 W 0
0000360 354 346 Q 266 U 005 237 223 243 351 031 \v 320 206 l 255
0000400 375 G H 2 d 335 326 031 375 D 016 331 363 271 246 O
0000420 L I 027 031 202 Z q 030 002 352 317 204 261 203 033 376
0000440 | 227 Q 373 262 1 206 001 253 f N
0000453
The first 16 bytes are in the clear so the file can be identified, then
each key is preceded by a single "Y" character, and the end of keys is
indicated by a single "N". Everything else is encrypted, each key
with each password.
This is all fine and dandy, but as you can see with the -l option, there's
no text in the file, so let's put some in:
$ cf somefile.cf
Without options, cf prompts for a password and then calls an editor on a
"clear" empty file. "clear" here means un-encrypted. The clear file
resides in your $HOME/.cf directory and is randomly named.
It exists for a short period of time because CF wipes it as soon as
the editor has it read in memory.
The editor called by default is vi or vim if it exists. This
default can be changed by setting the CFEDITOR environment variable.
Note that vim is called as "vim -n" so it doesn't keep a swap file, which
would also be un-encrypted.
So while in the editor, put some text in. At least 4 characters' worth,
otherwise CF will consider the editing session as cancelled.
Remember this: If you want to cancel your editing session, you can
delete the whole text and quit the editor; the .cf file will
be left unchanged.
When you end your editing session, the editor will put your text in the
randomly-named clear file, CF will read it in memory and immediately wipe
and remove it. It then encrypts the text and stuffs it in the .cf file.
$ cf -l somefile.cf
Key Owner Created Modified
--- ---------------- ------------------------ ------------------------
0 Danny Wed Sep 2 10:29:39 2009 Never
1 Bruno Wed Sep 2 10:37:35 2009 Never
--- ---------------- ------------------------ ------------------------
Version: CF V14 AES-128, Password length: 16
Header : 16
Keys : 282 (141x2)
Marker : 1
TxtSalt: 16
Text : 40
ls -l : -rw-r--r-- 1 danny humans 355 Sep 2 11:08 somefile.cf
As you can see in this example, somefile.cf is now 355 bytes long,
consisting of a 16 bytes header, 282 bytes for 2 keys, one lonely byte
to mark the end of keys, 16 bytes of text "Salt" and 40 bytes of text.
That's the basics of it. Do "cf -a blablabla.cf" to create a file,
do it again to give access to it to more people, then do "cf blablabla.cf"
to edit it. Do "cf -l blablabla.cf" to list statistics.
4. Advanced usage.
Of course CF can do a few more things. First, you can check the help usage
with the -h option:
$ cf -h
USAGE: cf [options] [file]
file.cf Edit.
-a file.cf Add key / Create file.cf
-l file.cf List information about file.cf
-r # file.cf Remove a key.
-c file.cf Change password.
-i file.cf < file.txt Read clear text from stdin.
-o file.cf > file.txt Output clear text to stdout.
-e < file.txt > file.enc Encrypt stdin, output crypt on stdout.
-d < file.enc >file.txt Decrypt stdin, output clear on stdout.
-p password Set password. You probably shouldn't use this.
-P [file.cf] Reveal password[s].
Env. var. Used for Default
-------------- ------------------------------------- ----------------
CFOWNER Owner name. $LOGNAME
CFCLEARDIR Directory for temporary clear files. $HOME/.cfprivate
CFPASSWORD Password. Input
CFPASSFILE Use secret file instead of password.
CFEDITOR Editor for edit mode. vi or vim -n
-----------------------------------------------------------------------
A detail to note: When cf is used with a file.cf parameter, that must
always by stipulated as the last one. "cf -l file.cf" is valid,
however "cf file.cf -l" isn't.
By the way, throughout this document I've used the convention of naming
CF files with a ".cf" extension, but you don't have to. You can name them
anything you like, with or without extensions. CF won't try to add ".cf"
as a suffix.
Let's see the other options.
$ cf -r # file.cf
This removes a key from the list. Only owner of key 0 can remove keys.
Owner of key zero can even remove key 0, in which case the file is no
longer accessible. So be careful not to shoot yourself in the feet.
'#' means a number, not the literal '#' character.
Note that if there are multiple keys and key zero is removed, owner
of key 1 becomes owner of key 0, and therefore gains this priviledge.
$ cf -c file.cf
This changes a password. Which password is changed is identifed by
entering it since CF prevents duplicates. So you'll have to enter the
current password, then enter the new password twice. The -l listing
will then show when the password was changed.
$ cf -i file.cf < file.txt
The -i option "inputs" clear text. Any text stored currently in the
.cf file is replaced by the text read on stdin. Because stdin is busy
with the text input, cf will not be able to read a password, so either
use the -p option, the $CFPASSWORD or the $CFPASSFILE environment
variables (explained later.)
$ cf -o file.cf >file.txt
The -o option "outputs" clear text.
$ cf -e < file.txt > file.enc
This reads stdin, encrypts, outputs on stdout (it's a pipe!). You'll
have to use -p, $CFPASSWORD, or $CFPASSFILE.
$ cf -d < file.enc > file.txt
This reads encrypted data from stdin, decrypts, outputs in clear on stdout.
You'll have to use -p, $CFPASSWORD, or $CFPASSFILE. Wrong passwords will
result not in an error, but garbled data.
Note that the -e and -d options do NOT use a .cf file, and use a single
password.
Encrypted data with -e results in streams that are 16 bytes longer for
every 1048576 bytes of clear text.
$ cf -p password ...
Stipulate password on command line so CF doesn't have to prompt for it.
You probably do not want to use this as the password will be visible
in the list of processes (ps -ef or auxw) and may be stored in your
shell's command history file.
$ cf -P somefile.cf
Reveals passwords. Shown will be the password you use and the
"Master password" for the .cf file. Other owners' passwords cannot
be revealead. You probably don't want to do this if someone can
peek over your shoulder.
Environment variable CFPASSWORD:
If CF detects that the CFPASSWORD environment variable exists, it will use
its contents instead of prompting for a single password. In bash, you
can set it invisibly by doing:
$ read -s CFPASSWORD; export CFPASSWORD
CFPASSWORD isn't used when changing passwords.
Environment variable CFPASSFILE:
If CF detects that the CFPASSFILE environment variable exists, it perturbs
a random-number-generator by the whole file's data and so generates a 16
random character password from it. The file should be at least 256
characters long, but somewhat small. id_[rd]sa private key files in your
.ssh directory are good candidates. Any file is fine, small .gif or .jpg
images, etc... You should protect that file as you protect your ssh
private keys; readable by you alone.
To use it, first set CFPASSFILE to point to your private file. Then,
use the "cf -c somefile.cf" command to change your password. You will
be prompted to enter your _current_ password. CF will then not prompt
for a new password, but will instead use the file. Here's and example:
$ cf -a file.cf
Creating file file.cf.
Key owner's name (danny): Danny
Please enter new password for Danny.
(CF prompts for a password and confirmation.)
$ CFPASSFILE=~/.ssh/id_rsa
$ cf -c file.cf
(CF prompts for the current password, just entered in the previous command.)
Setting password as computed from /home/danny/.ssh/id_rsa
Password changed for Danny, key #0.
We can see what password is computed from the file:
$ cf -P
Password: #cKAtn9U*)h8=^0-
If you forget to set CFPASSFILE or if you lose the file, you could type
that in and it would work.
By the way, master passwords and passwords from CFPASSFILE are random. I'm
not responsible if they happen to spell out something offensive. :)
5. The Master password and multiple users.
Text in a .cf file isn't encrypted using owners' passwords. Instead,
it's encrypted using a master password randomly generated when the file
if created. The master password can be revealed (as long as you have a
valid key) with the -P option:
$ cf -P file.cf
(CF prompts for a password)
Password: frikfrak
Master password: 9CQG'}[Ieu;+"m{#F
In this example, the key owner's password is "frikfrak" but the text is
encrypted with the master password `9CQG'}[Ieu;+"m{#F`. The owners do not
need to know the master password because each owner's key contains the master
password encrypted with their resptective passwords.
Information about keys is encrypted with the master password so that
every owner can list the keys and related information (-l).
So for an usual editing session, cf prompts the owner for a password, tries
to decrypt every key with it until it succeeds, then it gets the master
password from a copy in the decrypted key. It then uses the master password
to decrypt the text.
This way multiple users can edit a single file without sharing passwords
between them. Tadaaaaa!
6. File locking
In order to prevent multiple users from changing a file at the same time,
it creates the file with an extra .lck suffix which contains clear text
describing the reason for the lock.
$ cf somefile.cf
(File is being edited)
(and in a different console...)
$ cf somefile.cf
somefile.cf locked: danny is editing, process 22084 on hanaji.
$ cat somefile.cf.lck
danny is editing, process 22084 on hanaji.
The lock file tells you who (danny) is doing what (editing), which process
number (22084) on which workstation (hanaji).
If CF or the workstation on which it was used crashes, you'll have to
remove the .lck file yourself.
7. How secure is CF?
First, let's consider brute-force attacks. A brute-force attack consists
of a program trying every possible passwords against an encrypted bit of
information starting with, let's say "aaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaab",
"aaaaaaaaaaaaaaac"... ending with "zzzzzzzzzzzzzzzz".
CF uses the Advanced Encryption Standard (AES) in 128 bit mode. That
means that passwords can be up to 16 bytes long. 16 bytes of 8 bits each
mean 128 bits, wich in turn means this many possible passwords:
340,282,366,920,938,463,463,374,607,431,768,211,456
That's a very very very very large number. Its Three hundred and fourty
million million million million million million. Or as Carl Sagan would
have said: "Three hundred and fourty billion billion billion billion".
Using the short scale, that number is:
Three hundred fourty undecillion, two hundred eighty-two decillion,
three hundred sixty-six nonillion, nine hundred twenty octillion,
nine hundred thirty-eight septillion, four hundred sixty-three sextillion,
four hundred sixty-three quintillion, three hundred seventy-four quadrillion,
six hundred and seven trillion, four hundred thrity-one billion,
seven hundred sixty-eight million, two hundred eleven thousand,
four hundred fifty-six.
As I said earlier, a large number indeed.
CF restricts passwords to a sub-set of that number so that passwords are
printable and typeable. The set is the ASCII character set from the
exclamation mark (!) (ASCII 33) to the Tilde (~) (ASCII 126). This reduces
the bytes from a 0-255 range to a 33-126 range. The resultant number of
possible passwords in CF is thus 94 to the 16th power:
37,157,429,083,410,091,685,945,089,785,856
It's about one nine millionth the number of possible passwords as the
previous number but it's still an incredibly large number. It's larger
than 104 bits' worth.
How long would a brute-force attack of this number take? Well, let's
imagine firstly that the average attack would take about %50 of the time
because they'd get lucky and the target password would be early in the set,
so we get:
18578714541705045842972544892928
Then, let's be really pessimistic and imagine that the attack uses some
as-of-now impossibly powerful large parallel hardware decryptor that can
do one trillion (1,000,000,000,000) decryptions per second, we then get
the number of seconds the attack would take:
18578714541705045842 seconds
Now divide that by 24 hours of seconds (86400):
215031418306771 days
Ummm... Let's divide that by years (365.24):
588,740,056,693 years.
That's over 588 billion years. Consider that our universe is about 13.5
billion years.
Ok, you can relax now, as long as you don't use "1234" as a password.
By the way, CF does absolutely no checks for password complexity. It's
your data, you're responsible. Use "1234" for all I care. If you need help
choosing good passwords, see http://en.wikipedia.org/wiki/Password
Now that we have that out of the way, let's consider how safe is the
clear text.
Because you need to edit the text, it needs to exist in clear form
somewhere as a file in order for the editor to pick it up. CF tries to
limit the amount of time that that file exists as much as possible but
because the editor doesn't send a signal to CF that it has finished reading
the file in memory, CF can only check when the file's access time changes
because of the editor's opening it. Then, CF waits a bit more to give
a chance to the editor to read the whole file in. Finally, CF wipes the
file and removes it.
When you quit the editor, CF knows right away because it receives a signal
that a child process ended, it therefore immediately reads the clear
text, wipes it and removes it.
That means that a randomly named file containing your clear text exists for
about 2 seconds every time you use CF in editing mode.
Before we try any more security hardening, consider the following facts:
Anything you type on your machine is stored momentarily in the kernel's
memory in various buffers. Anything you see on your screen ends
up in X's memory or a console buffer. If think that something or someone
can have access to your machine's memory with root priviledges, you data
is at risk if while it's in the clear.
Notes on the wiping of the clear file:
If you look at the source, you'll notice the wipefile function. It's called
when CF exists for any reason. It checks to see if a temporary clear file
exists, and if it does, it then writes the same 1K block of random data over
the whole length of it. It then syncs the filesystems and removes the file.
Security afficionados will point out that data over-written on disk can
be recovered (at great cost) using very sophisticated equipment and procedures
by data-recovering firms.
To them I point out the Great Zero Challenge, in which a security group
challenged a number of data recovery firms to recover a single file from
a disk that had been zero'ed completely just once, using 'dd'. They all
declined saying that it wasn't possible.
The original annoucement on slashdot was:
http://hardware.slashdot.org/article.pl?sid=08/09/06/189248
Also, see the Wikipedia page about Data Remnance:
http://en.wikipedia.org/wiki/Data_remanence
Notice the bit that says:
``Daniel Feenberg, an economist at the private National Bureau of Economic
Research, claims that the chances of overwritten data being recovered
from a modern hard drive amount to "urban legend".``
And:
``... the 2006 NIST Special Publication 800-88 (p. 7):
"Studies have shown that most of todays media can be effectively
cleared by one overwrite"``
The truth of it is this: Bits on modern hard disks aren't re-written in the
exact same spots, they're not written simply as "North for One",
"South for Zero", and they're not even written as "1 for one" and "0 for zero",
as every disk uses NRZ (Non-Return-to-Zero) algorithms to prevent writing
the same bit value many too times in a row. Implementing the old NIST or DOD
algorithms for data wiping is simply not necessary anymore.
Finally, during an editing session the clear file is written to the
file-system and then removed two seconds later. Because of how Unix/Linux
work, the actual contents actually aren't written to disk. They just live
in the Operating System's buffers, marked as data "to be written to disk on
the next flush". They get wiped there.
Also, there's a way to call the editor without there being a clear
text file at all, but it requires some scripting so I've only implemented
it for vim as of now. If you set CFUSEVIMSCRIPT=1, editing a .cf file
will create a vimscript file in your $HOME/.cf directory that does
two things:
It reads the output of `cf -o somefile.cf` in memory.
It maps the Q key to `:1,$w !cf -i somefile.cf<CR>:q!`
So basically vim starts, executes the .cfvimscript which calls cf to read
the clear text directly in memory. When you're done editing, don't try
to save, type Q instead. Vim will then pipe the clear text to
`cf -i somefile.cf`, which updates the .cf file and quit.
Caveats: Cannot cancel edit sessions, only works with vim,
requires user to not exit editor in the usual way (ZZ, :wq, etc...)
This is why CFUSEVIMSCRIPT is a kludge, optional, and not in the
usage (-h) list.
I'm going to try to do something more sensible with :autocmds.
That's it for now. CF V14 is ready for release as I've set the key structure
in stone for now and the foreseeable future. We've been using it for a few
weeks and it's stable.
For my e-mail address, execute this in a Unix shell:
echo qnaal.pubhvaneq@tznvy.pbz | tr a-z n-za-m
Don't hesitate to send me questions or suggestions.
Danny Chouinard, Montreal, September 6th 2009.
--------------------------------------------------------------------------
Changelog (I'm not keeping an extra file for it)
Sun Sep 6 20:08:07 EDT 2009 README: Added notes about wiping.
Sun Sep 6 20:08:36 EDT 2009 Added this change log.
Tue Sep 8 15:11:02 EDT 2009 Make sure password doesn't exist in -c.
Thu Sep 10 12:55:05 EDT 2009 Added missing open error check.