Vigenère cipher: Difference between revisions
Line 516: | Line 516: | ||
sub printHelp{ |
sub printHelp{ |
||
print "Usage:\n" . |
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; |
exit -1; |
||
} |
} |
||
Line 546: | Line 546: | ||
$ perl cipher.pl FOO WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY VIGENERECIPHER |
$ perl cipher.pl FOO WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY VIGENERECIPHER |
||
Usage: |
Usage: |
||
Encrypting: |
|||
Encypting: |
|||
perl cipher.pl ENC (plain text) (key) |
perl cipher.pl ENC (plain text) (key) |
||
Decrypting: |
|||
Decypting: |
|||
perl cipher.pl DEC (cipher text) (key)</pre> |
perl cipher.pl DEC (cipher text) (key)</pre> |
||
Revision as of 03:40, 26 June 2011
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:
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
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
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
ASCII only: <lang d>import std.stdio, std.string;
string encrypt(string txt, in string key) {
string res; foreach (dchar c; txt.toupper) { if (c < 'A' || c > 'Z') continue; res ~= (c + key[res.length % $] - 2 * 'A') % 26 + 'A'; } return res;
}
string decrypt(string txt, in string key) {
string res; foreach (dchar c; txt.toupper) { if (c < 'A' || c > 'Z') continue; res ~= (c - key[res.length % $] + 26) % 26 + 'A'; } return res;
}
void main() {
auto key = "VIGENERECIPHER"; auto original = "Beware the Jabberwock, my son!" ~ " The jaws that bite, the claws that catch!"; auto encoded = encrypt(original, key); writeln(encoded, "\n", decrypt(encoded, key));
}</lang> Output:
WMCEEIKLGRPIFVMEUGXQPWQVIOIAVEYXUEKFKBTALVXTGAFXYEVKPAGY 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
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
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"
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
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