Version 6 of Encryption and Decryption

Updated 2009-09-18 08:42:42 by jdc

Note: This page describes Vigenere (vignere) a method of encryption that is not at all secure against cryptanalytic attack. There are much better encryption algorithms available elsewhere.


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
 }

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.