Vigenère cipher: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|D}}: changed my mind about removechars, it gives better guarantees)
(Contract Programming in D code)
Line 266: Line 266:
=={{header|D}}==
=={{header|D}}==
ASCII only:
ASCII only:
<lang d>import std.stdio, std.string, std.ctype, std.exception;
<lang d>import std.stdio, std.string, std.ctype;


string encrypt(string txt, in string key) {
string encrypt(string txt, in string key)
in {
enforce(key.idup.removechars("^A-Z") == key);
assert(key.idup.removechars("^A-Z") == key);
} body {
string res;
string res;
foreach (i, c; txt.toupper().removechars("^A-Z"))
foreach (i, c; txt.toupper().removechars("^A-Z"))
Line 275: Line 277:
return res;
return res;
}
}

string decrypt(string txt, in string key) {
string decrypt(string txt, in string key)
in {
enforce(key.idup.removechars("^A-Z") == key);
assert(key.idup.removechars("^A-Z") == key);
} body {
string res;
string res;
foreach (i, c; txt.toupper().removechars("^A-Z"))
foreach (i, c; txt.toupper().removechars("^A-Z"))

Revision as of 16:40, 2 July 2011

Task
Vigenère cipher
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

Translation of: C++

Note: This specimen retains the original C++ coding style.

Works with: ALGOL 68 version Revision 1 - no extensions to language used.
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny.
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d.

<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>

  1. include <stdlib.h>
  2. include <string.h>
  3. 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>

  1. 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

Translation of: D

<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...

  1. 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, std.ctype;

string encrypt(string txt, in string key) in {

   assert(key.idup.removechars("^A-Z") == key);

} body {

   string res;
   foreach (i, c; txt.toupper().removechars("^A-Z"))
       res ~= (c + key[i % $] - 2 * 'A') % 26 + 'A';
   return res;

}

string decrypt(string txt, in string key) in {

   assert(key.idup.removechars("^A-Z") == key);

} body {

   string res;
   foreach (i, c; txt.toupper().removechars("^A-Z"))
      res ~= (c - key[i % $] + 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>

strings.icn provides deletec

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

Translation of: D

<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

Translation of: Haskell

<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

Translation of: C++

<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