Diana Cryptosystem

December 19, 2014

[ Today’s exercise comes from the blog of long-time reader Ben Simon, after he declined my offer to guest-author the exercise and told me to steal it. The code and most of the text is his, so he gets the credit, not me. ]

It’s been a while since we had an exercise from our cryptography topic. Today’s exercise is the Diana Cryptosystem, also known as the trigraph cipher, which was used militarily by US forces during the Vietnam War and is theoretically unbreakable when used properly.

There are two pieces to the system: the trigraph itself, which is pictured at right, and a one-time pad, like this:

WHTVI AUCFU RETFK OMSAL
MYMNE ZIEGP UKVTF WZHOK
GORWY WETFR COYET OOWHY
ZPDDA CMMXT VYTJI RRQGU

To use the cipher, a section of the one-time pad is chosen and the two five-character groups that begin the section are transmitted unchanged. Thereafter, the key character is looked up on the trigraph, the next plaintext character is on the top row, and the corresponding ciphertext character is read off the bottom row. Decryption is the inverse operation. For instance, the message ATTACK AT DAWN is encoded like this, starting from the third group on the second row of the one-time pad:

UKVTF WZHOK GORWY WETFR COYET
            ATTAC KATDA WNXYZ
UKVTF WZHOK TSPDZ TVNRI BYEXH

Then UKVTF WZHOK TSPDZ TVNRI BYEXH is transmitted by Morse code. The recipient looks up the first two groups on the one-time pad then decrypts as follows:

UKVTF WZHOK GORWY WETFR COYET
UKVTF WZHOK TSPDZ TVNRI BYEXH
            ATTAC KATDA WNXYZ

The cipher is unbreakable without the one-time pad.

We said earlier that the cipher was used militarily. Ben points to this description of its use:

Special Forces were one of (if not the only) units in Vietnam to utilize Morse code on a regular basis. We used a method of encryption called the Diana Cryptosystem.

The basis of these “One-Time Pads”, is that there were only two matching pads in existence, and they would only be used one time. They were booklets that contained randomly generated groups of 5-letter “words;” 30 words to a page. The person sending a message would first write the letters to the message, over these random groups of words. Included in the front of each one-time pad was a one-page encryption table. If I wanted to send the letter “P”, and the letter under the “P” was an “A”, then I would send a “K”. The person listening on the frequency at the other end, would have the other matching pad. They would write the letter they received (a “K”) over the letter in their one-time pad (an “A”), and decipher it based on the table, yielding the original letter “P”.

Each communication site in Vietnam (we had over 100 A-Camps along the Cambodian / Laotian border, and some 20 B-detachment sites spread over the country) had a different pad, depending on the location they were having the commo-check with. It obviously was very important that both people were using the appropriate matching pads, or the deciphered messages would not make any sense.

After a while, most of us became so proficient with the system, that we actually learned the deciphering matrix by heart. No matter what pads anyone had, the combinations always were the same. i.e. Any 3 letters always went together, regardless of the order; “BKO”/”KOB”/”OBK”/”BOK”. After listening to thousands and thousands of transmissions, it really got quite simple. If I was listening to code, and a letter “B” was sent (now remember, we usually sent around 20-25 “words” (5 letters per word) a minute, hence the importance of the “speed” keys!), and the letter it was associated with was an “O”, most of us would decipher as we heard it, and just write the “K”. That may sound like quite a yarn, but it is absolutely true.

Your task is to write a program that implements the trigraph cipher. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Pages: 1 2

8 Responses to “Diana Cryptosystem”

  1. Francesco said

    Haskell

    import Control.Monad (replicateM)
    import System.Random (randomRIO)
    import Data.Function (on)
    
    t a b = let (i,f) = splitAt (d a) ['z','y'..'a'] in head . drop (d b) $ f ++ i
        where d i = on (-) fromEnum i 'a'
    
    mkPad c r = replicateM r . replicateM c . replicateM 5 $ randomRIO ('a', 'z')
    
    trans pad msg = zipWith t pad msg
    
    main = mkPad 3 2 >>= print >>
           let otp = "rtlesohpctdgvyx"; mess = "ciaomamma"
               enc = trans otp mess; tra = trans otp enc in
           putStrLn ("otp: " ++ otp ++ "   enc: " ++ enc ++ "   dec: " ++ tra)
    
  2. Paul said

    In Python.

    from string import ascii_uppercase
    from random import choice
    
    def code(t, k): return ascii_uppercase[(25 - ord(k) - ord(t)) % 26]
    def split5(txt): return " ".join("".join(txt[i:i+5]) for i in range(0, len(txt), 5))
    
    def cgen(txt):
        for c in txt:
            if c.isalpha(): yield c
    
    def tri_lookup(msg, key):
        return split5([code(t, k) for t, k in zip(cgen(msg), cgen(key))])
    
    def make_otp(rows=4, columns=4, size=5):
        output = []
        for row in range(rows):
            o = [choice(ascii_uppercase) for _ in range(size * columns)]
            output.append(split5(o))
        return "\n".join(output)
    
    def print_trigraph():
        print "   " + " ".join(ascii_uppercase)
        for line in ascii_uppercase:
            print line + ":", " ".join(code(line, c) for c in ascii_uppercase)
        
    otp = make_otp()
    print otp
    msg = "HELLO WORLD"
    enc = tri_lookup(msg, otp)
    print enc
    print tri_lookup(enc, otp)
    
  3. […] a previous exercise Ben Simon showed us how to use a trigraph for secret communication. For illustration, he used a […]

  4. Anish Sharma said

    In “C”, the following code can be used. One time pad has to be entered by the user manually though since it is more flexible to the user (i guess so).
    #include
    #include
    void morse (char);
    char dna(char, char);
    void main()
    {
    char line[20];
    char crypt[20];
    char newc[20];
    int letter_no,i;
    clrscr();
    printf(“\n………………………….DIANA CRYPTOSYSTEM……………………….\n”);
    printf(“\nEnter the number of letters you want to add and then press Enter:”);
    scanf(“%d”,&letter_no);
    printf(“\nEnter your Sentence(in block letters. Without Spaces) :\n”);
    for(i=0;i<letter_no;i++)
    {
    line[i]=getche();
    }
    printf("\nEnter a one time pad (without spaces. Do remember the pad).:\n");
    for(i=0;i<letter_no;i++)
    {
    crypt[i]=getche();
    }
    for(i=0;i<letter_no;i++)
    {
    newc[i]=dna(line[i],crypt[i]);
    }
    printf("\nYour Substitution\n");
    for(i=0;i<letter_no;i++)
    {
    printf("%c",newc[i]);

    }
    getch();
    }

    char dna(char ui, char tg)
    {
    int c1,c2,c3,flag,x=0;
    char a,b,c,e;
    for(c=65;c<=90;c++)
    {
    x++;
    c1=0;c2=0;c3=0;flag=0;
    for(a=65;a=65;b–)
    {
    c2++;
    if(b==tg)
    {
    flag=1;
    break;
    }

    }
    if(flag==0)
    {
    for(e=90;e>=65;e–)
    {
    c3++;
    if(e==tg)
    break;
    }
    }
    if(c1==c2+c3)
    return c;
    }
    }

  5. Michael said

    I’m curious how they transmitted numbers via this cipher – presumably just by expanding it to 36 characters?

  6. programmingpraxis said

    @Michael: The usual answer is to spell out numbers as words. Thus, 227 is encoded as TWO TWO SEVEN.

Leave a comment