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::commandSee also Base 64 encode/decode [L5 ]