http://qs321.pair.com?node_id=139710
Category: Cryptography
Author/Contact Info /msg mrbbking
Description:

This is a complete and historically accurate implementation of the Vigenere cipher. According to The Code Book, by Simon Singh, (Doubleday, 1999, ISBN 0385495315) Blaise de Vigenere formalized this cipher system based on the earlier work of Battista Alberti, Johannes Trithemius and Giovanni Porta.

This cipher is defined to function only on letters, and only with a key comprised exclusively of letters. Among this cipher's strengths is that only the encrypted letters are included in the ciphertext.
All punctuation and spaces are removed, so the ciphertext is an unbroken string of letters. No word breaks or punctuation to help in cryptanalysis.

Don't take that to mean this is secure against anyone serious.
It isn't.

There is a recent reference to a module called Crypt::Vigenere by Alistair Mills, but a CPAN search does not locate it as of 2002-01-13.
Discussion of the submission of that module is at: http://archive.develooper.com/modules@perl.org/msg08962.html

#!/usr/bin/perl -w
use strict;

# Vigenere cipher toolkit. Encrypt and Decrypt.
# Cracking not included.
# 

my $plaintext    = "This is not secure, but it's kind of fun.";
my $key            = 'perlmonks';        # By definition, letters only
+.
my $ciphertext;
my $derived_plaintext;

# For convenience, do the work in lowercase...
$plaintext = lc($plaintext);
$key       = lc($key);

# By definition, only encipher letters, and only use letters in the ke
+y...
$plaintext =~ s/[^a-z]//g;
$key       =~ s/[^a-z]//g;
if(length($key) < 1){
    die "Key must contain at least one letter.\n";
}

print "plaintext is [$plaintext]\n\n";
$ciphertext            = encrypt_string( $plaintext, $key);
$derived_plaintext    = decrypt_string( $ciphertext, $key );

print "Plaintext used      :$plaintext\n";
print "Ciphertext          :$ciphertext\n";
print "Recreated plaintext :$derived_plaintext\n";

sub encrypt_string{
    # encrypts a full string of plaintext, given the plaintext and the
+ key.
    # returns the encrypted string.
    my ($plaintext, $key) = @_;
    my $ciphertext;
    $key = $key x (length($plaintext) / length($key) + 1);
    for( my $i=0; $i<length($plaintext); $i++ ){
        $ciphertext .=
            encrypt_letter( (substr($plaintext,$i,1)),  (substr($key,$
+i,1)));
    }
    return $ciphertext;
}

sub decrypt_string{
    # decrypts a full string of ciphertext, given the ciphertext and t
+he key.
    # returns the plaintext string.
    my ($ciphertext, $key) = @_;
    my $plaintext;
    $key = $key x (length($ciphertext) / length($key) + 1);
    for( my $i=0; $i<length($ciphertext); $i++ ){
        $plaintext .=
            decrypt_letter( (substr($ciphertext,$i,1)),  (substr($key,
+$i,1)));
    }
    return $plaintext;
}


sub encrypt_letter{
    # encrypts a single letter of plaintext, given the plaintext
    # letter and the key to use for that letter's position.
    # The key is the first letter of the row to look in.
    my ($plain, $row) = @_;
    my $cipher;
    # in row n, ciphertext is plaintext + n, mod 26.
    $row     = ord(lc($row))   - ord('a');    # enable mod 26
    $plain  = ord(lc($plain)) - ord('a');    # enable mod 26
    $cipher = ($plain + $row) % 26;
    
    $cipher = chr($cipher + ord('a'));

    return uc($cipher);    #ciphertext in uppercase
}

sub decrypt_letter{
    # decrypts a single letter of ciphertext, given the ciphertext
    # letter and the key to use for that letter's position.
    # The key is the first letter of the row to look in.
    my ($cipher, $row) = @_;
    my $plain;
    # in row n, plaintext is ciphertext - n, mod 26.
    $row     = ord(lc($row))    - ord('a');    # enable mod 26
    $cipher = ord(lc($cipher)) - ord('a');    # enable mod 26
    $plain  = ($cipher - $row) % 26;
    
    $plain = chr($plain + ord('a'));

    return lc($plain);    #plaintext in lowercase
}