From a news:comp.lang.tcl posting by mailto:[email protected]In case anyone is interested, attached is what I use to encrypt/decrypt data files. Since I am trying to keep my program small, I decided to write my own functions instead of including another whole package like Trf.I haven't looked at them in a while, so they might not be as cleaned up as possible.I included a function I use to wrap it, but no full example code (too lazy), but it should be fairly easy to write :).Please let me know any suggestions/comments.Ryan
global enc_string global enc_idx proc {to_ascii} {char} { # set value 0 scan $char %c value return $value } proc {encrypt} {str} { # global enc_string global enc_idx set crypt_str "" for {set i 0} {$i < [string length $str]} {incr i 1} { set curnum [expr {[to_ascii [string index $str $i]] + [to_ascii [string index $enc_string $enc_idx]]}] if {$curnum > 255} {set curnum [expr {$curnum - 256}]} set crypt_char [format %c $curnum] set crypt_str "$crypt_str$crypt_char" set enc_idx [incr enc_idx 1] if {$enc_idx == [string length $enc_string]} {set enc_idx 0} } return $crypt_str } proc {decrypt} {str} { # global enc_string global enc_idx set crypt_str "" set strlen [string length $str] if {$strlen == 0} {return} for {set testx 0} {$testx < $strlen} {incr testx 1} { set curnum [expr {[to_ascii [string index $str $testx]]-[to_ascii [string index $enc_string $enc_idx]]}] if {$curnum < 0} {set curnum [expr {$curnum + 256}]} set crypt_str "$crypt_str[format %c $curnum]" set enc_idx [incr enc_idx 1] if {$enc_idx == [string length $enc_string]} {set enc_idx 0} } return $crypt_str } proc {readFile} {filename} { set ::enc_idx 0 set fp [open $filename r] fconfigure $fp -encoding identity set data [split [read $fp $size] \n] foreach line $data { puts [decrypt $line] } close $fp } proc {writeFile} {filename} { set enc_string "password" set enc_idx 0 set fp [open $filename r] fconfigure $fp -encoding identity # Write out your information using "puts $fp [encrypt XXXXX]" close $fp }
PT: What this method is doing is rotating the cipher text by the ascii value of the key. This is a very weak encryption algorithm. If you really need to do encryption you should be using something else and the Trf package has these (RCn, Blowfish etc). This rotation algorithm is really only sufficient for smudging the cipher text. That is making it a bit harder to read. An equivalent algorithm that is somewhat quicker to use is to xor the characters against the key phrase where a repeat pass decrypts the encoded stream:
proc XORcrypt {passphrase cleartext} { set r {} binary scan $passphrase c* l binary scan $cleartext c* d set pmax [llength $l] set cn 0 foreach {c} $d { set cp [lindex $l $cn] append r [format %c [expr {($c & 0xff) ^ ($cp & 0xff)}]] incr cn if {$cn >= $pmax} { set cn 0 } } return $r }Beware : Just wanted to add that I tried this and it worked well, however there's a chance that a character xor'ed with another can produce the eof character, so you have to fconfigure -eofchar to be blank.The rotation implementation given above is equivalent to
proc encrypt {passphrase cleartext} { set r {} binary scan $passphrase c* l binary scan $cleartext c* d set pmax [llength $l] set cn 0 foreach {c} $d { set cp [lindex $l $cn] append r [format %c [expr {($c & 0xff) + ($cp & 0xff)}]] incr cn if {$cn >= $pmax} { set cn 0 } } return $r }but using binary scan to split the string into a list and using foreach can improve the execution speed. Also the decrypt is the same but substituting subtraction for the addition.