Version 16 of Vigenere

Updated 2020-04-26 17:09:38 by LGT

Here is a program that applies Vigenère's encryption method [L1 ] to files.

At first It transposes input to base 64 encoding [L2 ], then it applies Vigenere's algorithm.

Usage is, to encrypt :

        tclsh vigenere.tcl -encrypt "my secret key" inputfile.bin file.crypt

to decrypt :

        tclsh vigenere.tcl -decrypt "my secret key" file.crypt outputfile.bin

The source code is also stored at [L3 ] and at [L4 ]

Here is the source code :

    #! /usr/local/bin/tclsh8.6
    # vigenere.tcl --
    #
    #         provide method to encrypt and decrypt a file following vigenere algorithm.
    #
    #       encrypt read from a input stream and write encrypted data to an output stream.
    #       decrypt read from a encrypted input stream and write decrypted (clear) data to an output stream.
    #       streams should be "fconfigure"'d with "-translation binary" option.
    #
    # Copyright (c) 2009-2020 Laurent Gateau.
    #
    # version 1.2
    #
    package require Tcl 8.6
    
    namespace eval vigenere {
            namespace export encode decode encrypt decrypt        
            variable alphabet64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
            variable bufferlen 57 
            variable version "1.1"
    }
    
    # vigenere::engine --
    #
    # Arguments: 
    #    key and data variables must be part of alphabet64 
    #    key and data variables might result from binary encode base64 call
    #    encode must be either 1 (encode) or 0 (decode)
    #
    # Results:
    #    result is a cyphered string containing symbols from alphabet64
    #
    proc vigenere::engine { key data {encode -encode}} {
                    variable alphabet64
                    set result ""
                    set ii 0
                    set keylen [string length $key]
                    while {$ii < [string length $data]} {
                            set car [string index $data $ii]                        
                            if {$encode && ($car == "=")} {
                                    incr ii
                                    continue
                            }
                            set keyii [expr $ii % $keylen]
                            set keycar [string index $key $keyii]
                            set index1 [string first $car $alphabet64]
                            set index2 [string first $keycar $alphabet64]                        
                            if {$encode} {
                                    set jj [expr ($index1 + $index2) % 64]
                            } else {
                                    set jj [expr ($index1 - $index2) % 64]                
                            }
                            append result "[string index $alphabet64 $jj]"
                            incr ii
                    }
                    return $result
    }
    
    # vigenere::encode --        
    #
    # Arguments: 
    #    key and data variables must be part of alphabet64
    #    key and data variables might result from binary encode base64 call
    #
    # Results:
    #    result is a cyphered string containing symbols from alphabet64
    #
    proc vigenere::encode { key data } {
            return [vigenere::engine "$key" "$data" 1]
    }
    
    # vigenere::decode --
    #
    # Arguments: 
    #    key and data variables must contains only symbol from alphabet64
    #    key variable might result from a call of binary decode base64
    #
    # Results:
    #    result is a clear string containing symbols from alphabet64
    #    result might be a parameter given to a call of binary decode base64
    #
    proc vigenere::decode { key data } {
            return [vigenere::engine "$key" "$data" 0]
    }
    
    # vigenere::encrypt --
    #
    # Arguments:
    #    key is a pass phrase ; the longer the better secrets are kept.
    #    fin is the input stream
    #    fout is the output stream 
    # Results:
    #    fin has reached its end
    #    fout has been written with encrypted data
    #
    proc vigenere::encrypt { key fin fout } {
            variable bufferlen
            while { ! [eof $fin] } {
                    set input [read $fin $bufferlen]
                    set data [binary encode base64 -maxlen [expr $bufferlen * 4 / 3] $input]
                    puts $fout [::vigenere::encode [binary encode base64 "$key"] "$data"]
            }
    }
    
    # vigenere::decrypt --
    #
    # Arguments: 
    #   key is a pass phrase ; the longer the better secrets are kept.
    #   fin is the input stream
    #   fout is the output stream
    # 
    # Results:
    #   fin has reached its end
    #   fout has been written with decrypted (clear) data.
    #
    proc vigenere::decrypt { key fin fout } {
            while { ! [eof $fin] } {
                    set input [gets $fin]
                    set data [::vigenere::decode [binary encode base64 "$key"] "$input"]
                    puts -nonewline $fout [binary decode base64 "$data"]
            }
    }        
    
    # vigenere::command --
    #
    # Arguments:
    #    command line arguments : arc and argv
    #    mode is either -encrypt or -decrypt
    #    key is the cypher key
    #    input file name
    #    output file name
    #
    # Results:
    #    write output file or display usage.
    #
    proc vigenere::command {} {
            global argc argv
            if { $argc > 0 } {
                    set mode [lindex $argv 0]                
                    set key [lindex $argv 1] 
                    switch -exact -- $mode {
                            -encrypt {
                                    set fin [open [lindex $argv 2] "r"]
                                    fconfigure $fin -translation binary
                                    set fout [open [lindex $argv 3] "w"]
                                    fconfigure $fout -translation binary
                                    encrypt "$key" $fin $fout        
                                    exit 0
                            }
                            -decrypt {
                                    set fin [open [lindex $argv 2] "r"]
                                    fconfigure $fin -translation binary
                                    set fout [open [lindex $argv 3] "w"]
                                    fconfigure $fout -translation binary
                                    decrypt "$key" $fin $fout                                
                                    exit 0
                            }
                    }
            }
            ::vigenere::usage 
             
    }
    
    proc vigenere::usage {} {
        puts "usage: (-encrypt|-decrypt) key input_file output_file"
        exit 1
    }
    
    package provide vigenere $::vigenere::version
    
    vigenere::command

See also Base 64 encode/decode [L5 ]