One Time Pad

OTP in 1 line of perl: vec($_,0,1);open(P,shift);read(P,$p,length),print $_^$p while<> John Allen <allen@grumman.com> shortened my previous perl implemenation by 11 chars. He also has this even shorter perl5 specific version: open P,shift;read(P,$p,length),print $_^$p while<> Paul Leyland wrote one in 1 line of C :
main(i,c)int*c;{for(c=fopen(c[1],"r");i=~getchar();putchar(getc(c)^~i));}

What is a One Time Pad?

A one time pad is the only currently known unconditionally secure encryption system. Other encryption systems are cryptographically secure which means that they have a cost associated with breaking, this cost will be very high, but it would theoretically be possible to break if enough compute time could be gathered.

OTPs are provably unconditionally secure, this means that you can not break them with any amount of compute time. It is mathematically impossible to break a OTP.

Okay, so a OTP is a marvelously secure crypto system, so why isn't it more widely used? This is due to convenience, in order to use a OTP you have to trade pads with each person you wish to communicate with. The pad should be a truly random number, so you would ideally want a radioactive decay card or something to generate the pad. The system will critically depend on the true randomness of the pad, and of course on keeping the pad known only to you and the recipient.

This is where the inconvenience comes in, you must somehow trade pads with your intendend recipient securely, this means meeting in person or using a trusted courier.

How does it work

Basically you have your random OTP, which both you and your intended recipient have. You have a message M, and you compute the ciphertext C by XORing the message with the OTP:

C = M xor OTP

You send the ciphertext to your recipient, the recipient knowing the OTP also can recover the message by computing the reverse, XORing the ciphertext C with the OTP:

M = C xor OTP

You must never re-use the OTP, other wise it wouldn't be a "One-Time" pad anymore, and it would loose it's unbreakable properties as information would start to be leaked.

One Time Pad in 1 line of perl


#!/usr/local/bin/perl
open(P,$ARGV[0]);print pack(C,unpack(C,$_)^unpack(C,getc(P)))while$_=getc;

Save as otp and mark as executable:
% chmod 700 otp

One Time Pad in 1 line of C


main(i,c)int*c;{for(c=fopen(c[1],"r");~(i=getchar());putchar(getc(c)^i));}

by Paul Leyland. Just compile with a K&R or ANSI C compiler:
% cc -o otp otp.c

Using the OTP

You must create and exchange a OTP with your recipient. We call the OTP file "pad" here, the message to exchange "msg", and the encrypted ciphertext "cipher".

To encrypt, do (same usage for C or perl versions):

% otp pad < msg > cipher
Now you can send "cipher" to your recipient in the clear, just email will do fine as you will be the only two people who will ever be able to decipher the message.

To decrypt your recipient does:

% otp pad < cipher > msg
to recover the message.

Generating OTPs

It can't be stressed enough how important it is to have a truly random OTP. Just using the random() function provided with C libraries is nowhere near good enough, these typically have a seed of one 32 bit word, so that even if you used the millisecond of your clock as a seed the whole system could be broken with a brute force keysearch of all possible seeds. In cryptographic terms a 32 bit keyspace is tiny, and would take a negligble amount of compute time to break.

Basically if you use pseudo-random number generators they are going to be the weak point in the system, unless you have external input like a radio-active decay card, or timings of the milliseconds between keystrokes with proper entropy estimation as used by PGP.


Comments, html bugs to me (Adam Back) at <adam@cypherspace.org>