Implement a One-Time Pad

GolfScript, 53 chars

n%(0=2%{~.,[{26rand 65+}*]:K]}*zip{{-}*~)26%65+}%K]n*

This is a task for which GolfScript seems just about perfectly suited.

To keep the code short, I'm using the same code for both encryption and decryption: to decrypt, I subtract the key from the ciphertext, while for encryption, I first generate a random ciphertext and then subtract the plaintext from it. Even so, the extra code for implementing encryption mode takes just a little over half the length of the program.

De-golfed version with comments:

n %             # split input into an array of lines

# KEY GENERATION FOR ENCRYPTION MODE:
(               # extract the first line from the array
0 = 2 %         # check if the first char of that line is odd (E = 69)...
{               # ...and execute this block if it is:
    ~           # dump the remaining lines (of which the should be only one) on the stack
    . ,         # calculate the length of the last line...
    [ { 26 rand 65 + } * ]  # ...make an array of that many random letters...
    :K          # ...and assign it to K
    ]           # collect all the lines, including K, back into an array
} *

# ENCRYPTION / DECRYPTION ROUTINE:
zip             # transpose the array of 2 n-char strings into n 2-char strings...
{               # ...and execute this block for each 2-char string:
    {-} *       # subtract the second char code from the first
    ~ )         # negate the result (using the two's complement trick -x = ~x+1)
    26 % 65 +   # reduce modulo 26 and add 65 = A
} %

# OUTPUT:
K ] n*         # join the result and K (if defined) with a newline, stringifying them

Ruby (200 185)

sample runs + wc:

$ ruby onetimepad.rb
ENCODE
ANOTHERTESTINPUTZZZ
ZYCLGHDWLDASFUTHWKC
BPMIBXOXTPTQIVBMDPX
$ ruby onetimepad.rb
DECODE
ZYCLGHDWLDASFUTHWKC
BPMIBXOXTPTQIVBMDPX
ANOTHERTESTINPUTZZZ
$ wc onetimepad.rb
       4       7     185 onetimepad.rb
def f;gets.scan(/./).map{|b|b.ord-65};end
s=->a{a.map{|b|(b+65).chr}*''}
r=->b,a,o{s[a.zip(b).map{|a,b|(a.send o,b)%26}]}
puts(gets=~/^D/?r[f,f,:+]:[s[k=(p=f).map{rand 26}],r[k,p,:-]])

APL (Dyalog Unicode), 46 bytes

⎕A[26|{'N'∊⍞:⍉x,⍪(⎕A⍳w)+x←26?⍨⍴w←⍞⋄-⌿⎕A⍳↑⍞⍞}1]

Try it online!

The current full program is the result of a 2hr long session at The APL Orchard., with a lot of golfing input from Adám (-13 bytes!).

Requires ⎕IO←0 (0-indexing).

Explanation

⎕A[26|{'N'∊⍞:⍉x,⍪(⎕A⍳w)+x←26?⍨⍴w←⍞⋄-⌿⎕A⍳↑⍞⍞}1]
      {                                    }1  inner fn(called with junk param)
           ⍞                                   first input
       'N'∊                                    is 'N' present in it?
            :⍉x,⍪(⎕A⍳w)+x←26?⍨⍴w←⍞             if so, eNcrypt:
                               w←⍞              store message in w
                          26?⍨⍴                 generate 26 random numbers,
                        x←                      store in x
                 (⎕A⍳w)+                        add that to the indices in the alphabet
                ⍪                               table them
              x,                                join with the random numbers
             ⍉                                  transpose to get key and encrypted value
                                  ⋄-⌿⎕A⍳↑⍞⍞    else, decrypt:
                                         ⍞⍞     input key and value
                                        ↑       convert to matrix
                                     ⎕A⍳        get the indices of both in the alphabet
                                   -⌿           difference of all columns
   26|                                          mod the result of the inner fn.
  [                                          ] index the result of the program in 
⎕A                                             the capitalized alphabet.