Shrinking generator

Zarutian 20:06 30. desember 2006 (UTC): Not finished yet

gg 21:52 (GMT+01) 2006-12-30: Changed "SH" to "SA" (that is the correct term). You also need to link to the license if you want legal coverage, as far as I am aware.

Zarutian 21:55 30. desember 2005 (UTC): Details details. And legal coverage where?

 #####################################################
 # Tcl Code below by Zarutian here by released under #
 # CreativeCommons SA-BY license. Contact him if any #
 # other license is required.                        #
 # (SA stands for Share Alike and BY for give credit #
 # to who ever wrote the software or parts there of) #
 # http://creativecommons.org/licenses/by-sa/2.5/    #
 #####################################################

 proc repeat {body keyword cond} {
   uplevel 1 $body
   if {$keyword == "until"} {
     set cond "!([set cond])"
   } elseif {$keyword == "while"} {
     # left empty on purpose
   } else {
     error "repeat expected 'while' or 'until' as an keyword"
   }
   while {[uplevel 1 [list expr $cond]]} {
     uplevel 1 $body
   }
 }
 proc XOR args {
   if {[llength $args] == 1} { set args [lindex $args 0] }
   set work [lindex $args 0]
   set args [lrange $args 1 end]
   foreach item $args {
     set work [expr $work ^ $item]
   }
   return $work
 }
 proc leftshift {current polynominals} {
   set selected [list]
   foreach selector $polynominals {
     lappend selected [string index $current $selector]
   }
   set new_bit [XOR $selected]
   return "[string range $current 1 end][set new_bit]"
 }
 proc shrink_generate_keystream {seedA polynominalsA seedS polynominalsS keystream_length} {
   set registerA $seedA
   set registerS $seedS
   set keystream {}
   repeat {
     repeat {
       set new_bit [string index [set registerA [leftshift $registerA $polynominalsA]] end]
     } until {[string index [set registerS [leftshift $registerS $polynominalsS]] end] == "1"}
     append keystream $new_bit
   } until {[string length $keystream] == $keystream_length}
   return $keystream
 }
 proc crypt_with_shrinking_generator {seedA polynominalsA seedS polynominalsS message} {
   binary scan $message B* message
   set keystream [shrink_generate_keystream $seedA $polynominalsA $seedS $polynominalsS [string length $message]]
   set result ""
   set index 0
   repeat {
     append result [XOR [string index $keystream $index] [string index $message $index]]
     incr index
   } until {$index == [string length $message]}
   return [binary format B* $result]
 }