---- # vignere.tcl - Copyright (C) 2002 Pat Thoyts # # Provide a Tcl only implementation of the Vign�re cipher. # # ------------------------------------------------------------------------- # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # ------------------------------------------------------------------------- # @(#)$Id: 2884,v 1.1 2002-06-21 04:29:55 jcw Exp $ namespace eval vign�re { namespace export vign�re interp alias {} [namespace current]::encode \ {} [namespace current]::Cipher encode interp alias {} [namespace current]::decode \ {} [namespace current]::Cipher decode } # ------------------------------------------------------------------------- # Description: # An implementation of the Vign�re symmetric polyalphabetic cipher. # In this cipher each letter is encoded using a caesar rotation given by the # value of the corresponding letter in the key. # proc vign�re::Cipher {mode key plaintext} { binary scan $plaintext c* plainchars set K [Shifts $mode $key] set N 0 set M [llength $K] foreach c $plainchars { set n [lindex $K $N] set C [expr { (($c ^ 0x40) & 0x5F) < 27 ? (((($c ^ 0x40) & 0x5F) + $n - 1) % 26 + 1) | ($c & 0xe0) : $c }] if {$c != $C} { incr N if {$N >= $M} { set N 0} } append r [format %c $C] } return $r } # ------------------------------------------------------------------------- # Description: # The cipher operates by converting the key phrase into a sequence of shift # values from 1 to 26 that correspond to Caesar alphabets to use for enciphering # the current character. This procedure calculates the shifts from the key text. # proc vign�re::Shifts {mode keytext} { binary scan $keytext c* keychars set encode [string match "encode" $mode] foreach kc $keychars { set v [expr {($kc & 0x5f) - 0x41}] if {$encode} { lappend shifts $v } else { lappend shifts [expr {abs($v - 26)}] } } return $shifts } # ------------------------------------------------------------------------- # Description: # Encrypt data using the Vign�re cipher. Not secure (but better that rot13!) # proc vign�re::vign�re {args} { array set opts {filename {} mode encode key {}} while {[string match -* [lindex $args 0]]} { switch -glob -- [lindex $args 0] { -k* { set opts(key) [lindex $args 1] set args [lreplace $args 0 0] } -m* { set opts(mode) [lindex $args 1] set args [lreplace $args 0 0] } -f* { set opts(filename) [lindex $args 1] set args [lreplace $args 0 0] } -- { set args [lreplace $args 0 0] break } default { return -code error "bad option [lindex $args 0]:\ must be -key, -mode, -filename or --" } } set args [lreplace $args 0 0] } if {$opts(key) == {}} { return -code error "invalid args: -key must be specified" } if {$opts(filename) != {}} { set f [open $opts(filename) r] #fconfigure $f -translation binary set data [read $f] close $f } else { if {[llength $args] != 1} { return -code error "wrong \# args: should be\ \"vign�re ?-mode mode? -key phrase -file name | data\"" } set data [lindex $args 0] } if {[string match "encode" $opts(mode)]} { return [encode $opts(key) $data] } else { return [decode $opts(key) $data] } } # ------------------------------------------------------------------------- package provide vign�re 1.0 # ------------------------------------------------------------------------- # # Local variables: # mode: tcl # indent-tabs-mode: nil # End: ---- See also [uuencode], [base64], [caesar], [rot13] [Category Packages] [Category Crytography]