Vigenère cipher: Difference between revisions
→{{header|REXX}}: renamed this "rexx" version to oorexx. -- ~~~~ |
Moved ooRexx to it's proper location alphabetically. -- ~~~~ |
||
Line 1,220: | Line 1,220: | ||
Code: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY |
Code: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY |
||
Back: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH</pre> |
Back: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH</pre> |
||
=={{header|ooRexx}}== |
|||
A reworking of the [[NetRexx]] version using Open Object Rexx but shouldn't take much to translate to Classic Rexx. |
|||
<lang REXX>/* Rexx */ |
|||
Do |
|||
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' |
|||
key = 'LEMON' |
|||
pt = 'Attack at dawn!' |
|||
Call test key, pt |
|||
key = 'N' |
|||
Call test key, pt |
|||
key = 'B' |
|||
Call test key, pt |
|||
pt = alpha |
|||
key = 'A' |
|||
Call test key, pt |
|||
pt = sampledata() |
|||
key = 'Hamlet; Prince of Denmark' |
|||
Call test key, pt |
|||
Return |
|||
End |
|||
Exit |
|||
vigenere: |
|||
Procedure Expose alpha |
|||
Do |
|||
Parse upper Arg meth, key, text |
|||
Select |
|||
When 'ENCIPHER'~abbrev(meth, 1) = 1 then df = 1 |
|||
When 'DECIPHER'~abbrev(meth, 1) = 1 then df = -1 |
|||
Otherwise Do |
|||
Say meth 'invalid. Must be "ENCIPHER" or "DECIPHER"' |
|||
Exit |
|||
End |
|||
End |
|||
text = stringscrubber(text) |
|||
key = stringscrubber(key) |
|||
code = '' |
|||
Do l_ = 1 to text~length() |
|||
M = alpha~pos(text~substr(l_, 1)) - 1 |
|||
k_ = (l_ - 1) // key~length() |
|||
K = alpha~pos(key~substr(k_ + 1, 1)) - 1 |
|||
C = mod((M + K * df), alpha~length()) |
|||
C = alpha~substr(C + 1, 1) |
|||
code = code || C |
|||
End l_ |
|||
Return code |
|||
Return |
|||
End |
|||
Exit |
|||
vigenere_encipher: |
|||
Procedure Expose alpha |
|||
Do |
|||
Parse upper Arg key, plaintext |
|||
Return vigenere('ENCIPHER', key, plaintext) |
|||
End |
|||
Exit |
|||
vigenere_decipher: |
|||
Procedure Expose alpha |
|||
Do |
|||
Parse upper Arg key, ciphertext |
|||
Return vigenere('DECIPHER', key, ciphertext) |
|||
End |
|||
Exit |
|||
mod: |
|||
Procedure |
|||
Do |
|||
Parse Arg N, D |
|||
Return (D + (N // D)) // D |
|||
End |
|||
Exit |
|||
stringscrubber: |
|||
Procedure Expose alpha |
|||
Do |
|||
Parse upper Arg cleanup |
|||
cleanup = cleanup~space(0) |
|||
Do label f_ forever |
|||
x_ = cleanup~verify(alpha) |
|||
If x_ = 0 then Leave f_ |
|||
cleanup = cleanup~changestr(cleanup~substr(x_, 1), '') |
|||
end f_ |
|||
Return cleanup |
|||
End |
|||
Exit |
|||
test: |
|||
Procedure Expose alpha |
|||
Do |
|||
Parse Arg key, pt |
|||
ct = vigenere_encipher(key, pt) |
|||
Call display ct |
|||
dt = vigenere_decipher(key, ct) |
|||
Call display dt |
|||
Return |
|||
End |
|||
Exit |
|||
display: |
|||
Procedure |
|||
Do |
|||
Parse Arg text |
|||
line = '' |
|||
o_ = 0 |
|||
Do c_ = 1 to text~length() |
|||
b_ = o_ // 5 |
|||
o_ = o_ + 1 |
|||
If b_ = 0 then line = line' ' |
|||
line = line || text~substr(c_, 1) |
|||
End c_ |
|||
Say '....+....|'~copies(8) |
|||
Do label l_ forever |
|||
Parse Var line w1 w2 w3 w4 w5 w6 W7 w8 w9 w10 w11 w12 line |
|||
pline = w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 |
|||
Say pline~strip() |
|||
If line~strip()~length() = 0 then Leave l_ |
|||
End l_ |
|||
Say |
|||
Return |
|||
End |
|||
Exit |
|||
sampledata: |
|||
Procedure |
|||
Do |
|||
NL = '0a'x |
|||
X = 0 |
|||
antic_disposition. = '' |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To be, or not to be--that is the question:" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Whether 'tis nobler in the mind to suffer" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The slings and arrows of outrageous fortune" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Or to take arms against a sea of troubles" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And by opposing end them. To die, to sleep--" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "No more--and by a sleep to say we end" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The heartache, and the thousand natural shocks" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That flesh is heir to. 'Tis a consummation" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Devoutly to be wished. To die, to sleep--" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To sleep--perchance to dream: ay, there's the rub," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "For in that sleep of death what dreams may come" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "When we have shuffled off this mortal coil," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Must give us pause. There's the respect" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That makes calamity of so long life." |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "For who would bear the whips and scorns of time," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Th' oppressor's wrong, the proud man's contumely" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The pangs of despised love, the law's delay," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The insolence of office, and the spurns" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That patient merit of th' unworthy takes," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "When he himself might his quietus make" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "With a bare bodkin? Who would fardels bear," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To grunt and sweat under a weary life," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "But that the dread of something after death," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The undiscovered country, from whose bourn" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "No traveller returns, puzzles the will," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And makes us rather bear those ills we have" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Than fly to others that we know not of?" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Thus conscience does make cowards of us all," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And thus the native hue of resolution" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Is sicklied o'er with the pale cast of thought," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And enterprise of great pith and moment" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "With this regard their currents turn awry" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And lose the name of action. -- Soft you now," |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The fair Ophelia! -- Nymph, in thy orisons" |
|||
X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Be all my sins remembered." |
|||
melancholy_dane = '' |
|||
Do l_ = 1 for antic_disposition.0 |
|||
melancholy_dane = melancholy_dane || antic_disposition.l_ || NL |
|||
End l_ |
|||
Return melancholy_dane |
|||
End |
|||
Exit |
|||
</lang> |
|||
;Output |
|||
<pre style="height: 60ex; overflow: scroll;"> |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
LXFOP VEFRN HR |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
ATTAC KATDA WN |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
NGGNP XNGQN JA |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
ATTAC KATDA WN |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
BUUBD LBUEB XO |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
ATTAC KATDA WN |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
ABCDE FGHIJ KLMNO PQRST UVWXY Z |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
ABCDE FGHIJ KLMNO PQRST UVWXY Z |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
AONPS KCFBG QFSYK EGUSK RLQGP WMXFV JJIHM HVGUS EYILQ CMGIY MZKRR YRWHR |
|||
FVBAH QDPBC XANPH OWUSJ EOWYB TDLKX DLASQ VHZQI BDTFD HKQLV FHRON KRGYD |
|||
WRMOW DYOGM PXHRV QDCCU SSFUN XOUDF SIFIF LVGXC XOIRB NFWVR QLRWQ PIFNI |
|||
SUWSF MYNOL NPELX WVIEV EQMHE APTYO AHAFW TCUVN VYFFO WUACB CAHME JETJP |
|||
VULSN UXBFI JKJOZ DYFBR BVQRR JYSHF LPDVB QHMLW VLGQH WJWSF XEVZA OEWIX |
|||
EGMEE LOSFI GADIO HMMJX ATIMF VLSWX FSARZ XAHME WETVX BHHSF WLJTA KNYEM |
|||
XWFPP KBOIK MHRJQ HRFLS TFJYA VLBHJ HMLWZ ARKKS CATPF JJBTK ZSZVT NGSVD |
|||
OEDPW MWVZR UTSHW XUMTD KREEN EEPDQ GASTX RPBZG CSMER ZVPWF EBWPR GHEEF |
|||
HVGOI BDEGS JKBTR GTIXV YEKRV PBCIL HFZFY VCSJX UQPIY BDYLR LRFVG WQSQB |
|||
XUQPR XNSAQ HXHGQ FGHZT YIGTE CKDSP PPTNK PRKRG TOIAO EFPVF RTGXP ELGJI |
|||
GUXVA ETYKA PMEMX CKURT MHTIX UGNNY YTTJX TZVAJ JIBMH LVYSV VMMUR LMWZA |
|||
DWMSY XWZMK VGPTT LFTGV JBFOW SZLBI OLVKF MCHXA JJRCV HTJVH ZTRXK SIPEM |
|||
JELRT EKJDV LXIWO IUFEL TIKPR FVSFG SSEOD OAHUY KTUKM EFIOY KXUQU ENPSO |
|||
ZZXGV LPQYB YUCSD ODGOO EPFHJ IVAQX FFYIY XEIBL TGCRL ELHMN IGYKI JULCK |
|||
UDYLO XHLAE CXVJU FRMRK RVSQT PEHNM UCZSY KEARL PDVOF SIKHK PNVAS PQSJZ |
|||
OKYMT TFWVD EAPKI BHHHB QSDKR EOZAT GUABH YGFOP NZDKR BSFSI GPKQI GLIJR |
|||
JEQSF VBTUZ RBHJQ PMPWJ GSRDW ZDOTT PTTAV KNUXC KWLBG GYDHN PPRMT IXEKW |
|||
STIKE QAKZP TTLRW BFURP XKNWL GTIJB LGMCH MWVQE EYFWH RGETL BUAIC CTCUT |
|||
BUIHM HRNYE FPHCF TSGHF NGASI SRAGT EWKPR AALXA ZIAAQ DMLRG TYFBP SAYWU |
|||
TRTYO CGNQW EQMVW IEDPH |
|||
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| |
|||
TOBEO RNOTT OBETH ATIST HEQUE STION WHETH ERTIS NOBLE RINTH EMIND TOSUF |
|||
FERTH ESLIN GSAND ARROW SOFOU TRAGE OUSFO RTUNE ORTOT AKEAR MSAGA INSTA |
|||
SEAOF TROUB LESAN DBYOP POSIN GENDT HEMTO DIETO SLEEP NOMOR EANDB YASLE |
|||
EPTOS AYWEE NDTHE HEART ACHEA NDTHE THOUS ANDNA TURAL SHOCK STHAT FLESH |
|||
ISHEI RTOTI SACON SUMMA TIOND EVOUT LYTOB EWISH EDTOD IETOS LEEPT OSLEE |
|||
PPERC HANCE TODRE AMAYT HERES THERU BFORI NTHAT SLEEP OFDEA THWHA TDREA |
|||
MSMAY COMEW HENWE HAVES HUFFL EDOFF THISM ORTAL COILM USTGI VEUSP AUSET |
|||
HERES THERE SPECT THATM AKESC ALAMI TYOFS OLONG LIFEF ORWHO WOULD BEART |
|||
HEWHI PSAND SCORN SOFTI METHO PPRES SORSW RONGT HEPRO UDMAN SCONT UMELY |
|||
THEPA NGSOF DESPI SEDLO VETHE LAWSD ELAYT HEINS OLENC EOFOF FICEA NDTHE |
|||
SPURN STHAT PATIE NTMER ITOFT HUNWO RTHYT AKESW HENHE HIMSE LFMIG HTHIS |
|||
QUIET USMAK EWITH ABARE BODKI NWHOW OULDF ARDEL SBEAR TOGRU NTAND SWEAT |
|||
UNDER AWEAR YLIFE BUTTH ATTHE DREAD OFSOM ETHIN GAFTE RDEAT HTHEU NDISC |
|||
OVERE DCOUN TRYFR OMWHO SEBOU RNNOT RAVEL LERRE TURNS PUZZL ESTHE WILLA |
|||
NDMAK ESUSR ATHER BEART HOSEI LLSWE HAVET HANFL YTOOT HERST HATWE KNOWN |
|||
OTOFT HUSCO NSCIE NCEDO ESMAK ECOWA RDSOF USALL ANDTH USTHE NATIV EHUEO |
|||
FRESO LUTIO NISSI CKLIE DOERW ITHTH EPALE CASTO FTHOU GHTAN DENTE RPRIS |
|||
EOFGR EATPI THAND MOMEN TWITH THISR EGARD THEIR CURRE NTSTU RNAWR YANDL |
|||
OSETH ENAME OFACT IONSO FTYOU NOWTH EFAIR OPHEL IANYM PHINT HYORI SONSB |
|||
EALLM YSINS REMEM BERED |
|||
</pre> |
|||
=={{header|Perl}}== |
=={{header|Perl}}== |
Revision as of 22:19, 9 June 2012
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
Implement a Vigenère cypher, both encryption and decryption. The program should handle keys and text of unequal length, and should capitalize everything and discard non-alphabetic characters. (If your program handles non-alphabetic characters in another way, make a note of it.)
See also:
Ada
<lang Ada>with Ada.Text_IO;
procedure Vignere_Cipher is
subtype Letter is Character range 'A' .. 'Z'; subtype Lowercase is Character range 'a' .. 'z';
function "+"(X, Y: Letter) return Letter is begin return Character'Val( ( (Character'Pos(X)-Character'Pos('A')) + (Character'Pos(Y)-Character'Pos('A')) ) mod 26 + Character'Pos('A')); end;
function Normalize(S: String) return String is -- removes all characters except for uppercase and lowercase letters -- replaces lowercase by uppercase letters Offset: Integer := Character'Pos('A') - Character'Pos('a'); begin if S="" then return ""; elsif S(S'First) in Letter then return S(S'First) & Normalize(S(S'First+1 .. S'Last)); elsif S(S'First) in Lowercase then return (Character'Val(Character'Pos(S(S'First)) + Offset) & Normalize(S(S'First+1 .. S'Last))); else return Normalize(S(S'First+1 .. S'Last)); end if; end Normalize;
function Encrypt(Key: String; Text: String) return String is Ciphertext: String(Text'Range); begin for I in Text'Range loop Ciphertext(I) := Text(I) + Key(Key'First + ((I-Text'First) mod Key'Length)); end loop; return Ciphertext; end Encrypt;
function Invert(Key: String) return String is Result: String(Key'Range); begin for I in Key'Range loop Result(I) := Character'Val( 26 - (Character'Pos(Key(I))-Character'Pos('A')) + Character'Pos('A') ); end loop; return Result; end Invert;
use Ada.Text_IO; Input: String := Get_Line; Key: String := Normalize(Get_Line); Ciph: String := Encrypt(Key => Key, Text => Normalize(Input));
begin
Put_Line("Input =" & Input); Put_Line("Key =" & Key); Put_Line("Ciphertext =" & Ciph); Put_Line("Decryption =" & Encrypt(Key => Invert(Key), Text => Ciph));
end Vignere_Cipher;</lang>
Output
./vignere_cipher < input.txt Input =Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Key =VIGENERECIPHER Ciphertext =WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decryption =BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
ALGOL 68
Note: This specimen retains the original C++ coding style.
<lang algol68>STRING key := "";
PROC vigenere cipher = (REF STRING key)VOID: (
FOR i FROM LWB key TO UPB key DO IF key[i] >= "A" AND key[i] <= "Z" THEN key +:= key[i] FI; IF key[i] >= "a" AND key[i] <= "z" THEN key +:= REPR(ABS key[i] + ABS"A" - ABS"a") FI OD
);
PROC encrypt = (STRING text)STRING: (
STRING out := "";
INT j := LWB text; FOR i FROM LWB text TO UPB text DO CHAR c := text[i];
IF c >= "a" AND c <= "z" THEN c := REPR(ABS c + (ABS"A" - ABS"a")) FI; IF c >= "A" AND c <= "Z" THEN out +:= REPR((ABS c + ABS key[j] - 2*ABS"A") MOD 26 + ABS"A"); j := j MOD UPB key + 1 FI OD;
out
);
PROC decrypt = (STRING text)STRING: (
STRING out;
INT j := LWB text; FOR i FROM LWB text TO UPB text DO CHAR c := text[i];
IF c >= "a" AND c <= "z" THEN c := REPR(ABS c + (ABS"A" - ABS"a")) FI; IF c >= "A" AND c <= "Z" THEN out +:= REPR((ABS c - ABS key[j] + 26) MOD 26 + ABS"A"); j := j MOD UPB key + 1 FI OD;
out
);
main: (
vigenere cipher(key:="VIGENERECIPHER");
STRING original := "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"; STRING encrypted := encrypt(original); STRING decrypted := decrypt(encrypted);
print((original, new line)); print(("Encrypted: ", encrypted, new line)); print(("Decrypted: ", decrypted, new line))
)</lang> Output:
Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
AutoHotkey
<lang AutoHotkey>Key = VIGENERECIPHER Text= Beware the Jabberwock, my son! The jaws that bite, the claws that catch!
out := "Input =" text "`nkey =" key "`nCiphertext =" (c := VigenereCipher(Text, Key)) "`nDecrypted =" VigenereDecipher(c, key) MsgBox % clipboard := out
VigenereCipher(Text, Key){
StringUpper, Text, Text Text := RegExReplace(Text, "[^A-Z]") Loop Parse, Text { a := Asc(A_LoopField) - Asc("A") b := Asc(SubStr(Key, 1+Mod(A_Index-1, StrLen(Key)), 1)) - Asc("A") out .= Chr(Mod(a+b,26)+Asc("A")) } return out
}
VigenereDecipher(Text, key){
Loop Parse, key decoderKey .= Chr(26-(Asc(A_LoopField)-65)+65) return VigenereCipher(Text, decoderKey)
}</lang> Output:
Input =Beware the Jabberwock, my son! The jaws that bite, the claws that catch! key =VIGENERECIPHER Ciphertext =WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted =BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
C
<lang C>#include <stdio.h>
- include <stdlib.h>
- include <string.h>
- include <ctype.h>
void upper_case(char *src) {
while (*src != '\0') { if (islower(*src)) *src &= ~0x20; src++; }
}
char* encipher(char *src, char *key, int is_encode) {
int i, klen, slen; char *dest;
dest = strdup(src); upper_case(dest); upper_case(key);
/* strip out non-letters */ for (i = 0, slen = 0; dest[slen] != '\0'; slen++) if (isupper(dest[slen])) dest[i++] = dest[slen];
dest[slen = i] = '\0'; /* null pad it, make it safe to use */
klen = strlen(key); for (i = 0; i < slen; i++) { if (!isupper(dest[i])) continue; dest[i] = 'A' + (is_encode ? dest[i] - 'A' + key[i % klen] - 'A' : dest[i] - key[i % klen] + 26) % 26; }
return dest;
}
int main() {
char *str = "Beware the Jabberwock, my son! The jaws that bite, " "the claws that catch!"; char *cod, *dec; char key[] = "VIGENERECIPHER";
printf("Text: %s\n", str); printf("key: %s\n", key);
cod = encipher(str, key, 1); printf("Code: %s\n", cod); dec = encipher(cod, key, 0); printf("Back: %s\n", dec);
/* free(dec); free(cod); */ /* nah */ return 0;
}</lang>Output:<lang>Text: Beware the Jabberwock, my son! The jaws that bite, the claws that catch! key: VIGENERECIPHER Code: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Back: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH</lang>
C++
<lang cpp>#include <iostream>
- include <string>
using namespace std;
class Vigenere { public:
string key;
Vigenere(string key) { for(int i = 0; i < key.size(); ++i) { if(key[i] >= 'A' && key[i] <= 'Z') this->key += key[i]; else if(key[i] >= 'a' && key[i] <= 'z') this->key += key[i] + 'A' - 'a'; } }
string encrypt(string text) { string out;
for(int i = 0, j = 0; i < text.length(); ++i) { char c = text[i]; if(c >= 'a' && c <= 'z') c += 'A' - 'a'; else if(c < 'A' || c > 'Z') continue;
out += (c + key[j] - 2*'A') % 26 + 'A'; j = (j + 1) % key.length(); }
return out; }
string decrypt(string text) { string out;
for(int i = 0, j = 0; i < text.length(); ++i) { char c = text[i]; if(c >= 'a' && c <= 'z') c += 'A' - 'a'; else if(c < 'A' || c > 'Z') continue;
out += (c - key[j] + 26) % 26 + 'A'; j = (j + 1) % key.length(); }
return out; }
};
int main() {
Vigenere cipher("VIGENERECIPHER");
string original = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"; string encrypted = cipher.encrypt(original); string decrypted = cipher.decrypt(encrypted);
cout << original << endl; cout << "Encrypted: " << encrypted << endl; cout << "Decrypted: " << decrypted << endl;
}</lang>
Output:
Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
Common Lisp
This doesn't assume anything about character codes other than A-Z being a contiguous block (but still, we could be using EBCDIC. Who knows.) <lang lisp>(defun strip (s)
(remove-if-not (lambda (c) (char<= #\A c #\Z)) (string-upcase s)))
(defun vigenère (s key &key decipher &aux (A (char-code #\A)) (op (if decipher #'- #'+)))
(labels ((to-char (c) (code-char (+ c A))) (to-code (c) (- (char-code c) A))) (let ((k (map 'list #'to-code (strip key)))) (setf (cdr (last k)) k) (map 'string
(lambda (c) (prog1 (to-char (mod (funcall op (to-code c) (car k)) 26)) (setf k (cdr k)))) (strip s)))))
(let* ((msg "Beware the Jabberwock... The jaws that... the claws that catch!")
(key "vigenere cipher") (enc (vigenère msg key)) (dec (vigenère enc key :decipher t))) (format t "msg: ~a~%enc: ~a~%dec: ~a~%" msg enc dec))</lang>output<lang>msg: Beware the Jabberwock... The jaws that... the claws that catch!
enc: WMCEEIKLGRPIFVMEUGXXYILILZXYVBZLRGCEYAIOEKXIZGU dec: BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH</lang>
Clojure
Requires Clojure 1.2. <lang clojure>(ns org.rosettacode.clojure.vigenere
(:require [clojure.string :as string]))
- convert letter to offset from \A
(defn to-num [char] (- (int char) (int \A)))
- convert number to letter, treating it as modulo 26 offset from \A
(defn from-num [num] (char (+ (mod num 26) (int \A))))
- Convert a string to a sequence of just the letters as uppercase chars
(defn to-normalized-seq [str]
(map #'first (re-seq #"[A-Z]" (string/upper-case str))))
- add (op=+) or subtract (op=-) the numerical value of the key letter from the
- text letter.
(defn crypt1 [op text key]
(from-num (apply op (list (to-num text) (to-num key)))))
(defn crypt [op text key]
(let [xcrypt1 (partial #'crypt1 op)] (apply #'str (map xcrypt1 (to-normalized-seq text) (cycle (to-normalized-seq key))))))
- encipher a text
(defn encrypt [plaintext key] (crypt #'+ plaintext key))
- decipher a text
(defn decrypt [ciphertext key] (crypt #'- ciphertext key))</lang>
Demonstration code: <lang clojure>(ns org.rosettacode.clojure.test-vigenere
(:require [org.rosettacode.clojure.vigenere :as vigenere]))
(let
[ plaintext "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" key "Vigenere cipher" ciphertext (vigenere/encrypt plaintext key) recovered (vigenere/decrypt ciphertext key) ]
(doall (map (fn k v (printf "%9s: %s\n" k v)) [ ["Original" plaintext] ["Key" key] ["Encrypted" ciphertext] ["Decrypted" recovered] ])))
</lang>
Output:
Original: Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Key: Vigenere cipher Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
CoffeeScript
<lang coffeescript># Simple helper since charCodeAt is quite long to write. code = (char) -> char.charCodeAt()
encrypt = (text, key) -> res = [] j = 0
for c in text.toUpperCase() continue if c < 'A' or c > 'Z'
res.push ((code c) + (code key[j]) - 130) % 26 + 65 j = ++j % key.length
String.fromCharCode res...
decrypt = (text, key) -> res = [] j = 0
for c in text.toUpperCase() continue if c < 'A' or c > 'Z'
res.push ((code c) - (code key[j]) + 26) % 26 + 65 j = ++j % key.length
String.fromCharCode res...
- Trying it out
key = "VIGENERECIPHER" original = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" encrypted = encrypt original, key
console.log "Original : #{original}" console.log "Encrypted : #{encrypted}" console.log "Decrypted : #{decrypt encrypted, key}"</lang>
Original : Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Encrypted : WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted : BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
D
<lang d>import std.stdio, std.string;
string encrypt(in string txt, in string key) pure /*nothrow*/ in {
assert(key.removechars("^A-Z") == key);
} body {
string res; foreach (i, const char c; txt.toUpper().removechars("^A-Z")) res ~= (c + key[i % $] - 2 * 'A') % 26 + 'A'; return res;
}
string decrypt(in string txt, in string key) pure /*nothrow*/ in {
assert(key.removechars("^A-Z") == key);
} body {
string res; foreach (i, const char c; txt.toUpper().removechars("^A-Z")) res ~= (c - key[i % $] + 26) % 26 + 'A'; return res;
}
void main() {
const key = "VIGENERECIPHER"; const original = "Beware the Jabberwock, my son!" ~ " The jaws that bite, the claws that catch!"; const encoded = encrypt(original, key); writeln(encoded, "\n", decrypt(encoded, key));
}</lang> Output:
WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
F#
<lang fsharp> module vigenere =
let keyschedule (key:string) = let s = key.ToUpper().ToCharArray() |> Array.filter System.Char.IsLetter let l = Array.length s (fun n -> int s.[n % l])
let enc k c = ((c + k - 130) % 26) + 65 let dec k c = ((c - k + 130) % 26) + 65 let crypt f key = Array.mapi (fun n c -> f (key n) c |> char)
let encrypt key (plaintext:string) = plaintext.ToUpper().ToCharArray() |> Array.filter System.Char.IsLetter |> Array.map int |> crypt enc (keyschedule key) |> (fun a -> new string(a))
let decrypt key (ciphertext:string) = ciphertext.ToUpper().ToCharArray() |> Array.map int |> crypt dec (keyschedule key) |> (fun a -> new string(a))
let passwd = "Vigenere Cipher" let cipher = vigenere.encrypt passwd "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" let plain = vigenere.decrypt passwd cipher printfn "%s\n%s" cipher plain </lang>
C:\src\fsharp>fsi vigenere.fsx WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
Go
<lang go>package main
import "fmt"
type vkey string
func newVigenère(key string) (vkey, bool) {
v := vkey(upperOnly(key)) return v, len(v) > 0 // key length 0 invalid
}
func (k vkey) encipher(pt string) string {
ct := upperOnly(pt) for i, c := range ct { ct[i] = 'A' + (c-'A'+k[i%len(k)]-'A')%26 } return string(ct)
}
func (k vkey) decipher(ct string) (string, bool) {
pt := make([]byte, len(ct)) for i := range pt { c := ct[i] if c < 'A' || c > 'Z' { return "", false // invalid ciphertext } pt[i] = 'A' + (c-k[i%len(k)]+26)%26 } return string(pt), true
}
// upperOnly extracts letters A-Z, a-z from a string and // returns them all upper case in a byte slice. // Useful for vkey constructor and encipher function. func upperOnly(s string) []byte {
u := make([]byte, 0, len(s)) for i := 0; i < len(s); i++ { c := s[i] if c >= 'A' && c <= 'Z' { u = append(u, c) } else if c >= 'a' && c <= 'z' { u = append(u, c-32) } } return u
}
const testKey = "Vigenère Cipher" const testPT = `Beware the Jabberwock, my son!
The jaws that bite, the claws that catch!`
func main() {
fmt.Println("Supplied key: ", testKey) v, ok := newVigenère(testKey) if !ok { fmt.Println("Invalid key") return } fmt.Println("Effective key:", v) fmt.Println("Plain text:", testPT) ct := v.encipher(testPT) fmt.Println("Enciphered:", ct) dt, ok := v.decipher(ct) if !ok { fmt.Println("Invalid ciphertext") return } fmt.Println("Deciphered:", dt)
}</lang> Output:
Supplied key: Vigenère Cipher Effective key: VIGENRECIPHER Plain text: Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Enciphered: WMCEEVXJMYHFSZZCSPBQAADUXYZRGAFKLCBQPXVOPKGYRAUBWHXTVBIL Deciphered: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
Haskell
<lang haskell>import Data.Char import Text.Printf
-- Perform encryption or decryption, depending on f. crypt f key = map toLetter . zipWith f (cycle key)
where toLetter = chr . (+) (ord 'A')
-- Encrypt or decrypt one letter. enc k c = (ord k + ord c) `mod` 26 dec k c = (ord c - ord k) `mod` 26
-- Given a key, encrypt or decrypt an input string. encrypt = crypt enc decrypt = crypt dec
-- Convert a string to have only upper case letters. convert = map toUpper . filter isLetter
main = do
let key = "VIGENERECIPHER" text = "Beware the Jabberwock, my son! The jaws that bite, " ++ "the claws that catch!" encr = encrypt key $ convert text decr = decrypt key encr printf " Input: %s\n Key: %s\nEncrypted: %s\nDecrypted: %s\n" text key encr decr</lang>
Output:
Input: Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Key: VIGENERECIPHER Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
Icon and Unicon
<lang Icon>procedure main()
ptext := "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" write("Key = ",ekey := "VIGENERECIPHER") write("Plain Text = ",ptext) write("Normalized = ",GFormat(ptext := NormalizeText(ptext))) write("Enciphered = ",GFormat(ctext := Vignere("e",ekey,ptext))) write("Deciphered = ",GFormat(ptext := Vignere("d",ekey,ctext)))
end
procedure Vignere(mode,ekey,ptext,alpha) #: Vignere cipher
/alpha := &ucase # default if *alpha ~= *cset(alpha) then runerr(205,alpha) # no dups alpha ||:= alpha # unobstructed
every ctext:="" & p:=ptext[i := 1 to *ptext] & k:=ekey[(i-1)%*ekey+1] do case mode of { "e"|"encrypt": ctext||:=map(p,alpha[1+:*alpha/2],alpha[find(k,alpha)+:(*alpha/2)]) "d"|"decrypt": ctext||:=map(p,alpha[find(k,alpha)+:(*alpha/2)],alpha[1+:*alpha/2]) default: runerr(205,mode) }
return ctext end</lang>
The following helper procedures will be of general use with classical cryptography tasks. <lang Icon> link strings
procedure NormalizeText(ptext,alpha) #: text/case classical crypto helper
/alpha := &ucase # default if &lcase === (alpha := cset(alpha)) then ptext := map(ptext) # lower if &ucase === alpha then ptext := map(ptext,&lcase,&ucase) # upper return deletec(ptext,&cset--alpha) # only alphas
end
procedure GFormat(text) #: 5 letter group formatting helper
text ? (s := "", until pos(0) do s ||:= " " || move(5)|tab(0)) return s[2:0]
end</lang>
Output:
Key = VIGENERECIPHER Plain Text = Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Normalized = BEWAR ETHEJ ABBER WOCKM YSONT HEJAW STHAT BITET HECLA WSTHA TCATCH Enciphered = WMCEE IKLGR PIFVM EUGXQ PWQVI OIAVE YXUEK FKBTA LVXTG AFXYE VKPAGY Deciphered = BEWAR ETHEJ ABBER WOCKM YSONT HEJAW STHAT BITET HECLA WSTHA TCATCH
J
Solution:
Using vig
from the convert/misc/vig addon:
<lang j>NB.*vig c Vigenère cipher
NB. cipher=. key 0 vig charset plain
NB. plain=. key 1 vig charset cipher
vig=: conjunction define
r=. (#y) $ n i.x n {~ (#n) | (r*_1^m) + n i.y
)
ALPHA=: (65,:26) ];.0 a. NB. Character Set preprocess=: (#~ e.&ALPHA)@toupper NB. force uppercase and discard non-alpha chars vigEncryptRC=: 0 vig ALPHA preprocess vigDecryptRC=: 1 vig ALPHA preprocess</lang>
Example Use: <lang j> 'VIGENERECIPHER' vigEncryptRC 'Beware the Jabberwock, my son! The jaws that bite, the claws that catch!' WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY
'VIGENERECIPHER' vigDecryptRC 'WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY'
BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH</lang>
Java
<lang d>public class VigenereCipher {
public static void main(String[] args) { String key = "VIGENERECIPHER"; String ori = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"; String enc = encrypt(ori, key); System.out.println(enc); System.out.println(decrypt(enc, key)); }
static String encrypt(String text, final String key) { String res = ""; text = text.toUpperCase(); for (int i = 0, j = 0; i < text.length(); i++) { char c = text.charAt(i); if (c < 'A' || c > 'Z') continue; res += (char)((c + key.charAt(j) - 2 * 'A') % 26 + 'A'); j = ++j % key.length(); } return res; }
static String decrypt(String text, final String key) { String res = ""; text = text.toUpperCase(); for (int i = 0, j = 0; i < text.length(); i++) { char c = text.charAt(i); if (c < 'A' || c > 'Z') continue; res += (char)((c - key.charAt(j) + 26) % 26 + 'A'); j = ++j % key.length(); } return res; }
}</lang>
WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
JavaScript
<lang javascript><html><head><title>Vigenère</title></head>
<body>
<script type="application/javascript"> function disp(x) { var e = document.createTextNode(x + '\n'); document.getElementById('x').appendChild(e); }
function ord(x) { return x.charCodeAt(0) } function chr(x) { return String.fromCharCode(x) } function rot(a, b, decode) { return decode ? chr((26 + ord(a) - ord(b)) % 26 + ord('A')) : chr((26 + ord(a) + ord(b) - ord('A') * 2) % 26 + ord('A')) }
function trans(msg, key, decode) { var i = 0; key = key.toUpperCase(); msg = msg.toUpperCase().replace(/[^A-Z]/g, ); return msg.replace(/([A-Z])/g, function($1) { return rot($1, key[i++ % key.length], decode) }); }
var msg = "The quick brown fox Jumped over the lazy Dog the lazy dog lazy dog dog"; var key = 'VIGENERECIPHER'; var enc = trans(msg, key); var dec = trans(enc, key, 'decipher');
disp("Original:" + msg + "\nEncoded: " + enc + "\nDecoded: " + dec); </script></body></html></lang>
Liberty BASIC
<lang lb> ori$ = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" key$ = filter$("vigenerecipher") print ori$ print key$ enc$ = encrypt$(ori$, key$) print enc$ dec$ = decrypt$(enc$, key$) print dec$
end
function encrypt$(text$, key$)
flt$ = filter$(text$) encrypt$ = "" j = 1 for i = 1 to len(flt$) m$ = mid$(flt$, i, 1) m = asc(m$)-asc("A") k$ = mid$(key$, j, 1) k = asc(k$)-asc("A") j = (j mod len(key$)) + 1 c = (m + k) mod 26 c$=chr$(asc("A")+c) encrypt$=encrypt$+c$ next
end function
function decrypt$(flt$, key$)
decrypt$ = "" j = 1 for i = 1 to len(flt$) m$ = mid$(flt$, i, 1) m = asc(m$)-asc("A") k$ = mid$(key$, j, 1) k = asc(k$)-asc("A") j = (j mod len(key$)) + 1 c = (m - k + 26) mod 26 c$=chr$(asc("A")+c) decrypt$=decrypt$+c$ next
end function
function filter$(ori$) 'a..z A..Z go caps, other skipped
filter$="" for i = 1 to len(ori$) c$ = upper$(mid$(ori$,i,1)) if instr("ABCDEFGHIJKLMNOPQRSTUVWXYZ", c$) then filter$ = filter$ + c$ next
end function </lang>
Beware the Jabberwock, my son! The jaws that bite, the claws that catch! VIGENERECIPHER WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
Lua
<lang lua>function Encrypt( _msg, _key )
local msg = { _msg:upper():byte( 1, -1 ) } local key = { _key:upper():byte( 1, -1 ) } local enc = {}
local j, k = 1, 1 for i = 1, #msg do if msg[i] >= string.byte('A') and msg[i] <= string.byte('Z') then enc[k] = ( msg[i] + key[j] - 2*string.byte('A') ) % 26 + string.byte('A') k = k + 1 if j == #key then j = 1 else j = j + 1 end end end return string.char( unpack(enc) )
end
function Decrypt( _msg, _key )
local msg = { _msg:byte( 1, -1 ) } local key = { _key:upper():byte( 1, -1 ) } local dec = {}
local j = 1 for i = 1, #msg do dec[i] = ( msg[i] - key[j] + 26 ) % 26 + string.byte('A') if j == #key then j = 1 else j = j + 1 end end return string.char( unpack(dec) )
end
original = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"
key = "VIGENERECIPHER";
encrypted = Encrypt( original, key ) decrypted = Decrypt( encrypted, key )
print( encrypted ) print( decrypted )</lang>
WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
NetRexx
<lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog symbols nobinary
pt = 'Attack at dawn!' key = 'LEMON' test(key, pt)
key = 'N' -- rot-13 test(key, pt)
key = 'B' -- Caesar test(key, pt)
pt = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' key = 'A' test(key, pt)
pt = sampledata() key = 'Hamlet; Prince of Denmark' test(key, pt)
return
method vigenere(meth, key, text) public static
select when 'encipher'.abbrev(meth.lower, 1) then df = 1 when 'decipher'.abbrev(meth.lower, 1) then df = -1 otherwise signal IllegalArgumentException(meth 'must be "encipher" or "decipher"') end
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
text = stringscrubber(text) key = stringscrubber(key) code = loop l_ = 1 to text.length() M = alpha.pos(text.substr(l_, 1)) - 1 k_ = (l_ - 1) // key.length() K = alpha.pos(key.substr(k_ + 1, 1)) - 1 C = mod((M + K * df), alpha.length()) C = alpha.substr(C + 1, 1) code = code || C end l_
return code
method vigenere_encipher(key, plaintext) public static
return vigenere('encipher', key, plaintext)
method vigenere_decipher(key, ciphertext) public static
return vigenere('decipher', key, ciphertext)
method mod(N = int, D = int) private static
return (D + (N // D)) // D
method stringscrubber(cleanup) private static
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
cleanup = cleanup.upper.space(0) loop label f_ forever x_ = cleanup.verify(alpha) if x_ = 0 then leave f_ cleanup = cleanup.changestr(cleanup.substr(x_, 1), ) end f_
return cleanup
method test(key, pt) private static
ct = vigenere_encipher(key, pt) display(ct) dt = vigenere_decipher(key, ct) display(dt)
return
method display(text) public static
line = o_ = 0 loop c_ = 1 to text.length() b_ = o_ // 5 o_ = o_ + 1 if b_ = 0 then line = line' ' line = line || text.substr(c_, 1) end c_
say '....+....|'.copies(8) loop label l_ forever parse line w1 w2 w3 w4 w5 w6 W7 w8 w9 w10 w11 w12 line pline = w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 say pline.strip() if line.strip().length() = 0 then leave l_ end l_ say
return
method sampledata() private static returns Rexx
NL = char('\n') antic_disposition = Rexx[]
antic_disposition = [ - Rexx("To be, or not to be--that is the question:" ), - Rexx("Whether 'tis nobler in the mind to suffer" ), - Rexx("The slings and arrows of outrageous fortune" ), - Rexx("Or to take arms against a sea of troubles" ), - Rexx("And by opposing end them. To die, to sleep--" ), - Rexx("No more--and by a sleep to say we end" ), - Rexx("The heartache, and the thousand natural shocks" ), - Rexx("That flesh is heir to. 'Tis a consummation" ), - Rexx("Devoutly to be wished. To die, to sleep--" ), - Rexx("To sleep--perchance to dream: ay, there's the rub,"), - Rexx("For in that sleep of death what dreams may come" ), - Rexx("When we have shuffled off this mortal coil," ), - Rexx("Must give us pause. There's the respect" ), - Rexx("That makes calamity of so long life." ), - Rexx("For who would bear the whips and scorns of time," ), - Rexx("Th' oppressor's wrong, the proud man's contumely" ), - Rexx("The pangs of despised love, the law's delay," ), - Rexx("The insolence of office, and the spurns" ), - Rexx("That patient merit of th' unworthy takes," ), - Rexx("When he himself might his quietus make" ), - Rexx("With a bare bodkin? Who would fardels bear," ), - Rexx("To grunt and sweat under a weary life," ), - Rexx("But that the dread of something after death," ), - Rexx("The undiscovered country, from whose bourn" ), - Rexx("No traveller returns, puzzles the will," ), - Rexx("And makes us rather bear those ills we have" ), - Rexx("Than fly to others that we know not of?" ), - Rexx("Thus conscience does make cowards of us all," ), - Rexx("And thus the native hue of resolution" ), - Rexx("Is sicklied o'er with the pale cast of thought," ), - Rexx("And enterprise of great pith and moment" ), - Rexx("With this regard their currents turn awry" ), - Rexx("And lose the name of action. -- Soft you now," ), - Rexx("The fair Ophelia! -- Nymph, in thy orisons" ), - Rexx("Be all my sins remembered." ) - ]
melancholy_dane = Rexx() loop l_ = 0 for antic_disposition.length melancholy_dane = melancholy_dane || antic_disposition[l_] || NL end l_ return melancholy_dane
</lang>
- Output
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| LXFOP VEFRN HR ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| NGGNP XNGQN JA ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| BUUBD LBUEB XO ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ABCDE FGHIJ KLMNO PQRST UVWXY Z ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ABCDE FGHIJ KLMNO PQRST UVWXY Z ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| AONPS KCFBG QFSYK EGUSK RLQGP WMXFV JJIHM HVGUS EYILQ CMGIY MZKRR YRWHR FVBAH QDPBC XANPH OWUSJ EOWYB TDLKX DLASQ VHZQI BDTFD HKQLV FHRON KRGYD WRMOW DYOGM PXHRV QDCCU SSFUN XOUDF SIFIF LVGXC XOIRB NFWVR QLRWQ PIFNI SUWSF MYNOL NPELX WVIEV EQMHE APTYO AHAFW TCUVN VYFFO WUACB CAHME JETJP VULSN UXBFI JKJOZ DYFBR BVQRR JYSHF LPDVB QHMLW VLGQH WJWSF XEVZA OEWIX EGMEE LOSFI GADIO HMMJX ATIMF VLSWX FSARZ XAHME WETVX BHHSF WLJTA KNYEM XWFPP KBOIK MHRJQ HRFLS TFJYA VLBHJ HMLWZ ARKKS CATPF JJBTK ZSZVT NGSVD OEDPW MWVZR UTSHW XUMTD KREEN EEPDQ GASTX RPBZG CSMER ZVPWF EBWPR GHEEF HVGOI BDEGS JKBTR GTIXV YEKRV PBCIL HFZFY VCSJX UQPIY BDYLR LRFVG WQSQB XUQPR XNSAQ HXHGQ FGHZT YIGTE CKDSP PPTNK PRKRG TOIAO EFPVF RTGXP ELGJI GUXVA ETYKA PMEMX CKURT MHTIX UGNNY YTTJX TZVAJ JIBMH LVYSV VMMUR LMWZA DWMSY XWZMK VGPTT LFTGV JBFOW SZLBI OLVKF MCHXA JJRCV HTJVH ZTRXK SIPEM JELRT EKJDV LXIWO IUFEL TIKPR FVSFG SSEOD OAHUY KTUKM EFIOY KXUQU ENPSO ZZXGV LPQYB YUCSD ODGOO EPFHJ IVAQX FFYIY XEIBL TGCRL ELHMN IGYKI JULCK UDYLO XHLAE CXVJU FRMRK RVSQT PEHNM UCZSY KEARL PDVOF SIKHK PNVAS PQSJZ OKYMT TFWVD EAPKI BHHHB QSDKR EOZAT GUABH YGFOP NZDKR BSFSI GPKQI GLIJR JEQSF VBTUZ RBHJQ PMPWJ GSRDW ZDOTT PTTAV KNUXC KWLBG GYDHN PPRMT IXEKW STIKE QAKZP TTLRW BFURP XKNWL GTIJB LGMCH MWVQE EYFWH RGETL BUAIC CTCUT BUIHM HRNYE FPHCF TSGHF NGASI SRAGT EWKPR AALXA ZIAAQ DMLRG TYFBP SAYWU TRTYO CGNQW EQMVW IEDPH ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| TOBEO RNOTT OBETH ATIST HEQUE STION WHETH ERTIS NOBLE RINTH EMIND TOSUF FERTH ESLIN GSAND ARROW SOFOU TRAGE OUSFO RTUNE ORTOT AKEAR MSAGA INSTA SEAOF TROUB LESAN DBYOP POSIN GENDT HEMTO DIETO SLEEP NOMOR EANDB YASLE EPTOS AYWEE NDTHE HEART ACHEA NDTHE THOUS ANDNA TURAL SHOCK STHAT FLESH ISHEI RTOTI SACON SUMMA TIOND EVOUT LYTOB EWISH EDTOD IETOS LEEPT OSLEE PPERC HANCE TODRE AMAYT HERES THERU BFORI NTHAT SLEEP OFDEA THWHA TDREA MSMAY COMEW HENWE HAVES HUFFL EDOFF THISM ORTAL COILM USTGI VEUSP AUSET HERES THERE SPECT THATM AKESC ALAMI TYOFS OLONG LIFEF ORWHO WOULD BEART HEWHI PSAND SCORN SOFTI METHO PPRES SORSW RONGT HEPRO UDMAN SCONT UMELY THEPA NGSOF DESPI SEDLO VETHE LAWSD ELAYT HEINS OLENC EOFOF FICEA NDTHE SPURN STHAT PATIE NTMER ITOFT HUNWO RTHYT AKESW HENHE HIMSE LFMIG HTHIS QUIET USMAK EWITH ABARE BODKI NWHOW OULDF ARDEL SBEAR TOGRU NTAND SWEAT UNDER AWEAR YLIFE BUTTH ATTHE DREAD OFSOM ETHIN GAFTE RDEAT HTHEU NDISC OVERE DCOUN TRYFR OMWHO SEBOU RNNOT RAVEL LERRE TURNS PUZZL ESTHE WILLA NDMAK ESUSR ATHER BEART HOSEI LLSWE HAVET HANFL YTOOT HERST HATWE KNOWN OTOFT HUSCO NSCIE NCEDO ESMAK ECOWA RDSOF USALL ANDTH USTHE NATIV EHUEO FRESO LUTIO NISSI CKLIE DOERW ITHTH EPALE CASTO FTHOU GHTAN DENTE RPRIS EOFGR EATPI THAND MOMEN TWITH THISR EGARD THEIR CURRE NTSTU RNAWR YANDL OSETH ENAME OFACT IONSO FTYOU NOWTH EFAIR OPHEL IANYM PHINT HYORI SONSB EALLM YSINS REMEM BERED
Objeck
<lang objeck> bundle Default {
class VigenereCipher { function : Main(args : String[]) ~ Nil { key := "VIGENERECIPHER"; ori := "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"; enc := encrypt(ori, key); IO.Console->Print("encrypt: ")->PrintLine(enc); IO.Console->Print("decrypt: ")->PrintLine(decrypt(enc, key)); }
function : native : encrypt(text : String, key : String) ~ String { res := ""; text := text->ToUpper(); j := 0;
each(i : text) { c := text->Get(i); if(c >= 'A' & c <= 'Z') { res->Append(((c + key->Get(j) - 2 * 'A') % 26 + 'A')->As(Char)); j += 1; j := j % key->Size(); }; };
return res; }
function : native : decrypt(text : String, key : String) ~ String { res := ""; text := text->ToUpper(); j := 0;
each(i : text) { c := text->Get(i); if(c >= 'A' & c <= 'Z') { res->Append(((c - key->Get(j) + 26) % 26 + 'A')->As(Char)); j += 1; j := j % key->Size(); }; };
return res; } }
} </lang>
encrypt: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY decrypt: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
OCaml
<lang ocaml>let cipher src key crypt =
let str = String.uppercase src in let key = String.uppercase key in
(* strip out non-letters *) let len = String.length str in let rec aux i j = if j >= len then String.sub str 0 i else if str.[j] >= 'A' && str.[j] <= 'Z' then (str.[i] <- str.[j]; aux (succ i) (succ j)) else aux i (succ j) in let res = aux 0 0 in
let slen = String.length res in let klen = String.length key in
let d = int_of_char in let f = if crypt then fun i -> d res.[i] - d 'A' + d key.[i mod klen] - d 'A' else fun i -> d res.[i] - d key.[i mod klen] + 26 in for i = 0 to pred slen do res.[i] <- char_of_int (d 'A' + (f i) mod 26) done; (res)
let () =
let str = "Beware the Jabberwock, my son! The jaws that bite, \ the claws that catch!" in let key = "VIGENERECIPHER" in
let cod = cipher str key true in let dec = cipher cod key false in
Printf.printf "Text: %s\n" str; Printf.printf "key: %s\n" key; Printf.printf "Code: %s\n" cod; Printf.printf "Back: %s\n" dec;
- </lang>
Run:
$ ocaml vigenere_cipher.ml Text: Beware the Jabberwock, my son! The jaws that bite, the claws that catch! key: VIGENERECIPHER Code: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Back: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
ooRexx
A reworking of the NetRexx version using Open Object Rexx but shouldn't take much to translate to Classic Rexx. <lang REXX>/* Rexx */ Do
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' key = 'LEMON'
pt = 'Attack at dawn!' Call test key, pt
key = 'N' Call test key, pt
key = 'B' Call test key, pt
pt = alpha key = 'A' Call test key, pt
pt = sampledata() key = 'Hamlet; Prince of Denmark' Call test key, pt
Return
End Exit
vigenere: Procedure Expose alpha Do
Parse upper Arg meth, key, text
Select When 'ENCIPHER'~abbrev(meth, 1) = 1 then df = 1 When 'DECIPHER'~abbrev(meth, 1) = 1 then df = -1 Otherwise Do Say meth 'invalid. Must be "ENCIPHER" or "DECIPHER"' Exit End End text = stringscrubber(text) key = stringscrubber(key) code =
Do l_ = 1 to text~length() M = alpha~pos(text~substr(l_, 1)) - 1 k_ = (l_ - 1) // key~length() K = alpha~pos(key~substr(k_ + 1, 1)) - 1 C = mod((M + K * df), alpha~length()) C = alpha~substr(C + 1, 1) code = code || C End l_
Return code
Return
End Exit
vigenere_encipher: Procedure Expose alpha Do
Parse upper Arg key, plaintext
Return vigenere('ENCIPHER', key, plaintext)
End Exit
vigenere_decipher: Procedure Expose alpha Do
Parse upper Arg key, ciphertext
Return vigenere('DECIPHER', key, ciphertext)
End Exit
mod: Procedure Do
Parse Arg N, D
Return (D + (N // D)) // D
End Exit
stringscrubber: Procedure Expose alpha Do
Parse upper Arg cleanup
cleanup = cleanup~space(0) Do label f_ forever x_ = cleanup~verify(alpha) If x_ = 0 then Leave f_ cleanup = cleanup~changestr(cleanup~substr(x_, 1), ) end f_
Return cleanup
End Exit
test: Procedure Expose alpha Do
Parse Arg key, pt
ct = vigenere_encipher(key, pt) Call display ct dt = vigenere_decipher(key, ct) Call display dt
Return
End Exit
display: Procedure Do
Parse Arg text
line = o_ = 0 Do c_ = 1 to text~length() b_ = o_ // 5 o_ = o_ + 1 If b_ = 0 then line = line' ' line = line || text~substr(c_, 1) End c_
Say '....+....|'~copies(8) Do label l_ forever Parse Var line w1 w2 w3 w4 w5 w6 W7 w8 w9 w10 w11 w12 line pline = w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 Say pline~strip() If line~strip()~length() = 0 then Leave l_ End l_ Say
Return
End Exit
sampledata: Procedure Do
NL = '0a'x X = 0 antic_disposition. = X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To be, or not to be--that is the question:" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Whether 'tis nobler in the mind to suffer" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The slings and arrows of outrageous fortune" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Or to take arms against a sea of troubles" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And by opposing end them. To die, to sleep--" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "No more--and by a sleep to say we end" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The heartache, and the thousand natural shocks" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That flesh is heir to. 'Tis a consummation" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Devoutly to be wished. To die, to sleep--" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To sleep--perchance to dream: ay, there's the rub," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "For in that sleep of death what dreams may come" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "When we have shuffled off this mortal coil," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Must give us pause. There's the respect" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That makes calamity of so long life." X = X + 1; antic_disposition.0 = X; antic_disposition.X = "For who would bear the whips and scorns of time," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Th' oppressor's wrong, the proud man's contumely" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The pangs of despised love, the law's delay," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The insolence of office, and the spurns" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That patient merit of th' unworthy takes," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "When he himself might his quietus make" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "With a bare bodkin? Who would fardels bear," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To grunt and sweat under a weary life," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "But that the dread of something after death," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The undiscovered country, from whose bourn" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "No traveller returns, puzzles the will," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And makes us rather bear those ills we have" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Than fly to others that we know not of?" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Thus conscience does make cowards of us all," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And thus the native hue of resolution" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Is sicklied o'er with the pale cast of thought," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And enterprise of great pith and moment" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "With this regard their currents turn awry" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And lose the name of action. -- Soft you now," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The fair Ophelia! -- Nymph, in thy orisons" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Be all my sins remembered."
melancholy_dane = Do l_ = 1 for antic_disposition.0 melancholy_dane = melancholy_dane || antic_disposition.l_ || NL End l_ Return melancholy_dane
End Exit </lang>
- Output
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| LXFOP VEFRN HR ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| NGGNP XNGQN JA ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| BUUBD LBUEB XO ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ABCDE FGHIJ KLMNO PQRST UVWXY Z ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ABCDE FGHIJ KLMNO PQRST UVWXY Z ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| AONPS KCFBG QFSYK EGUSK RLQGP WMXFV JJIHM HVGUS EYILQ CMGIY MZKRR YRWHR FVBAH QDPBC XANPH OWUSJ EOWYB TDLKX DLASQ VHZQI BDTFD HKQLV FHRON KRGYD WRMOW DYOGM PXHRV QDCCU SSFUN XOUDF SIFIF LVGXC XOIRB NFWVR QLRWQ PIFNI SUWSF MYNOL NPELX WVIEV EQMHE APTYO AHAFW TCUVN VYFFO WUACB CAHME JETJP VULSN UXBFI JKJOZ DYFBR BVQRR JYSHF LPDVB QHMLW VLGQH WJWSF XEVZA OEWIX EGMEE LOSFI GADIO HMMJX ATIMF VLSWX FSARZ XAHME WETVX BHHSF WLJTA KNYEM XWFPP KBOIK MHRJQ HRFLS TFJYA VLBHJ HMLWZ ARKKS CATPF JJBTK ZSZVT NGSVD OEDPW MWVZR UTSHW XUMTD KREEN EEPDQ GASTX RPBZG CSMER ZVPWF EBWPR GHEEF HVGOI BDEGS JKBTR GTIXV YEKRV PBCIL HFZFY VCSJX UQPIY BDYLR LRFVG WQSQB XUQPR XNSAQ HXHGQ FGHZT YIGTE CKDSP PPTNK PRKRG TOIAO EFPVF RTGXP ELGJI GUXVA ETYKA PMEMX CKURT MHTIX UGNNY YTTJX TZVAJ JIBMH LVYSV VMMUR LMWZA DWMSY XWZMK VGPTT LFTGV JBFOW SZLBI OLVKF MCHXA JJRCV HTJVH ZTRXK SIPEM JELRT EKJDV LXIWO IUFEL TIKPR FVSFG SSEOD OAHUY KTUKM EFIOY KXUQU ENPSO ZZXGV LPQYB YUCSD ODGOO EPFHJ IVAQX FFYIY XEIBL TGCRL ELHMN IGYKI JULCK UDYLO XHLAE CXVJU FRMRK RVSQT PEHNM UCZSY KEARL PDVOF SIKHK PNVAS PQSJZ OKYMT TFWVD EAPKI BHHHB QSDKR EOZAT GUABH YGFOP NZDKR BSFSI GPKQI GLIJR JEQSF VBTUZ RBHJQ PMPWJ GSRDW ZDOTT PTTAV KNUXC KWLBG GYDHN PPRMT IXEKW STIKE QAKZP TTLRW BFURP XKNWL GTIJB LGMCH MWVQE EYFWH RGETL BUAIC CTCUT BUIHM HRNYE FPHCF TSGHF NGASI SRAGT EWKPR AALXA ZIAAQ DMLRG TYFBP SAYWU TRTYO CGNQW EQMVW IEDPH ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| TOBEO RNOTT OBETH ATIST HEQUE STION WHETH ERTIS NOBLE RINTH EMIND TOSUF FERTH ESLIN GSAND ARROW SOFOU TRAGE OUSFO RTUNE ORTOT AKEAR MSAGA INSTA SEAOF TROUB LESAN DBYOP POSIN GENDT HEMTO DIETO SLEEP NOMOR EANDB YASLE EPTOS AYWEE NDTHE HEART ACHEA NDTHE THOUS ANDNA TURAL SHOCK STHAT FLESH ISHEI RTOTI SACON SUMMA TIOND EVOUT LYTOB EWISH EDTOD IETOS LEEPT OSLEE PPERC HANCE TODRE AMAYT HERES THERU BFORI NTHAT SLEEP OFDEA THWHA TDREA MSMAY COMEW HENWE HAVES HUFFL EDOFF THISM ORTAL COILM USTGI VEUSP AUSET HERES THERE SPECT THATM AKESC ALAMI TYOFS OLONG LIFEF ORWHO WOULD BEART HEWHI PSAND SCORN SOFTI METHO PPRES SORSW RONGT HEPRO UDMAN SCONT UMELY THEPA NGSOF DESPI SEDLO VETHE LAWSD ELAYT HEINS OLENC EOFOF FICEA NDTHE SPURN STHAT PATIE NTMER ITOFT HUNWO RTHYT AKESW HENHE HIMSE LFMIG HTHIS QUIET USMAK EWITH ABARE BODKI NWHOW OULDF ARDEL SBEAR TOGRU NTAND SWEAT UNDER AWEAR YLIFE BUTTH ATTHE DREAD OFSOM ETHIN GAFTE RDEAT HTHEU NDISC OVERE DCOUN TRYFR OMWHO SEBOU RNNOT RAVEL LERRE TURNS PUZZL ESTHE WILLA NDMAK ESUSR ATHER BEART HOSEI LLSWE HAVET HANFL YTOOT HERST HATWE KNOWN OTOFT HUSCO NSCIE NCEDO ESMAK ECOWA RDSOF USALL ANDTH USTHE NATIV EHUEO FRESO LUTIO NISSI CKLIE DOERW ITHTH EPALE CASTO FTHOU GHTAN DENTE RPRIS EOFGR EATPI THAND MOMEN TWITH THISR EGARD THEIR CURRE NTSTU RNAWR YANDL OSETH ENAME OFACT IONSO FTYOU NOWTH EFAIR OPHEL IANYM PHINT HYORI SONSB EALLM YSINS REMEM BERED
Perl
<lang perl>if( @ARGV != 3 ){
printHelp();
}
# translate to upper-case, remove anything else
map( (tr/a-z/A-Z/, s/[^A-Z]//g), @ARGV );
my $cipher_decipher = $ARGV[ 0 ];
if( $cipher_decipher !~ /ENC|DEC/ ){
printHelp(); # user should say what to do
}
print "Key: " . (my $key = $ARGV[ 2 ]) . "\n";
if( $cipher_decipher =~ /ENC/ ){
print "Plain-text: " . (my $plain = $ARGV[ 1 ]) . "\n"; print "Encrypted: " . Vigenere( 1, $plain ) . "\n";
}elsif( $cipher_decipher =~ /DEC/ ){
print "Cipher-text: " . (my $cipher = $ARGV[ 1 ]) . "\n"; print "Decrypted: " . Vigenere( -1, $cipher ) . "\n";
}
sub printHelp{
print "Usage:\n" . "Encrypting:\n perl cipher.pl ENC (plain text) (key)\n" . "Decrypting:\n perl cipher.pl DEC (cipher text) (key)\n"; exit -1;
}
sub Vigenere{
my ($direction, $text) = @_; for( my $count = 0; $count < length $text; $count ++ ){ $key_offset = $direction * ord substr( $key, $count % length $key, 1); $char_offset = ord substr( $text, $count, 1 ); $cipher .= chr 65 + ((($char_offset % 26) + ($key_offset % 26)) % 26); # 65 is the ASCII character code for 'A' } return $cipher;
}</lang>
Demonstration:
$ perl cipher.pl ENC 'Beware the Jabberwock, my son! The jaws that bite, the claws that catch!' VIGENERECIPHER Key: VIGENERECIPHER Plain-text: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY $ perl cipher.pl DEC WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY VIGENERECIPHER Key: VIGENERECIPHER Cipher-text: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH $ perl cipher.pl FOO WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY VIGENERECIPHER Usage: Encrypting: perl cipher.pl ENC (plain text) (key) Decrypting: perl cipher.pl DEC (cipher text) (key)
Perl 6
<lang perl6>sub s2v ($s) { $s.uc.comb(/ <[ A..Z ]> /)».ord »-» 65 } sub v2s (@v) { (@v »%» 26 »+» 65)».chr.join }
sub blacken ($red, $key) { v2s s2v($red) »+» s2v($key) } sub redden ($blk, $key) { v2s s2v($blk) »-» s2v($key) }
my $red = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"; my $key = "Vigenere Cipher!!!";
say $red; say my $black = blacken($red, $key); say redden($black, $key);</lang> Output:
Beware the Jabberwock, my son! The jaws that bite, the claws that catch! WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
This is a natural job for hyperoperators, which can vectorize any operator. For infix operators the pointy end indicates which side to "dwim", repeating elements on that side until the other side runs out. In particular, repeating the key naturally falls out of this cyclic dwimmery, as does repeating the various constants to be applied with any of several operations to every element of the list. Factoring out the canonicalization and decanonicalization lets us see quite clearly that the only difference between encryption and decryptions is the sign of the vector addition/subtraction. Since hyperops are inherently parallelizable, this algorithm might run well in your GPU.
PicoLisp
<lang PicoLisp>(de vigenereKey (Str)
(extract '((C) (when (>= "Z" (uppc C) "A") (- (char (uppc C)) 65) ) ) (chop Str) ) )
(de vigenereEncrypt (Str Key)
(pack (mapcar '((C K) (char (+ 65 (% (+ C K) 26))) ) (vigenereKey Str) (apply circ (vigenereKey Key)) ) ) )
(de vigenereDecrypt (Str Key)
(pack (mapcar '((C K) (char (+ 65 (% (+ 26 (- C K)) 26))) ) (vigenereKey Str) (apply circ (vigenereKey Key)) ) ) )</lang>
Test:
: (vigenereEncrypt "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" "VIGENERECIPHER" ) -> "WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY" : (vigenereDecrypt @ "VIGENERECIPHER") -> "BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH"
PL/I
<lang PL/I> cypher: procedure options (main); /* 21 September 2012 */
declare t(26) character (26); declare (i, j, k, L) fixed binary; declare (original, encoded, coder) character (1000) varying initial (); declare cypher character (30) varying; declare (co, ct, cc) character (1);
/* Set up cypher table. */ t(1) = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; do i = 2 to 26; t(i) = substr(t(i-1), 2, 25) || substr(t(i-1), 1, 1); end;
cypher = 'VIGILANCE'; original = 'Meet me on Tuesday evening at seven.'; put edit ('Message=', original) (a); original = uppercase(original);
/* Create the cypher text, same length as original, or longer. */ coder = repeat(cypher, length(original)/length(cypher));
/* Encode the original message, character by character. */ /* Non-alphabetic characters are ignored. */ L = 0; do i = 1 to length(original); co = substr(original, i, 1); j = index(t(1), co); if j = 0 then iterate; /* Ignore non-alphabetic character */ L = L + 1; ct = substr(coder, L, 1); k = index(t(1), ct); encoded = encoded || substr(t(j), k, 1); end; put skip data (encoded);
/* DECODING. */ put skip list ('Decoded='); do i = 1 to length(encoded); cc = substr(coder, i, 1); j = index(t(1), cc); k = index(t(j), substr(encoded, i, 1)); put edit (substr(t(1), k, 1) ) (a(1)); end;
end cypher; </lang> Output:
Message=Meet me on Tuesday evening at seven. ENCODED='HMKBXEBPXPMYLLYRXIIQTOLTFGZZV'; Decoded= MEETMEONTUESDAYEVENINGATSEVEN
PureBasic
<lang PureBasic>Procedure prepString(text.s, Array letters(1))
;convert characters to an ordinal (0-25) and remove non-alphabetic characters, ;returns dimension size of result array letters() Protected *letter.Character, index Dim letters(Len(text)) text = UCase(text) *letter = @text While *letter\c Select *letter\c Case 'A' To 'Z' letters(index) = *letter\c - 65 index + 1 EndSelect *letter + SizeOf(Character) Wend If index > 0 Redim letters(index - 1) EndIf ProcedureReturn index - 1
EndProcedure
Procedure.s VC_encrypt(text.s, keyText.s, reverse = 0)
;if reverse <> 0 then reverse the key (decrypt) Protected *letter.Character Dim text(0) Dim keyText(0) If prepString(text, text()) < 0 Or prepString(keyText, keyText()) < 0: ProcedureReturn: EndIf ;exit, nothing to work with Protected i, keyLength = ArraySize(keyText()) If reverse For i = 0 To keyLength keyText(i) = 26 - keyText(i) Next EndIf Protected textLength = ArraySize(text()) ;zero-based length Protected result.s = Space(textLength + 1), *resultLetter.Character keyLength + 1 ;convert from zero-based to one-based count *resultLetter = @result For i = 0 To textLength *resultLetter\c = ((text(i) + keyText(i % keyLength)) % 26) + 65 *resultLetter + SizeOf(Character) Next ProcedureReturn result
EndProcedure
Procedure.s VC_decrypt(cypherText.s, keyText.s)
ProcedureReturn VC_encrypt(cypherText, keyText.s, 1)
EndProcedure
If OpenConsole()
Define VignereCipher.s, plainText.s, encryptedText.s, decryptedText.s VignereCipher.s = "VIGNERECIPHER" plainText = "The quick brown fox jumped over the lazy dogs.": PrintN(RSet("Plain text = ", 17) + #DQUOTE$ + plainText + #DQUOTE$) encryptedText = VC_encrypt(plainText, VignereCipher): PrintN(RSet("Encrypted text = ", 17) + #DQUOTE$ + encryptedText + #DQUOTE$) decryptedText = VC_decrypt(encryptedText, VignereCipher): PrintN(RSet("Decrypted text = ", 17) + #DQUOTE$ + decryptedText + #DQUOTE$) Print(#CRLF$ + #CRLF$ + "Press ENTER to exit"): Input() CloseConsole()
EndIf</lang> Sample output:
Plain text = "The quick brown fox jumped over the lazy dogs." Encrypted text = "OPKDYZGMJGVAEAWDWYDTGLDCIIOPKYEQCFWVZ" Decrypted text = "THEQUICKBROWNFOXJUMPEDOVERTHELAZYDOGS"
Python
<lang python> from itertools import starmap, cycle
def encrypt(message, key):
# convert to uppercase. # strip out non-alpha characters. message = filter(lambda _: _.isalpha(), message.upper()) # single letter encrpytion. def enc(c,k): return chr(((ord(k) + ord(c)) % 26) + ord('A')) return "".join(starmap(enc, zip(message, cycle(key))))
def decrpyt(message, key):
# single letter decryption. def dec(c,k): return chr(((ord(c) - ord(k)) % 26) + ord('A')) return "".join(starmap(dec, zip(message, cycle(key))))
</lang> Demonstrating: <lang python> text = "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" key = "VIGENERECIPHER"
encr = encrypt(text, key) decr = decrpyt(encr, key)
print text print encr print decr </lang> Output:
Beware the Jabberwock, my son! The jaws that bite, the claws that catch! WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
ooRexx
A reworking of the NetRexx version using Open Object Rexx but shouldn't take much to translate to Classic Rexx. <lang REXX>/* Rexx */ Do
alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' key = 'LEMON'
pt = 'Attack at dawn!' Call test key, pt
key = 'N' Call test key, pt
key = 'B' Call test key, pt
pt = alpha key = 'A' Call test key, pt
pt = sampledata() key = 'Hamlet; Prince of Denmark' Call test key, pt
Return
End Exit
vigenere: Procedure Expose alpha Do
Parse upper Arg meth, key, text
Select When 'ENCIPHER'~abbrev(meth, 1) = 1 then df = 1 When 'DECIPHER'~abbrev(meth, 1) = 1 then df = -1 Otherwise Do Say meth 'invalid. Must be "ENCIPHER" or "DECIPHER"' Exit End End text = stringscrubber(text) key = stringscrubber(key) code =
Do l_ = 1 to text~length() M = alpha~pos(text~substr(l_, 1)) - 1 k_ = (l_ - 1) // key~length() K = alpha~pos(key~substr(k_ + 1, 1)) - 1 C = mod((M + K * df), alpha~length()) C = alpha~substr(C + 1, 1) code = code || C End l_
Return code
Return
End Exit
vigenere_encipher: Procedure Expose alpha Do
Parse upper Arg key, plaintext
Return vigenere('ENCIPHER', key, plaintext)
End Exit
vigenere_decipher: Procedure Expose alpha Do
Parse upper Arg key, ciphertext
Return vigenere('DECIPHER', key, ciphertext)
End Exit
mod: Procedure Do
Parse Arg N, D
Return (D + (N // D)) // D
End Exit
stringscrubber: Procedure Expose alpha Do
Parse upper Arg cleanup
cleanup = cleanup~space(0) Do label f_ forever x_ = cleanup~verify(alpha) If x_ = 0 then Leave f_ cleanup = cleanup~changestr(cleanup~substr(x_, 1), ) end f_
Return cleanup
End Exit
test: Procedure Expose alpha Do
Parse Arg key, pt
ct = vigenere_encipher(key, pt) Call display ct dt = vigenere_decipher(key, ct) Call display dt
Return
End Exit
display: Procedure Do
Parse Arg text
line = o_ = 0 Do c_ = 1 to text~length() b_ = o_ // 5 o_ = o_ + 1 If b_ = 0 then line = line' ' line = line || text~substr(c_, 1) End c_
Say '....+....|'~copies(8) Do label l_ forever Parse Var line w1 w2 w3 w4 w5 w6 W7 w8 w9 w10 w11 w12 line pline = w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 Say pline~strip() If line~strip()~length() = 0 then Leave l_ End l_ Say
Return
End Exit
sampledata: Procedure Do
NL = '0a'x X = 0 antic_disposition. = X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To be, or not to be--that is the question:" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Whether 'tis nobler in the mind to suffer" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The slings and arrows of outrageous fortune" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Or to take arms against a sea of troubles" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And by opposing end them. To die, to sleep--" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "No more--and by a sleep to say we end" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The heartache, and the thousand natural shocks" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That flesh is heir to. 'Tis a consummation" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Devoutly to be wished. To die, to sleep--" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To sleep--perchance to dream: ay, there's the rub," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "For in that sleep of death what dreams may come" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "When we have shuffled off this mortal coil," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Must give us pause. There's the respect" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That makes calamity of so long life." X = X + 1; antic_disposition.0 = X; antic_disposition.X = "For who would bear the whips and scorns of time," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Th' oppressor's wrong, the proud man's contumely" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The pangs of despised love, the law's delay," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The insolence of office, and the spurns" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "That patient merit of th' unworthy takes," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "When he himself might his quietus make" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "With a bare bodkin? Who would fardels bear," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "To grunt and sweat under a weary life," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "But that the dread of something after death," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The undiscovered country, from whose bourn" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "No traveller returns, puzzles the will," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And makes us rather bear those ills we have" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Than fly to others that we know not of?" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Thus conscience does make cowards of us all," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And thus the native hue of resolution" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Is sicklied o'er with the pale cast of thought," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And enterprise of great pith and moment" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "With this regard their currents turn awry" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "And lose the name of action. -- Soft you now," X = X + 1; antic_disposition.0 = X; antic_disposition.X = "The fair Ophelia! -- Nymph, in thy orisons" X = X + 1; antic_disposition.0 = X; antic_disposition.X = "Be all my sins remembered."
melancholy_dane = Do l_ = 1 for antic_disposition.0 melancholy_dane = melancholy_dane || antic_disposition.l_ || NL End l_ Return melancholy_dane
End Exit </lang>
- Output
....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| LXFOP VEFRN HR ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| NGGNP XNGQN JA ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| BUUBD LBUEB XO ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ATTAC KATDA WN ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ABCDE FGHIJ KLMNO PQRST UVWXY Z ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| ABCDE FGHIJ KLMNO PQRST UVWXY Z ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| AONPS KCFBG QFSYK EGUSK RLQGP WMXFV JJIHM HVGUS EYILQ CMGIY MZKRR YRWHR FVBAH QDPBC XANPH OWUSJ EOWYB TDLKX DLASQ VHZQI BDTFD HKQLV FHRON KRGYD WRMOW DYOGM PXHRV QDCCU SSFUN XOUDF SIFIF LVGXC XOIRB NFWVR QLRWQ PIFNI SUWSF MYNOL NPELX WVIEV EQMHE APTYO AHAFW TCUVN VYFFO WUACB CAHME JETJP VULSN UXBFI JKJOZ DYFBR BVQRR JYSHF LPDVB QHMLW VLGQH WJWSF XEVZA OEWIX EGMEE LOSFI GADIO HMMJX ATIMF VLSWX FSARZ XAHME WETVX BHHSF WLJTA KNYEM XWFPP KBOIK MHRJQ HRFLS TFJYA VLBHJ HMLWZ ARKKS CATPF JJBTK ZSZVT NGSVD OEDPW MWVZR UTSHW XUMTD KREEN EEPDQ GASTX RPBZG CSMER ZVPWF EBWPR GHEEF HVGOI BDEGS JKBTR GTIXV YEKRV PBCIL HFZFY VCSJX UQPIY BDYLR LRFVG WQSQB XUQPR XNSAQ HXHGQ FGHZT YIGTE CKDSP PPTNK PRKRG TOIAO EFPVF RTGXP ELGJI GUXVA ETYKA PMEMX CKURT MHTIX UGNNY YTTJX TZVAJ JIBMH LVYSV VMMUR LMWZA DWMSY XWZMK VGPTT LFTGV JBFOW SZLBI OLVKF MCHXA JJRCV HTJVH ZTRXK SIPEM JELRT EKJDV LXIWO IUFEL TIKPR FVSFG SSEOD OAHUY KTUKM EFIOY KXUQU ENPSO ZZXGV LPQYB YUCSD ODGOO EPFHJ IVAQX FFYIY XEIBL TGCRL ELHMN IGYKI JULCK UDYLO XHLAE CXVJU FRMRK RVSQT PEHNM UCZSY KEARL PDVOF SIKHK PNVAS PQSJZ OKYMT TFWVD EAPKI BHHHB QSDKR EOZAT GUABH YGFOP NZDKR BSFSI GPKQI GLIJR JEQSF VBTUZ RBHJQ PMPWJ GSRDW ZDOTT PTTAV KNUXC KWLBG GYDHN PPRMT IXEKW STIKE QAKZP TTLRW BFURP XKNWL GTIJB LGMCH MWVQE EYFWH RGETL BUAIC CTCUT BUIHM HRNYE FPHCF TSGHF NGASI SRAGT EWKPR AALXA ZIAAQ DMLRG TYFBP SAYWU TRTYO CGNQW EQMVW IEDPH ....+....|....+....|....+....|....+....|....+....|....+....|....+....|....+....| TOBEO RNOTT OBETH ATIST HEQUE STION WHETH ERTIS NOBLE RINTH EMIND TOSUF FERTH ESLIN GSAND ARROW SOFOU TRAGE OUSFO RTUNE ORTOT AKEAR MSAGA INSTA SEAOF TROUB LESAN DBYOP POSIN GENDT HEMTO DIETO SLEEP NOMOR EANDB YASLE EPTOS AYWEE NDTHE HEART ACHEA NDTHE THOUS ANDNA TURAL SHOCK STHAT FLESH ISHEI RTOTI SACON SUMMA TIOND EVOUT LYTOB EWISH EDTOD IETOS LEEPT OSLEE PPERC HANCE TODRE AMAYT HERES THERU BFORI NTHAT SLEEP OFDEA THWHA TDREA MSMAY COMEW HENWE HAVES HUFFL EDOFF THISM ORTAL COILM USTGI VEUSP AUSET HERES THERE SPECT THATM AKESC ALAMI TYOFS OLONG LIFEF ORWHO WOULD BEART HEWHI PSAND SCORN SOFTI METHO PPRES SORSW RONGT HEPRO UDMAN SCONT UMELY THEPA NGSOF DESPI SEDLO VETHE LAWSD ELAYT HEINS OLENC EOFOF FICEA NDTHE SPURN STHAT PATIE NTMER ITOFT HUNWO RTHYT AKESW HENHE HIMSE LFMIG HTHIS QUIET USMAK EWITH ABARE BODKI NWHOW OULDF ARDEL SBEAR TOGRU NTAND SWEAT UNDER AWEAR YLIFE BUTTH ATTHE DREAD OFSOM ETHIN GAFTE RDEAT HTHEU NDISC OVERE DCOUN TRYFR OMWHO SEBOU RNNOT RAVEL LERRE TURNS PUZZL ESTHE WILLA NDMAK ESUSR ATHER BEART HOSEI LLSWE HAVET HANFL YTOOT HERST HATWE KNOWN OTOFT HUSCO NSCIE NCEDO ESMAK ECOWA RDSOF USALL ANDTH USTHE NATIV EHUEO FRESO LUTIO NISSI CKLIE DOERW ITHTH EPALE CASTO FTHOU GHTAN DENTE RPRIS EOFGR EATPI THAND MOMEN TWITH THISR EGARD THEIR CURRE NTSTU RNAWR YANDL OSETH ENAME OFACT IONSO FTYOU NOWTH EFAIR OPHEL IANYM PHINT HYORI SONSB EALLM YSINS REMEM BERED
Ruby
<lang Ruby>class VigenereCipher
BASE = 'A'.ord SIZE = 'Z'.ord - BASE + 1
def key=(key) @key = key.upcase.gsub(/[^A-Z]/, ) end
def initialize(key) self.key= key end
def encrypt(text) crypt(text, :+) end
def decrypt(text) crypt(text, :-) end
def crypt(text, dir) plaintext = text.upcase.gsub(/[^A-Z]/, ) key_iterator = @key.chars.cycle ciphertext = plaintext.each_char do |plain_char| offset = key_iterator.next.ord - BASE ciphertext += ((plain_char.ord - BASE).send(dir, offset) % SIZE + BASE).chr end return ciphertext end
end</lang>
Demonstration:
<lang Ruby>vc = VigenereCipher.new('Vigenere cipher') plaintext = 'Beware the Jabberwock, my son! The jaws that bite, the claws that catch!' ciphertext = vc.encrypt(plaintext) recovered = vc.decrypt(ciphertext) puts "Original: #{plaintext}" puts "Encrypted: #{ciphertext}" puts "Decrypted: #{recovered}"</lang>
Output:
Original: Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
Seed7
<lang seed7>$ include "seed7_05.s7i";
const func string: vigenereCipher (in string: source, in var string: keyword) is func
result var string: dest is ""; local var char: ch is ' '; var integer: index is 1; var integer: shift is 0; begin keyword := upper(keyword); for ch range source do if ch in {'A' .. 'Z'} | {'a' .. 'z'} then shift := ord(keyword[succ(pred(index) rem length(keyword))]) - ord('A'); dest &:= chr(ord('A') + (ord(upper(ch)) - ord('A') + shift) rem 26); incr(index); end if; end for; end func;
const func string: vigenereDecipher (in string: source, in var string: keyword) is func
result var string: dest is ""; local var char: ch is ' '; var integer: index is 0; var integer: shift is 0; begin keyword := upper(keyword); for ch key index range source do if ch in {'A' .. 'Z'} | {'a' .. 'z'} then shift := ord(keyword[succ(pred(index) rem length(keyword))]) - ord('A'); dest &:= chr(ord('A') + (ord(upper(ch)) - ord('A') - shift) mod 26); end if; end for; end func;
const proc: main is func
local const string: input is "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!"; const string: keyword is "VIGENERECIPHER"; var string: encrypted is ""; var string: decrypted is ""; begin writeln("Input: " <& input); writeln("key: " <& keyword); encrypted := vigenereCipher(input, keyword); writeln("Encrypted: " <& encrypted); decrypted := vigenereDecipher(encrypted, keyword); writeln("Decrypted: " <& decrypted); end func;</lang>
Output:
Input: Beware the Jabberwock, my son! The jaws that bite, the claws that catch! key: VIGENERECIPHER Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
Tcl
<lang tcl>package require Tcl 8.6
oo::class create Vigenere {
variable key constructor {protoKey} {
foreach c [split $protoKey ""] { if {[regexp {[A-Za-z]} $c]} { lappend key [scan [string toupper $c] %c] } }
}
method encrypt {text} {
set out "" set j 0 foreach c [split $text ""] { if {[regexp {[^a-zA-Z]} $c]} continue scan [string toupper $c] %c c append out [format %c [expr {($c+[lindex $key $j]-130)%26+65}]] set j [expr {($j+1) % [llength $key]}] } return $out
}
method decrypt {text} {
set out "" set j 0 foreach c [split $text ""] { if {[regexp {[^A-Z]} $c]} continue scan $c %c c append out [format %c [expr {($c-[lindex $key $j]+26)%26+65}]] set j [expr {($j+1) % [llength $key]}] } return $out
}
}</lang> Demonstrating: <lang tcl>set cypher [Vigenere new "Vigenere Cipher"] set original "Beware the Jabberwock, my son! The jaws that bite, the claws that catch!" set encrypted [$cypher encrypt $original] set decrypted [$cypher decrypt $encrypted] puts $original puts "Encrypted: $encrypted" puts "Decrypted: $decrypted"</lang> Output:
Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Encrypted: WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY Decrypted: BEWARETHEJABBERWOCKMYSONTHEJAWSTHATBITETHECLAWSTHATCATCH
TXR
<lang txr>@(next :args) @(do
(defun letter-mod26-op (func) ;; add or subtract capital letters modulo 26 (lambda (a b) (+ #\A (mod (call func (- a #\A) (- b #\A)) 26)))) (defun vig (msg key encrypt) (cat-str (mapcar (letter-mod26-op (if encrypt (fun +) (fun -))) (list-str msg) (repeat (list-str key))) "")))
@(coll)@{key /[A-Za-z]/}@(end) @(coll)@{msg /[A-Za-z]/}@(end) @(cat key "") @(filter :upcase key) @(cat msg "") @(filter :upcase msg) @(bind encoded @(vig msg key t)) @(bind decoded @(vig msg key nil)) @(bind check @(vig encoded key nil)) @(output) text: @msg key: @key enc: @encoded dec: @decoded check: @check @(end)</lang>
Here, the TXR pattern language is used to scan letters out of two arguments, and convert them to upper case. The embedded TXR Lisp dialect handles the Vigenère logic, in just a few lines of code.
The Vigenère substitution is driven by good old Lisp mapcar
which works over the data represented as lists of characters (provided by applying the list-str
function to the string inputs).
Now mapcar
walks lists in parallel, stopping at the end of the shortest list. This traditional behavior of mapcar
turns out to be a very good idea when you introduce infinite lazy lists into the mix. Infinite lists are longer than concrete lists and so mapcar keeps going until the shortest concrete list runs out.
We can represent the text to be enciphered or deciphered as a concrete list of the letters, and the Vigenère key as an infinite lazy list, giving us a key pad which consists of an infinite number of repetitions of the key. Such a list is produced by TXR Lisp's repeat
operator, which takes a list and makes a lazy list out of repetitions of that list.
Then mapcar
will zip the text and the infinite key pad two together, through the addition or subtraction operation.
TXR Lisp's +
and -
operators are generic over characters. An integer may be added to a character to produce a displacement through the code space to get to another character. When a character is subtracted from another, the result is an integer which is the difference between their codes.
$ ./txr vigenere.txr 'vigenere cipher' 'Beware the Jabberwock... The jaws that... the claws that catch!' text: BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH key: VIGENERECIPHER enc: WMCEEIKLGRPIFVMEUGXXYILILZXYVBZLRGCEYAIOEKXIZGU dec: GWQWEACDCBLUXNWOIYXPQAHSHLPQFLNDRYUWUKEAWCHSNYU check: BEWARETHEJABBERWOCKTHEJAWSTHATTHECLAWSTHATCATCH