Making and breaking codes Part 14- VIC Cipher on the Commodore VIC-20
By Michael Doornbos
- 4 minutes read - 824 wordsI love pretty good encryption that requires nothing but a pencil and paper, or a deck of cards.
VICTOR
In the twentieth century, Soviet spies used a simple paper cipher based on the codename VICTOR of a Soviet agent spying in the United States under the name Reino Häyhänen.
In 1957 he surrendered to the American intelligence agency and disclosed details of the cipher. Or so the story goes.
The VIC cipher is regarded as the most complex modification of the Nihilist cipher family. Considered to be one of the strongest ciphers, which can be used manually without computers, American counterintelligence hadn’t managed to break the cipher before he turned himself in. It uses a straddling checkerboard to change letters of plaintext into numbers rather than using a Polybius square.
Simplified version
Since the nickname is the VIC cipher, I’d like this to run on an unexpanded VIC. We shouldn’t need any Machine Language for this one, BASIC should be fast enough for a cipher designed to be done by hand.
Our Checkerboard
Much of the confusion around the VIC Cipher is in the convoluted way (secure?) of actually creating the straddling checkerboard. Coupled with the fact that the board that was actually used by the Russian’s used a Cyrillic alphabet means we’ve got to do this ourselves anyway. If you want to become a super spy in the 1950s, feel free to learn how to create these. For simplicities sake, we’re just going to make a simple one. And keep the keys to just one round.
Relax, we’re learning how to traverse straddling checkerboards, not smuggling state secrets out of the US in the 1950s. Just remember that keeping a random version of the checkerboard and constantly changing the key(s) will dramatically increase the security of this system.
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
---|---|---|---|---|---|---|---|---|---|---|
E | T | A | O | N | R | I | S | |||
2 | B | C | D | F | G | H | J | K | L | M |
6 | P | Q | / | U | V | W | X | Y | Z |
We’re not really trying to do this in the best way, just exploring a way to implement a cipher like this, while embracing the constraints of the VIC-20.
Code breakdown
Subroutines
- 1100 Print checkerboard
- 1200 find the letter location in the checkerboard
- 1300 build the number string
- 1400 print message
- 1500 create the addition string from the key
- 1600 addition mod 10
5 VIC=1
10 IF VIC=0THENPOKE53281,1:PRINT"":POKE53280,3
15 PRINT"":INPUT"(E)NCRYPT/(D)ECRYPT";MO$
20 PA$="2":PB$="6":REMPERSONAL NUMBERS
25 IFMO$="E"THENGOTO100
30 IFMO$="D"THENGOTO300
100 REM START ENCRYPT
110 M$="":MD$="":ME$="":REM MESS, MESS DIGITS, MES ENCRYPTED
120 SD$="":REM SECRET DIGITS
130 INPUT"MESSAGE";M$
140 INPUT"KEY";SD$
150 L$="":TI$="000000"
160 REM ROWS COLUMNS STRADDLING CHECKERBOARD
170 R=4:C=10:DIMSC$(R,C+1)
180 PRINT"VIC CIPHER ON A VIC-20";:IFVIC=0THENPRINT
190 GOSUB 1000
200 PRINT"STRADDLINGCHECKERBOARD"
210 GOSUB 1100
220 PRINT"----------------------"
230 PRINT"KEY:"SD$
240 PRINT:PRINT"MESS:";
250 GOSUB 1300
260 GOSUB 1400
270 GOSUB 1500
280 GOSUB 1600
290 GOTO 900
300 REM START DECRYPT
310 ME$="":REMMES ENCRYPTED
320 SD$="":REM SECRET DIGITS
330 INPUT"SECRET MESSAGE";ME$
340 INPUT"KEY";SD$
350 L$="":TI$="000000"
360 REM ROWS COLUMNS STRADDLING CHECKERBOARD
370 R=4:C=10:DIMSC$(R,C+1)
380 PRINT"VIC CIPHER ON A VIC-20";:IFVIC=0THENPRINT
390 GOSUB 1000
400 PRINT"STRADDLINGCHECKERBOARD"
410 GOSUB 1100
420 PRINT"----------------------"
430 PRINT"KEY:"SD$;
440 PRINT:PRINT"SECRET:"
450 GOSUB 2400
460 GOSUB 2500
470 GOSUB 2600
480 GOSUB 2300
490 GOTO 900
900 PRINT"JIFFIES:"TI;
910 GETQ$:IFQ$=""THENGOTO910
920 END
1000 REM POPULATE DIM
1010 FORRS=0TOR-1
1020 FORCS=0TOC
1030 READZ$:CS$(RS,CS)=Z$
1040 NEXTCS
1050 NEXTRS
1090 RETURN
1100 REM*** PRINT CHECKERBOARD
1110 FORRS=0TOR-1
1115 PRINT" ";
1120 FORCS=0TOC
1130 PRINTCS$(RS,CS);
1140 NEXTCS:PRINT""
1150 NEXTRS
1190 RETURN
1200 REM*** LOOK FOR MATCH
1210 FORRS=0TOR-1
1220 FORCS=0TOC
1230 IFL$=CS$(RS,CS)THEN GOTO1260
1240 NEXTCS
1250 NEXTRS
1260 T=VAL(CS$(RS,0)+CS$(0,CS)):MD$=MD$+MID$(STR$(T),2)
1290 RETURN
1300 REM***
1310 FOR I=1TO LEN(M$)
1320 L$=MID$(M$,I,1)
1330 GOSUB 1200
1340 NEXT
1390 RETURN
1400 REM*** PRINT MESSAGE
1410 PRINT""M$"":PRINT: PRINTMD$
1490 RETURN
1500 REM*** CREATE ADD STRING MA$
1510 SL=LEN(SD$):MA$=""
1520 FOR M=0TOLEN(MD$)-1
1530 MM=M-INT(M/SL)*SL
1540 MA$=MA$+MID$(SD$,MM+1,1)
1550 NEXT:PRINTMA$
1560 FOR P=1TOLEN(MD$):PRINT"-";:NEXTP
1590 RETURN
1600 REM*** ADD MOD 10
1610 FORM=1TOLEN(MA$)
1620 E=VAL(MID$(MA$,M,1))+VAL(MID$(MD$,M,1))
1630 E=E-INT(E/10)*10
1640 ME$=ME$+MID$(STR$(E),2)
1660 NEXTM:PRINT:PRINT""ME$""
1690 RETURN
2200 REM CREATE MD STRING
2210 FORRS=0TOR-1
2220 FORCS=0TOC
2230 IFL$=CS$(RS,CS)THEN GOTO2260
2240 NEXTCS:NEXTRS
2260 MD$=MD$+(CS$(RO,CS)):GOTO2290
2290 RETURN
2300 REM*** CREATE LOOKUP STRING
2310 FOR I=1TO LEN(MA$):RO=1
2320 L$=MID$(MA$,I,1)
2330 IFL$=PA$THENRO=2:I=I+1:L$=MID$(MA$,I,1):GOTO2370
2340 IFL$=PB$THENRO=3:I=I+1:L$=MID$(MA$,I,1):GOTO2370
2370 GOSUB 2200
2380 NEXT:PRINTMD$
2390 RETURN
2400 REM*** PRINT SECRET
2410 PRINT""ME$"":REMPRINT:REMPRINTMD$
2490 RETURN
2500 REM*** CREATE SUBT STRING SS$
2510 SL=LEN(SD$):SS$=""
2520 FOR M=0TOLEN(ME$)-1
2530 MM=M-INT(M/SL)*SL :REMPRINTMM
2540 SS$=SS$+MID$(SD$,MM+1,1)
2550 NEXT:PRINTSS$
2560 FOR P=1TOLEN(SS$):PRINT"-";:NEXTP
2590 RETURN
2600 REM*** SUBT MOD 10
2615 FORM=1TOLEN(ME$)
2620 E=VAL(MID$(ME$,M,1))-VAL(MID$(SS$,M,1))
2630 E=E-INT(E/10)*10
2640 MA$=MA$+MID$(STR$(E),2)
2660 NEXTM:PRINT:PRINT""MA$""
2690 RETURN
9000 DATA " ",0,1,2,3,4,5,6,7,8,9
9010 DATA " ",E,T," ",A,O,N," ",R,I,S
9020 DATA 2,B,C,D,F,G,H,J,K,L,M
9030 DATA 6,P,Q,/,U,V,W,X,Y,Z,.
You’re ready to start your spy ring now
This works fine on most 8-Bit computers of the era as is that run a similar BASIC. With minor modifications, I’ve run this code on the Apple II, Coco2, PET, and C64/128.
Here it is on a PET:
If you try it on your machine, please let me know!