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.
The file .vgnr in home directory contains the key or secret used to encrypt, decrypt.
Usage is, to encrypt :
tclsh vigenere.tcl filename => this will create a directory vgnr and create a file with the same filename but with encrypted content
to decrypt :
tclsh vigenere.tcl vgnr/filename => this will create a directory clear and create filename but with decrypted content
Here is a transcript of a linux session:
[lg@bjorn example]$ ll total 576 -rwxrwx---. 1 lg lg 579556 28 oct. 11:15 image.jpg -rw-rw-r--. 1 lg lg 6435 28 oct. 11:15 vigenere.tcl [lg@bjorn example]$ tclsh vigenere.tcl image.jpg [lg@bjorn example]$ ls -la vgnr/image.jpg -rw-rw-r--. 1 lg lg 782910 28 oct. 11:15 vgnr/image.jpg [lg@bjorn example]$ tclsh vigenere.tcl vgnr/image.jpg [lg@bjorn example]$ ls -la clear/image.jpg -rw-rw-r--. 1 lg lg 579556 28 oct. 11:16 clear/image.jpg [lg@bjorn example]$ md5sum image.jpg 532c492532e8c441cab0ed6f9de01962 image.jpg [lg@bjorn example]$ md5sum clear/image.jpg 532c492532e8c441cab0ed6f9de01962 clear/image.jpg
md5sum filename and md5sum clear/filename give the same md5sum.
The source code is also stored at [L3 ] and at [L4 ]
Here is the source code :
#! /usr/local/bin/tclsh8.6 # vigenere.tcl -- # # encrypt, decrypt a file following vigenere algorithm. # # a secret or key must be present as a file named .vgnr in home directory # # example: # # tclsh vigenere.tcl notes.txt # => will produce the file vgnr/notes.txt (encryption) # tclsh vigenere.tcl vgnr/notes.txt # => will produce the file clear/notes.txt (decryption) # # Copyright (c) 2009-2022 Laurent Gateau. # # version 1.3 # package require Tcl 8.6 namespace eval vigenere { namespace export encode decode encrypt decrypt variable alphabet64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" variable bufferlen 57 variable version "1.3" } # 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 == 1 } { set keyfile [open "~/.vgnr" "r"] fconfigure $keyfile -translation binary set key [read $keyfile] close $keyfile set filename [lindex $argv 0] set outFilename ${filename}.out if [string match "vgnr/*" $filename] { set mode "-decrypt" set outFilename "clear/[string range $filename 5 end]" if {![file exists "clear"]} { file mkdir "clear" } } else { set mode "-encrypt" set outFilename "vgnr/${filename}" if {![file exists "vgnr"]} { file mkdir "vgnr" } } switch -exact -- $mode { -encrypt { set fin [open $filename "r"] fconfigure $fin -translation binary set fout [open $outFilename "w"] fconfigure $fout -translation binary encrypt "$key" $fin $fout exit 0 } -decrypt { set fin [open $filename "r"] fconfigure $fin -translation binary set fout [open $outFilename "w"] fconfigure $fout -translation binary decrypt "$key" $fin $fout exit 0 } } } ::vigenere::usage } proc vigenere::usage {} { puts "usage: vigenere [vgnr/]<file>" puts " file ~/.vgnr must exists and will be the secret key" puts " example: vigenere input_file" puts " encrypt input_file as vgnr/input_file" puts " example: vigenere vgnr/input_file" puts " decrypt vgnr/input_file as clear/input_file" exit 1 } package provide vigenere $::vigenere::version vigenere::command
See also Base 64 encode/decode [L5 ]