summaryrefslogtreecommitdiffstats
path: root/tcllib/modules/blowfish
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 19:39:39 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-27 19:39:39 (GMT)
commitea28451286d3ea4a772fa174483f9a7a66bb1ab3 (patch)
tree6ee9d8a7848333a7ceeee3b13d492e40225f8b86 /tcllib/modules/blowfish
parentb5ca09bae0d6a1edce939eea03594dd56383f2c8 (diff)
parent7c621da28f07e449ad90c387344f07a453927569 (diff)
downloadblt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.zip
blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.gz
blt-ea28451286d3ea4a772fa174483f9a7a66bb1ab3.tar.bz2
Merge commit '7c621da28f07e449ad90c387344f07a453927569' as 'tcllib'
Diffstat (limited to 'tcllib/modules/blowfish')
-rw-r--r--tcllib/modules/blowfish/ChangeLog136
-rw-r--r--tcllib/modules/blowfish/blowfish.bench66
-rw-r--r--tcllib/modules/blowfish/blowfish.man164
-rw-r--r--tcllib/modules/blowfish/blowfish.tcl724
-rw-r--r--tcllib/modules/blowfish/blowfish.test315
-rw-r--r--tcllib/modules/blowfish/pkgIndex.tcl5
6 files changed, 1410 insertions, 0 deletions
diff --git a/tcllib/modules/blowfish/ChangeLog b/tcllib/modules/blowfish/ChangeLog
new file mode 100644
index 0000000..92da300
--- /dev/null
+++ b/tcllib/modules/blowfish/ChangeLog
@@ -0,0 +1,136 @@
+2013-02-01 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.15 ========================
+ *
+
+2011-12-13 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.14 ========================
+ *
+
+2011-01-24 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.13 ========================
+ *
+
+2009-12-07 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.12 ========================
+ *
+
+2008-12-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.11.1 ========================
+ *
+
+2008-10-16 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.11 ========================
+ *
+
+2007-09-17 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.test: Fix default if -dir option is not specified it
+ defaults to 'enc' and this fails to match 'encrypt' and results in
+ the default operation being 'decrypt'
+
+2007-09-12 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.10 ========================
+ *
+
+2007-08-20 Andreas Kupries <andreask@activestate.com>
+
+ * blowfish.man: Version bumped to 1.0.3 due to bugfix at Mar 12.
+ * blowfish.tcl:
+ * pkgIndex.tcl:
+
+2007-03-19 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * blowfish.man: Fixed all warnings due to use of now deprecated
+ commands. Added a section about how to give feedback.
+
+2007-03-12 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.tcl: Applied patch from bug #1664626 by Neil Madden to
+ the fix variable mis-naming in the Chunk command.
+
+2006-10-03 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.9 ========================
+ *
+
+2006-10-02 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.test: Document the padding and added -pad option
+ * blowfish.tcl: to turn off padding or change the pad char.
+ * blowfish.man: Increment the patchlevel.
+ * pkgIndex.tcl:
+
+2006-09-19 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.tcl: Bug 1560822: hyphen handling.
+ * blowfish.test: Added test for hyphen handling.
+ * blowfish.man: Note -- for option termination.
+ * pkgIndex.tcl: Increment patchlevel.
+
+2006-01-22 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * blowfish.test: More boilerplate simplified via use of test support.
+
+2006-01-19 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * blowfish.test: Hooked into the new common test support code.
+
+2005-10-18 Andreas Kupries <andreask@activestate.com>
+
+ * blowfish.bench: Extended with benchmarks for the keyschedule.
+
+2005-10-06 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ *
+ * Released and tagged Tcllib 1.8 ========================
+ *
+
+2005-09-04 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.tcl: Added some performance enhancements. Added some
+ * blowfish.test: documentation for the API. Fix testing to test
+ * blowfish.man: each implementation. Checked with tcl 8.2.
+ * pkgIndex.tcl:
+
+2005-06-21 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+ * blowfish.man: Fixed a typo.
+
+2005-06-22 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.man: new file
+
+2004-12-21 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.tcl: Fixed bug in search for Trfcrypt (noticed by
+ Antirez). Added a Reset command to the programming API to permit
+ reuse of a key with a new initialization vector..
+
+2004-12-07 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.tcl: Add in support for Trfcrypt implementation.
+ * blowfish.test: Support variable key length and added tests.
+
+2004-12-06 Pat Thoyts <patthoyts@users.sourceforge.net>
+
+ * blowfish.tcl: Imported Frank Pilhofer's pure-Tcl implementation
+ * blowfish.test: from the Tcler's wiki. Modified to remove the
+ Itcl code and to conform to the tcllib programming standards and
+ conventions. Test file includes standard test vectors.
+
+
diff --git a/tcllib/modules/blowfish/blowfish.bench b/tcllib/modules/blowfish/blowfish.bench
new file mode 100644
index 0000000..f3ece4e
--- /dev/null
+++ b/tcllib/modules/blowfish/blowfish.bench
@@ -0,0 +1,66 @@
+# -*- tcl -*-
+# Tcl Benchmark File
+#
+# This file contains a number of benchmarks for the 'blowfish' module.
+# This allow developers to monitor/gauge/track package performance.
+#
+# (c) 2005 Andreas Kupries <andreas_kupries@users.sourceforge.net>
+
+# We need at least version 8.2 for the package and thus the
+# benchmarks.
+
+if {![package vsatisfies [package provide Tcl] 8.2]} {
+ return
+}
+
+# ### ### ### ######### ######### ######### ###########################
+## Setting up the environment ...
+
+package forget blowfish
+catch {namespace delete ::blowfish}
+source [file join [file dirname [info script]] blowfish.tcl]
+
+set i [binary format H* 000000000000000]
+set p [binary format H* 00112233445566778899aabbccddeeff]
+
+set k [binary format H* 000102030405060]
+set c [binary format H* 69c4e0d86a7b0430d8cdb78070b4c55a]
+
+# ### ### ### ######### ######### ######### ###########################
+## Benchmarks.
+
+bench -desc "BLOWFISH ECB encryption" -body {
+ blowfish::blowfish -mode ecb -dir enc -key $k -iv $i $p
+}
+
+bench -desc "BLOWFISH ECB decryption" -body {
+ blowfish::blowfish -mode ecb -dir dec -key $k -iv $i $c
+}
+
+bench -desc "BLOWFISH ECB encryption core" -pre {
+ set key [blowfish::Init ecb $k $i]
+} -body {
+ blowfish::Encrypt $key $p
+} -post {
+ blowfish::Final $key
+}
+
+bench -desc "BLOWFISH ECB decryption core" -pre {
+ set key [blowfish::Init ecb $k $i]
+} -body {
+ blowfish::Decrypt $key $c
+} -post {
+ blowfish::Final $key
+}
+
+bench -desc "BLOWFISH ECB keyschedule" -body {
+ blowfish::Final [blowfish::Init ecb $k $i]
+}
+
+bench -desc "BLOWFISH CBC keyschedule" -body {
+ blowfish::Final [blowfish::Init cbc $k $i]
+}
+
+
+# ### ### ### ######### ######### ######### ###########################
+## Complete
diff --git a/tcllib/modules/blowfish/blowfish.man b/tcllib/modules/blowfish/blowfish.man
new file mode 100644
index 0000000..8ee4627
--- /dev/null
+++ b/tcllib/modules/blowfish/blowfish.man
@@ -0,0 +1,164 @@
+[comment {-*- tcl -*- doctools manpage}]
+[manpage_begin blowfish n 1.0.3]
+[see_also 3des]
+[see_also des]
+[see_also rc4]
+[keywords {block cipher}]
+[keywords blowfish]
+[keywords cryptography]
+[keywords encryption]
+[keywords security]
+[copyright {2003, Pat Thoyts <patthoyts@users.sourceforge.net>}]
+[moddesc {Blowfish Block Cipher}]
+[titledesc {Implementation of the Blowfish block cipher}]
+[category {Hashes, checksums, and encryption}]
+[require Tcl 8.4]
+[require blowfish [opt 1.0.4]]
+[description]
+[para]
+
+This package is an implementation in Tcl of the Blowfish algorithm
+developed by Bruce Schneier [lb]1[rb]. Blowfish is a 64-bit block cipher
+designed to operate quickly on 32 bit architectures and accepting a
+variable key length. This implementation supports ECB and CBC mode
+blowfish encryption.
+
+[section {COMMANDS}]
+
+[list_begin definitions]
+
+[call [cmd "::blowfish::blowfish"] \
+ [opt [arg "-mode [lb]ecb|cbc[rb]"]] \
+ [opt [arg "-dir [lb]encrypt|decrypt[rb]"]] \
+ [arg "-key keydata"] \
+ [opt [arg "-iv vector"]] \
+ [opt [arg "-out channel"]] \
+ [opt [arg "-chunksize size"]] \
+ [opt [arg "-pad padchar"]] \
+ [lb] [arg "-in channel"] | \
+ [opt [arg "--"]] [arg "data"] [rb]]
+
+Perform the [package blowfish] algorithm on either the data provided
+by the argument or on the data read from the [arg "-in"] channel. If
+an [arg "-out"] channel is given then the result will be written to
+this channel.
+
+[para]
+
+The [arg -key] option must be given. This parameter takes a binary
+string of variable length and is used to generate the [package blowfish]
+key schedule. You should be aware that creating a key
+schedule is quite an expensive operation in blowfish so it is worth
+reusing the key where possible. See [cmd Reset].
+
+[para]
+
+The [arg -mode] and [arg -dir] options are optional and default to cbc
+mode and encrypt respectively. The initialization vector [arg -iv]
+takes an 8 byte binary argument which defaults to 8 zeros.
+See [sectref "MODES OF OPERATION"] for more about available modes and
+their uses.
+
+[para]
+
+Blowfish is a 64-bit block cipher. This means that the data must be
+provided in units that are a multiple of 8 bytes. The [cmd blowfish]
+command will by default add nul characters to pad the input data to a
+multiple of 8 bytes if necessary. The programming api commands will
+never add padding and instead will raise an error if the input is not
+a multiple of the block size. The [arg -pad] option can be used to
+change the padding character or to disable padding if the empty string
+is provided as the argument.
+
+[list_end]
+
+[section "PROGRAMMING INTERFACE"]
+
+[list_begin definitions]
+
+[call [cmd "::blowfish::Init"] [arg "mode"] [arg "keydata"] [arg "iv"]]
+
+Construct a new blowfish key schedule using the specified key data and
+the given initialization vector. The initialization vector is not used
+with ECB mode but is important for CBC mode.
+See [sectref "MODES OF OPERATION"] for details about cipher modes.
+
+[call [cmd "::blowfish::Encrypt"] [arg "Key"] [arg "data"]]
+
+Use a prepared key acquired by calling [cmd Init] to encrypt the
+provided data. The data argument should be a binary array that is a
+multiple of the block size of 8 bytes. The result is a binary
+array the same size as the input of encrypted data.
+
+[call [cmd "::blowfish::Decrypt"] [arg "Key"] [arg "data"]]
+
+Decipher data using the key. Note that the same key may be used to
+encrypt and decrypt data provided that the initialization vector is
+reset appropriately for CBC mode.
+
+[call [cmd "::blowfish::Reset"] [arg "Key"] [arg "iv"]]
+
+Reset the initialization vector. This permits the programmer to re-use
+a key and avoid the cost of re-generating the key schedule where the
+same key data is being used multiple times.
+
+[call [cmd "::blowfish::Final"] [arg "Key"]]
+
+This should be called to clean up resources associated with [arg Key].
+Once this function has been called the key may not be used again.
+
+[list_end]
+
+[section "MODES OF OPERATION"]
+
+[list_begin definitions]
+
+[def "Electronic Code Book (ECB)"]
+ECB is the basic mode of all block ciphers. Each block is encrypted
+independently and so identical plain text will produce identical
+output when encrypted with the same key. Any encryption errors will
+only affect a single block however this is vulnerable to known
+plaintext attacks.
+
+[def "Cipher Block Chaining (CBC)"]
+
+CBC mode uses the output of the last block encryption to affect the
+current block. An initialization vector of the same size as the cipher
+block size is used to handle the first block. The initialization
+vector should be chosen randomly and transmitted as the first block of
+the output. Errors in encryption affect the current block and the next
+block after which the cipher will correct itself. CBC is the most
+commonly used mode in software encryption.
+
+[list_end]
+
+[section "EXAMPLES"]
+
+[example {
+% blowfish::blowfish -hex -mode ecb -dir encrypt -key secret01 "hello, world!"
+d0d8f27e7a374b9e2dbd9938dd04195a
+}]
+
+[example {
+ set Key [blowfish::Init cbc $eight_bytes_key_data $eight_byte_iv]
+ append ciphertext [blowfish::Encrypt $Key $plaintext]
+ append ciphertext [blowfish::Encrypt $Key $additional_plaintext]
+ blowfish::Final $Key
+}]
+
+[section "REFERENCES"]
+
+[list_begin enumerated]
+
+[enum]
+ Schneier, B. "Applied Cryptography, 2nd edition", 1996,
+ ISBN 0-471-11709-9, pub. John Wiley & Sons.
+
+[list_end]
+
+[section AUTHORS]
+Frank Pilhofer, Pat Thoyts
+
+[vset CATEGORY blowfish]
+[include ../doctools2base/include/feedback.inc]
+[manpage_end]
diff --git a/tcllib/modules/blowfish/blowfish.tcl b/tcllib/modules/blowfish/blowfish.tcl
new file mode 100644
index 0000000..2610ae1
--- /dev/null
+++ b/tcllib/modules/blowfish/blowfish.tcl
@@ -0,0 +1,724 @@
+# blowfish.tcl -
+#
+# Pure-Tcl implementation of the Blowfish algorithm.
+#
+# See http://www.schneier.com/blowfish.html for information about the
+# Blowfish algorithm.
+#
+# The implementation is derived from Paul Kocher's implementation,
+# available at http://www.schneier.com/blowfish-download.html
+#
+# Copyright (C) 2004 Frank Pilhofer
+# Copyright (C) 2004 Pat Thoyts <patthoyts@users.sourceforge.net>
+#
+# -------------------------------------------------------------------------
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+# -------------------------------------------------------------------------
+#
+
+package require Tcl 8.2
+
+namespace eval blowfish {
+ variable uid
+ if {![info exists uid]} { set uid 0 }
+
+ variable accel
+ array set accel {trf 0}
+
+ namespace export blowfish
+
+ variable ORIG_P {
+ 0x243F6A88 0x85A308D3 0x13198A2E 0x03707344
+ 0xA4093822 0x299F31D0 0x082EFA98 0xEC4E6C89
+ 0x452821E6 0x38D01377 0xBE5466CF 0x34E90C6C
+ 0xC0AC29B7 0xC97C50DD 0x3F84D5B5 0xB5470917
+ 0x9216D5D9 0x8979FB1B
+ }
+
+ variable ORIG_S {
+ 0xD1310BA6 0x98DFB5AC 0x2FFD72DB 0xD01ADFB7
+ 0xB8E1AFED 0x6A267E96 0xBA7C9045 0xF12C7F99
+ 0x24A19947 0xB3916CF7 0x0801F2E2 0x858EFC16
+ 0x636920D8 0x71574E69 0xA458FEA3 0xF4933D7E
+ 0x0D95748F 0x728EB658 0x718BCD58 0x82154AEE
+ 0x7B54A41D 0xC25A59B5 0x9C30D539 0x2AF26013
+ 0xC5D1B023 0x286085F0 0xCA417918 0xB8DB38EF
+ 0x8E79DCB0 0x603A180E 0x6C9E0E8B 0xB01E8A3E
+ 0xD71577C1 0xBD314B27 0x78AF2FDA 0x55605C60
+ 0xE65525F3 0xAA55AB94 0x57489862 0x63E81440
+ 0x55CA396A 0x2AAB10B6 0xB4CC5C34 0x1141E8CE
+ 0xA15486AF 0x7C72E993 0xB3EE1411 0x636FBC2A
+ 0x2BA9C55D 0x741831F6 0xCE5C3E16 0x9B87931E
+ 0xAFD6BA33 0x6C24CF5C 0x7A325381 0x28958677
+ 0x3B8F4898 0x6B4BB9AF 0xC4BFE81B 0x66282193
+ 0x61D809CC 0xFB21A991 0x487CAC60 0x5DEC8032
+ 0xEF845D5D 0xE98575B1 0xDC262302 0xEB651B88
+ 0x23893E81 0xD396ACC5 0x0F6D6FF3 0x83F44239
+ 0x2E0B4482 0xA4842004 0x69C8F04A 0x9E1F9B5E
+ 0x21C66842 0xF6E96C9A 0x670C9C61 0xABD388F0
+ 0x6A51A0D2 0xD8542F68 0x960FA728 0xAB5133A3
+ 0x6EEF0B6C 0x137A3BE4 0xBA3BF050 0x7EFB2A98
+ 0xA1F1651D 0x39AF0176 0x66CA593E 0x82430E88
+ 0x8CEE8619 0x456F9FB4 0x7D84A5C3 0x3B8B5EBE
+ 0xE06F75D8 0x85C12073 0x401A449F 0x56C16AA6
+ 0x4ED3AA62 0x363F7706 0x1BFEDF72 0x429B023D
+ 0x37D0D724 0xD00A1248 0xDB0FEAD3 0x49F1C09B
+ 0x075372C9 0x80991B7B 0x25D479D8 0xF6E8DEF7
+ 0xE3FE501A 0xB6794C3B 0x976CE0BD 0x04C006BA
+ 0xC1A94FB6 0x409F60C4 0x5E5C9EC2 0x196A2463
+ 0x68FB6FAF 0x3E6C53B5 0x1339B2EB 0x3B52EC6F
+ 0x6DFC511F 0x9B30952C 0xCC814544 0xAF5EBD09
+ 0xBEE3D004 0xDE334AFD 0x660F2807 0x192E4BB3
+ 0xC0CBA857 0x45C8740F 0xD20B5F39 0xB9D3FBDB
+ 0x5579C0BD 0x1A60320A 0xD6A100C6 0x402C7279
+ 0x679F25FE 0xFB1FA3CC 0x8EA5E9F8 0xDB3222F8
+ 0x3C7516DF 0xFD616B15 0x2F501EC8 0xAD0552AB
+ 0x323DB5FA 0xFD238760 0x53317B48 0x3E00DF82
+ 0x9E5C57BB 0xCA6F8CA0 0x1A87562E 0xDF1769DB
+ 0xD542A8F6 0x287EFFC3 0xAC6732C6 0x8C4F5573
+ 0x695B27B0 0xBBCA58C8 0xE1FFA35D 0xB8F011A0
+ 0x10FA3D98 0xFD2183B8 0x4AFCB56C 0x2DD1D35B
+ 0x9A53E479 0xB6F84565 0xD28E49BC 0x4BFB9790
+ 0xE1DDF2DA 0xA4CB7E33 0x62FB1341 0xCEE4C6E8
+ 0xEF20CADA 0x36774C01 0xD07E9EFE 0x2BF11FB4
+ 0x95DBDA4D 0xAE909198 0xEAAD8E71 0x6B93D5A0
+ 0xD08ED1D0 0xAFC725E0 0x8E3C5B2F 0x8E7594B7
+ 0x8FF6E2FB 0xF2122B64 0x8888B812 0x900DF01C
+ 0x4FAD5EA0 0x688FC31C 0xD1CFF191 0xB3A8C1AD
+ 0x2F2F2218 0xBE0E1777 0xEA752DFE 0x8B021FA1
+ 0xE5A0CC0F 0xB56F74E8 0x18ACF3D6 0xCE89E299
+ 0xB4A84FE0 0xFD13E0B7 0x7CC43B81 0xD2ADA8D9
+ 0x165FA266 0x80957705 0x93CC7314 0x211A1477
+ 0xE6AD2065 0x77B5FA86 0xC75442F5 0xFB9D35CF
+ 0xEBCDAF0C 0x7B3E89A0 0xD6411BD3 0xAE1E7E49
+ 0x00250E2D 0x2071B35E 0x226800BB 0x57B8E0AF
+ 0x2464369B 0xF009B91E 0x5563911D 0x59DFA6AA
+ 0x78C14389 0xD95A537F 0x207D5BA2 0x02E5B9C5
+ 0x83260376 0x6295CFA9 0x11C81968 0x4E734A41
+ 0xB3472DCA 0x7B14A94A 0x1B510052 0x9A532915
+ 0xD60F573F 0xBC9BC6E4 0x2B60A476 0x81E67400
+ 0x08BA6FB5 0x571BE91F 0xF296EC6B 0x2A0DD915
+ 0xB6636521 0xE7B9F9B6 0xFF34052E 0xC5855664
+ 0x53B02D5D 0xA99F8FA1 0x08BA4799 0x6E85076A
+ 0x4B7A70E9 0xB5B32944 0xDB75092E 0xC4192623
+ 0xAD6EA6B0 0x49A7DF7D 0x9CEE60B8 0x8FEDB266
+ 0xECAA8C71 0x699A17FF 0x5664526C 0xC2B19EE1
+ 0x193602A5 0x75094C29 0xA0591340 0xE4183A3E
+ 0x3F54989A 0x5B429D65 0x6B8FE4D6 0x99F73FD6
+ 0xA1D29C07 0xEFE830F5 0x4D2D38E6 0xF0255DC1
+ 0x4CDD2086 0x8470EB26 0x6382E9C6 0x021ECC5E
+ 0x09686B3F 0x3EBAEFC9 0x3C971814 0x6B6A70A1
+ 0x687F3584 0x52A0E286 0xB79C5305 0xAA500737
+ 0x3E07841C 0x7FDEAE5C 0x8E7D44EC 0x5716F2B8
+ 0xB03ADA37 0xF0500C0D 0xF01C1F04 0x0200B3FF
+ 0xAE0CF51A 0x3CB574B2 0x25837A58 0xDC0921BD
+ 0xD19113F9 0x7CA92FF6 0x94324773 0x22F54701
+ 0x3AE5E581 0x37C2DADC 0xC8B57634 0x9AF3DDA7
+ 0xA9446146 0x0FD0030E 0xECC8C73E 0xA4751E41
+ 0xE238CD99 0x3BEA0E2F 0x3280BBA1 0x183EB331
+ 0x4E548B38 0x4F6DB908 0x6F420D03 0xF60A04BF
+ 0x2CB81290 0x24977C79 0x5679B072 0xBCAF89AF
+ 0xDE9A771F 0xD9930810 0xB38BAE12 0xDCCF3F2E
+ 0x5512721F 0x2E6B7124 0x501ADDE6 0x9F84CD87
+ 0x7A584718 0x7408DA17 0xBC9F9ABC 0xE94B7D8C
+ 0xEC7AEC3A 0xDB851DFA 0x63094366 0xC464C3D2
+ 0xEF1C1847 0x3215D908 0xDD433B37 0x24C2BA16
+ 0x12A14D43 0x2A65C451 0x50940002 0x133AE4DD
+ 0x71DFF89E 0x10314E55 0x81AC77D6 0x5F11199B
+ 0x043556F1 0xD7A3C76B 0x3C11183B 0x5924A509
+ 0xF28FE6ED 0x97F1FBFA 0x9EBABF2C 0x1E153C6E
+ 0x86E34570 0xEAE96FB1 0x860E5E0A 0x5A3E2AB3
+ 0x771FE71C 0x4E3D06FA 0x2965DCB9 0x99E71D0F
+ 0x803E89D6 0x5266C825 0x2E4CC978 0x9C10B36A
+ 0xC6150EBA 0x94E2EA78 0xA5FC3C53 0x1E0A2DF4
+ 0xF2F74EA7 0x361D2B3D 0x1939260F 0x19C27960
+ 0x5223A708 0xF71312B6 0xEBADFE6E 0xEAC31F66
+ 0xE3BC4595 0xA67BC883 0xB17F37D1 0x018CFF28
+ 0xC332DDEF 0xBE6C5AA5 0x65582185 0x68AB9802
+ 0xEECEA50F 0xDB2F953B 0x2AEF7DAD 0x5B6E2F84
+ 0x1521B628 0x29076170 0xECDD4775 0x619F1510
+ 0x13CCA830 0xEB61BD96 0x0334FE1E 0xAA0363CF
+ 0xB5735C90 0x4C70A239 0xD59E9E0B 0xCBAADE14
+ 0xEECC86BC 0x60622CA7 0x9CAB5CAB 0xB2F3846E
+ 0x648B1EAF 0x19BDF0CA 0xA02369B9 0x655ABB50
+ 0x40685A32 0x3C2AB4B3 0x319EE9D5 0xC021B8F7
+ 0x9B540B19 0x875FA099 0x95F7997E 0x623D7DA8
+ 0xF837889A 0x97E32D77 0x11ED935F 0x16681281
+ 0x0E358829 0xC7E61FD6 0x96DEDFA1 0x7858BA99
+ 0x57F584A5 0x1B227263 0x9B83C3FF 0x1AC24696
+ 0xCDB30AEB 0x532E3054 0x8FD948E4 0x6DBC3128
+ 0x58EBF2EF 0x34C6FFEA 0xFE28ED61 0xEE7C3C73
+ 0x5D4A14D9 0xE864B7E3 0x42105D14 0x203E13E0
+ 0x45EEE2B6 0xA3AAABEA 0xDB6C4F15 0xFACB4FD0
+ 0xC742F442 0xEF6ABBB5 0x654F3B1D 0x41CD2105
+ 0xD81E799E 0x86854DC7 0xE44B476A 0x3D816250
+ 0xCF62A1F2 0x5B8D2646 0xFC8883A0 0xC1C7B6A3
+ 0x7F1524C3 0x69CB7492 0x47848A0B 0x5692B285
+ 0x095BBF00 0xAD19489D 0x1462B174 0x23820E00
+ 0x58428D2A 0x0C55F5EA 0x1DADF43E 0x233F7061
+ 0x3372F092 0x8D937E41 0xD65FECF1 0x6C223BDB
+ 0x7CDE3759 0xCBEE7460 0x4085F2A7 0xCE77326E
+ 0xA6078084 0x19F8509E 0xE8EFD855 0x61D99735
+ 0xA969A7AA 0xC50C06C2 0x5A04ABFC 0x800BCADC
+ 0x9E447A2E 0xC3453484 0xFDD56705 0x0E1E9EC9
+ 0xDB73DBD3 0x105588CD 0x675FDA79 0xE3674340
+ 0xC5C43465 0x713E38D8 0x3D28F89E 0xF16DFF20
+ 0x153E21E7 0x8FB03D4A 0xE6E39F2B 0xDB83ADF7
+ 0xE93D5A68 0x948140F7 0xF64C261C 0x94692934
+ 0x411520F7 0x7602D4F7 0xBCF46B2E 0xD4A20068
+ 0xD4082471 0x3320F46A 0x43B7D4B7 0x500061AF
+ 0x1E39F62E 0x97244546 0x14214F74 0xBF8B8840
+ 0x4D95FC1D 0x96B591AF 0x70F4DDD3 0x66A02F45
+ 0xBFBC09EC 0x03BD9785 0x7FAC6DD0 0x31CB8504
+ 0x96EB27B3 0x55FD3941 0xDA2547E6 0xABCA0A9A
+ 0x28507825 0x530429F4 0x0A2C86DA 0xE9B66DFB
+ 0x68DC1462 0xD7486900 0x680EC0A4 0x27A18DEE
+ 0x4F3FFEA2 0xE887AD8C 0xB58CE006 0x7AF4D6B6
+ 0xAACE1E7C 0xD3375FEC 0xCE78A399 0x406B2A42
+ 0x20FE9E35 0xD9F385B9 0xEE39D7AB 0x3B124E8B
+ 0x1DC9FAF7 0x4B6D1856 0x26A36631 0xEAE397B2
+ 0x3A6EFA74 0xDD5B4332 0x6841E7F7 0xCA7820FB
+ 0xFB0AF54E 0xD8FEB397 0x454056AC 0xBA489527
+ 0x55533A3A 0x20838D87 0xFE6BA9B7 0xD096954B
+ 0x55A867BC 0xA1159A58 0xCCA92963 0x99E1DB33
+ 0xA62A4A56 0x3F3125F9 0x5EF47E1C 0x9029317C
+ 0xFDF8E802 0x04272F70 0x80BB155C 0x05282CE3
+ 0x95C11548 0xE4C66D22 0x48C1133F 0xC70F86DC
+ 0x07F9C9EE 0x41041F0F 0x404779A4 0x5D886E17
+ 0x325F51EB 0xD59BC0D1 0xF2BCC18F 0x41113564
+ 0x257B7834 0x602A9C60 0xDFF8E8A3 0x1F636C1B
+ 0x0E12B4C2 0x02E1329E 0xAF664FD1 0xCAD18115
+ 0x6B2395E0 0x333E92E1 0x3B240B62 0xEEBEB922
+ 0x85B2A20E 0xE6BA0D99 0xDE720C8C 0x2DA2F728
+ 0xD0127845 0x95B794FD 0x647D0862 0xE7CCF5F0
+ 0x5449A36F 0x877D48FA 0xC39DFD27 0xF33E8D1E
+ 0x0A476341 0x992EFF74 0x3A6F6EAB 0xF4F8FD37
+ 0xA812DC60 0xA1EBDDF8 0x991BE14C 0xDB6E6B0D
+ 0xC67B5510 0x6D672C37 0x2765D43B 0xDCD0E804
+ 0xF1290DC7 0xCC00FFA3 0xB5390F92 0x690FED0B
+ 0x667B9FFB 0xCEDB7D9C 0xA091CF0B 0xD9155EA3
+ 0xBB132F88 0x515BAD24 0x7B9479BF 0x763BD6EB
+ 0x37392EB3 0xCC115979 0x8026E297 0xF42E312D
+ 0x6842ADA7 0xC66A2B3B 0x12754CCC 0x782EF11C
+ 0x6A124237 0xB79251E7 0x06A1BBE6 0x4BFB6350
+ 0x1A6B1018 0x11CAEDFA 0x3D25BDD8 0xE2E1C3C9
+ 0x44421659 0x0A121386 0xD90CEC6E 0xD5ABEA2A
+ 0x64AF674E 0xDA86A85F 0xBEBFE988 0x64E4C3FE
+ 0x9DBC8057 0xF0F7C086 0x60787BF8 0x6003604D
+ 0xD1FD8346 0xF6381FB0 0x7745AE04 0xD736FCCC
+ 0x83426B33 0xF01EAB71 0xB0804187 0x3C005E5F
+ 0x77A057BE 0xBDE8AE24 0x55464299 0xBF582E61
+ 0x4E58F48F 0xF2DDFDA2 0xF474EF38 0x8789BDC2
+ 0x5366F9C3 0xC8B38E74 0xB475F255 0x46FCD9B9
+ 0x7AEB2661 0x8B1DDF84 0x846A0E79 0x915F95E2
+ 0x466E598E 0x20B45770 0x8CD55591 0xC902DE4C
+ 0xB90BACE1 0xBB8205D0 0x11A86248 0x7574A99E
+ 0xB77F19B6 0xE0A9DC09 0x662D09A1 0xC4324633
+ 0xE85A1F02 0x09F0BE8C 0x4A99A025 0x1D6EFE10
+ 0x1AB93D1D 0x0BA5A4DF 0xA186F20F 0x2868F169
+ 0xDCB7DA83 0x573906FE 0xA1E2CE9B 0x4FCD7F52
+ 0x50115E01 0xA70683FA 0xA002B5C4 0x0DE6D027
+ 0x9AF88C27 0x773F8641 0xC3604C06 0x61A806B5
+ 0xF0177A28 0xC0F586E0 0x006058AA 0x30DC7D62
+ 0x11E69ED7 0x2338EA63 0x53C2DD94 0xC2C21634
+ 0xBBCBEE56 0x90BCB6DE 0xEBFC7DA1 0xCE591D76
+ 0x6F05E409 0x4B7C0188 0x39720A3D 0x7C927C24
+ 0x86E3725F 0x724D9DB9 0x1AC15BB4 0xD39EB8FC
+ 0xED545578 0x08FCA5B5 0xD83D7CD3 0x4DAD0FC4
+ 0x1E50EF5E 0xB161E6F8 0xA28514D9 0x6C51133C
+ 0x6FD5C7E7 0x56E14EC4 0x362ABFCE 0xDDC6C837
+ 0xD79A3234 0x92638212 0x670EFA8E 0x406000E0
+ 0x3A39CE37 0xD3FAF5CF 0xABC27737 0x5AC52D1B
+ 0x5CB0679E 0x4FA33742 0xD3822740 0x99BC9BBE
+ 0xD5118E9D 0xBF0F7315 0xD62D1C7E 0xC700C47B
+ 0xB78C1B6B 0x21A19045 0xB26EB1BE 0x6A366EB4
+ 0x5748AB2F 0xBC946E79 0xC6A376D2 0x6549C2C8
+ 0x530FF8EE 0x468DDE7D 0xD5730A1D 0x4CD04DC6
+ 0x2939BBDB 0xA9BA4650 0xAC9526E8 0xBE5EE304
+ 0xA1FAD5F0 0x6A2D519A 0x63EF8CE2 0x9A86EE22
+ 0xC089C2B8 0x43242EF6 0xA51E03AA 0x9CF2D0A4
+ 0x83C061BA 0x9BE96A4D 0x8FE51550 0xBA645BD6
+ 0x2826A2F9 0xA73A3AE1 0x4BA99586 0xEF5562E9
+ 0xC72FEFD3 0xF752F7DA 0x3F046F69 0x77FA0A59
+ 0x80E4A915 0x87B08601 0x9B09E6AD 0x3B3EE593
+ 0xE990FD5A 0x9E34D797 0x2CF0B7D9 0x022B8B51
+ 0x96D5AC3A 0x017DA67D 0xD1CF3ED6 0x7C7D2D28
+ 0x1F9F25CF 0xADF2B89B 0x5AD6B472 0x5A88F54C
+ 0xE029AC71 0xE019A5E6 0x47B0ACFD 0xED93FA9B
+ 0xE8D3C48D 0x283B57CC 0xF8D56629 0x79132E28
+ 0x785F0191 0xED756055 0xF7960E44 0xE3D35E8C
+ 0x15056DD4 0x88F46DBA 0x03A16125 0x0564F0BD
+ 0xC3EB9E15 0x3C9057A2 0x97271AEC 0xA93A072A
+ 0x1B3F6D9B 0x1E6321F5 0xF59C66FB 0x26DCF319
+ 0x7533D928 0xB155FDF5 0x03563482 0x8ABA3CBB
+ 0x28517711 0xC20AD9F8 0xABCC5167 0xCCAD925F
+ 0x4DE81751 0x3830DC8E 0x379D5862 0x9320F991
+ 0xEA7A90C2 0xFB3E7BCE 0x5121CE64 0x774FBE32
+ 0xA8B6E37E 0xC3293D46 0x48DE5369 0x6413E680
+ 0xA2AE0810 0xDD6DB224 0x69852DFD 0x09072166
+ 0xB39A460A 0x6445C0DD 0x586CDECF 0x1C20C8AE
+ 0x5BBEF7DD 0x1B588D40 0xCCD2017F 0x6BB4E3BB
+ 0xDDA26A7E 0x3A59FF45 0x3E350A44 0xBCB4CDD5
+ 0x72EACEA8 0xFA6484BB 0x8D6612AE 0xBF3C6F47
+ 0xD29BE463 0x542F5D9E 0xAEC2771B 0xF64E6370
+ 0x740E0D8D 0xE75B1357 0xF8721671 0xAF537D5D
+ 0x4040CB08 0x4EB4E2CC 0x34D2466A 0x0115AF84
+ 0xE1B00428 0x95983A1D 0x06B89FB4 0xCE6EA048
+ 0x6F3F3B82 0x3520AB82 0x011A1D4B 0x277227F8
+ 0x611560B1 0xE7933FDC 0xBB3A792B 0x344525BD
+ 0xA08839E1 0x51CE794B 0x2F32C9B7 0xA01FBAC9
+ 0xE01CC87E 0xBCC7D1F6 0xCF0111C3 0xA1E8AAC7
+ 0x1A908749 0xD44FBD9A 0xD0DADECB 0xD50ADA38
+ 0x0339C32A 0xC6913667 0x8DF9317C 0xE0B12B4F
+ 0xF79E59B7 0x43F5BB3A 0xF2D519FF 0x27D9459C
+ 0xBF97222C 0x15E6FC2A 0x0F91FC71 0x9B941525
+ 0xFAE59361 0xCEB69CEB 0xC2A86459 0x12BAA8D1
+ 0xB6C1075E 0xE3056A0C 0x10D25065 0xCB03A442
+ 0xE0EC6E0E 0x1698DB3B 0x4C98A0BE 0x3278E964
+ 0x9F1F9532 0xE0D392DF 0xD3A0342B 0x8971F21E
+ 0x1B0A7441 0x4BA3348C 0xC5BE7120 0xC37632D8
+ 0xDF359F8D 0x9B992F2E 0xE60B6F47 0x0FE3F11D
+ 0xE54CDA54 0x1EDAD891 0xCE6279CF 0xCD3E7E6F
+ 0x1618B166 0xFD2C1D05 0x848FD2C5 0xF6FB2299
+ 0xF523F357 0xA6327623 0x93A83531 0x56CCCD02
+ 0xACF08162 0x5A75EBB5 0x6E163697 0x88D273CC
+ 0xDE966292 0x81B949D0 0x4C50901B 0x71C65614
+ 0xE6C6C7BD 0x327A140A 0x45E1D006 0xC3F27B9A
+ 0xC9AA53FD 0x62A80F00 0xBB25BFE2 0x35BDD2F6
+ 0x71126905 0xB2040222 0xB6CBCF7C 0xCD769C2B
+ 0x53113EC0 0x1640E3D3 0x38ABBD60 0x2547ADF0
+ 0xBA38209C 0xF746CE76 0x77AFA1C5 0x20756060
+ 0x85CBFE4E 0x8AE88DD8 0x7AAAF9B0 0x4CF9AA7E
+ 0x1948C25C 0x02FB8A8C 0x01C36AE4 0xD6EBE1F9
+ 0x90D4F869 0xA65CDEA0 0x3F09252D 0xC208E69F
+ 0xB74E6132 0xCE77E25B 0x578FDFE3 0x3AC372E6
+ }
+}
+
+proc ::blowfish::intEncrypt {P S xl xr} {
+ for {set i 0} {$i < 16} {incr i} {
+ set xl [expr {$xl ^ [lindex $P $i]}]
+
+ set S0a [lindex $S [expr { ($xl >> 24) & 0xff}]]
+ set S1b [lindex $S [expr {(($xl >> 16) & 0xff) + 256}]]
+ set S2c [lindex $S [expr {(($xl >> 8) & 0xff) + 512}]]
+ set S3d [lindex $S [expr { ($xl & 0xff) + 768}]]
+ set xr [expr {(((($S0a + $S1b) ^ $S2c) + $S3d) & 0xffffffff) ^ $xr}]
+
+ set temp $xl ; set xl $xr ; set xr $temp
+ }
+
+ set temp $xl ; set xl $xr ; set xr $temp
+ return [list [expr {$xl ^ [lindex $P 17]}] [expr {$xr ^ [lindex $P 16]}]]
+}
+
+proc ::blowfish::intDecrypt {P S xl xr} {
+ for {set i 17} {$i > 1} {incr i -1} {
+ set xl [expr {$xl ^ [lindex $P $i]}]
+
+ set S0a [lindex $S [expr { ($xl >> 24) & 0xff}]]
+ set S1b [lindex $S [expr {(($xl >> 16) & 0xff) + 256}]]
+ set S2c [lindex $S [expr {(($xl >> 8) & 0xff) + 512}]]
+ set S3d [lindex $S [expr { ($xl & 0xff) + 768}]]
+ set xr [expr {(((($S0a + $S1b) ^ $S2c) + $S3d) & 0xffffffff) ^ $xr}]
+
+ set temp $xl ; set xl $xr ; set xr $temp
+ }
+
+ set temp $xl ; set xl $xr ; set xr $temp
+ return [list [expr {$xl ^ [lindex $P 0]}] [expr {$xr ^ [lindex $P 1]}]]
+}
+
+proc ::blowfish::Init {mode key iv} {
+ variable ORIG_S
+ variable ORIG_P
+ variable uid
+
+ set S $ORIG_S
+ set P [list]
+
+ set kl [string length $key]
+ binary scan $key c* kc
+
+ set j 0
+ for {set i 0} {$i < 18} {incr i} {
+ set data 0
+ for {set k 0} {$k < 4} {incr k} {
+ set data [expr {(($data << 8) | ([lindex $kc $j] & 0xff)) & 0xffffffff}]
+ if {[incr j] >= $kl} {
+ set j 0
+ }
+ }
+ set OPi [lindex $ORIG_P $i]
+ lappend P [expr {$OPi ^ $data}]
+ }
+
+ set datal 0
+ set datar 0
+
+ for {set i 0} {$i < 18} {incr i} {
+ set ed [intEncrypt $P $S $datal $datar]
+ set datal [lindex $ed 0]
+ set datar [lindex $ed 1]
+ set P [lreplace $P $i [incr i] $datal $datar]
+ }
+
+ for {set i 0} {$i < 4} {incr i} {
+ for {set j 0} {$j < 256} {incr j 2} {
+ set ed [intEncrypt $P $S $datal $datar]
+ set datal [lindex $ed 0]
+ set datar [lindex $ed 1]
+ set t [expr {$i * 256 + $j}]
+ set S [lreplace $S $t [incr t] $datal $datar]
+ }
+ }
+
+ set token [namespace current]::[incr uid]
+ variable $token
+ upvar #0 $token state
+ array set state [list P $P S $S M $mode I $iv]
+ return $token
+}
+
+proc ::blowfish::Reset {token iv} {
+ upvar #0 $token state
+ set state(I) $iv
+ return
+}
+
+proc ::blowfish::Final {token} {
+ # PRAGMA: nocheck
+ variable $token
+ unset $token
+}
+
+proc ::blowfish::EncryptBlock {token block} {
+ upvar #0 $token state
+ if {[binary scan $block II xl xr] != 2} {
+ error "block must be 8 bytes"
+ }
+ set xl [expr {$xl & 0xffffffff}]
+ set xr [expr {$xr & 0xffffffff}]
+ set d [intEncrypt $state(P) $state(S) $xl $xr]
+ return [binary format I2 $d]
+}
+
+proc ::blowfish::Encrypt {Key data} {
+ upvar #0 $Key state
+ set P $state(P)
+ set S $state(S)
+ set cbc_mode [string equal "cbc" $state(M)]
+
+ if {[binary scan $state(I) II s0 s1] != 2} {
+ return -code error "invalid initialization vector: must be 8 bytes"
+ }
+
+ set len [string length $data]
+ if {($len % 8) != 0} {
+ return -code error "invalid block size: blocks must be 8 bytes"
+ }
+
+ set s0 [expr {$s0 & 0xffffffff}]
+ set s1 [expr {$s1 & 0xffffffff}]
+
+ set result ""
+ for {set i 0} {$i < $len} {incr i 8} {
+ if {[binary scan $data @[set i]II xl xr] != 2} {
+ return -code error "oops"
+ }
+ if {$cbc_mode} {
+ set xl [expr {($xl & 0xffffffff) ^ $s0}]
+ set xr [expr {($xr & 0xffffffff) ^ $s1}]
+ }
+ set d [intEncrypt $P $S $xl $xr]
+ if {$cbc_mode} {
+ set s0 [lindex $d 0]
+ set s1 [lindex $d 1]
+ }
+ append result [binary format I2 $d]
+ }
+ if {$cbc_mode} {
+ set state(I) [binary format II $s0 $s1]
+ }
+ return $result
+}
+
+proc ::blowfish::DecryptBlock {Key block} {
+ upvar #0 $Key state
+ if {[binary scan $block II xl xr] != 2} {
+ return -code error "invalid block size: block must be 8 bytes"
+ }
+ set xl [expr {$xl & 0xffffffff}]
+ set xr [expr {$xr & 0xffffffff}]
+ set d [intDecrypt $state(P) $state(S) $xl $xr]
+ return [binary format I2 $d]
+}
+
+proc ::blowfish::Decrypt {token data} {
+ upvar #0 $token state
+ set P $state(P)
+ set S $state(S)
+ set cbc_mode [string equal "cbc" $state(M)]
+
+ if {[binary scan $state(I) II s0 s1] != 2} {
+ return -code error "initialization vector must be 8 bytes"
+ }
+
+ set len [string length $data]
+ if {($len % 8) != 0} {
+ return -code error "block size invalid"
+ }
+
+ set s0 [expr {$s0 & 0xffffffff}]
+ set s1 [expr {$s1 & 0xffffffff}]
+
+ set result ""
+ for {set i 0} {$i < $len} {incr i 8} {
+ if {[binary scan $data @[set i]II xl xr] != 2} {
+ error "oops"
+ }
+ set xl [expr {$xl & 0xffffffff}]
+ set xr [expr {$xr & 0xffffffff}]
+ set d [intDecrypt $P $S $xl $xr]
+ if {$cbc_mode} {
+ set d0 [lindex $d 0]
+ set d1 [lindex $d 1]
+ set c0 [expr {$d0 ^ $s0}]
+ set c1 [expr {$d1 ^ $s1}]
+ set s0 $xl
+ set s1 $xr
+ append result [binary format II $c0 $c1]
+ } else {
+ append result [binary format I2 $d]
+ }
+ }
+ if {$cbc_mode} {
+ set state(I) [binary format II $s0 $s1]
+ }
+ return $result
+}
+
+
+# -------------------------------------------------------------------------
+# Fileevent handler for chunked file reading.
+#
+proc ::blowfish::Chunk {Key in {out {}} {chunksize 4096} {pad \0}} {
+ upvar #0 $Key state
+
+ if {[eof $in]} {
+ fileevent $in readable {}
+ set state(reading) 0
+ }
+
+ set data [read $in $chunksize]
+ # FIX ME: we should ony pad after eof
+ if {[string length $pad] > 0} {
+ set data [Pad $data 8]
+ }
+
+ if {$out == {}} {
+ append state(output) [$state(cmd) $Key $data]
+ } else {
+ puts -nonewline $out [$state(cmd) $Key $data]
+ }
+}
+
+# -------------------------------------------------------------------------
+
+# LoadAccelerator --
+#
+# This package can make use of a number of compiled extensions to
+# accelerate the digest computation. This procedure manages the
+# use of these extensions within the package. During normal usage
+# this should not be called, but the test package manipulates the
+# list of enabled accelerators.
+#
+proc ::blowfish::LoadAccelerator {name} {
+ variable accel
+ set r 0
+ switch -exact -- $name {
+ trf {
+ if {![catch {package require Trfcrypt}]} {
+ set block [string repeat \0 8]
+ set r [expr {![catch {::blowfish -dir enc -mode ecb -key $block $block} msg]}]
+ }
+ }
+ default {
+ return -code error "invalid accelerator package:\
+ must be one of [join [array names accel] {, }]"
+ }
+ }
+ set accel($name) $r
+}
+
+# -------------------------------------------------------------------------
+
+proc ::blowfish::Hex {data} {
+ binary scan $data H* r
+ return $r
+}
+
+proc ::blowfish::SetOneOf {lst item} {
+ set ndx [lsearch -glob $lst "${item}*"]
+ if {$ndx == -1} {
+ set err [join $lst ", "]
+ return -code error "invalid mode \"$item\": must be one of $err"
+ }
+ return [lindex $lst $ndx]
+}
+
+proc ::blowfish::CheckSize {what size thing} {
+ if {[string length $thing] != $size} {
+ return -code error "invalid value for $what: must be $size bytes long"
+ }
+ return $thing
+}
+
+proc ::blowfish::CheckPad {char} {
+ if {[string length $char] > 1} {
+ return -code error "invalid value: should be a char or empty string"
+ }
+ return $char
+}
+
+proc ::blowfish::Pad {data blocksize {fill \0}} {
+ set len [string length $data]
+ if {$len == 0} {
+ set data [string repeat $fill $blocksize]
+ } elseif {($len % $blocksize) != 0} {
+ set pad [expr {$blocksize - ($len % $blocksize)}]
+ append data [string repeat $fill $pad]
+ }
+ return $data
+}
+
+# Description:
+# Pop the nth element off a list. Used in options processing.
+#
+proc ::blowfish::Pop {varname {nth 0}} {
+ upvar $varname args
+ set r [lindex $args $nth]
+ set args [lreplace $args $nth $nth]
+ return $r
+}
+
+proc ::blowfish::blowfish {args} {
+ variable accel
+ array set opts {-dir encrypt -mode cbc -key {} -in {} -out {} -hex 0 -pad \0}
+ set opts(-chunksize) 4096
+ set opts(-iv) [string repeat \0 8]
+ set modes {ecb cbc}
+ set dirs {encrypt decrypt}
+ while {[string match -* [set option [lindex $args 0]]]} {
+ switch -exact -- $option {
+ -mode { set opts(-mode) [SetOneOf $modes [Pop args 1]] }
+ -dir { set opts(-dir) [SetOneOf $dirs [Pop args 1]] }
+ -iv { set opts(-iv) [CheckSize -iv 8 [Pop args 1]] }
+ -key { set opts(-key) [Pop args 1] }
+ -in { set opts(-in) [Pop args 1] }
+ -out { set opts(-out) [Pop args 1] }
+ -chunksize { set opts(-chunksize) [Pop args 1] }
+ -hex { set opts(-hex) 1 }
+ -pad { set opts(-pad) [CheckPad [Pop args 1]] }
+ -- { Pop args; break }
+ default {
+ if {[string length $opts(-in)] == 0 && [llength $args] == 1} break
+ set err [join [lsort [array names opts]] ", "]
+ return -code error "bad option \"$option\":\
+ must be one of $err"
+ }
+ }
+ Pop args
+ }
+
+ if {$opts(-key) == {}} {
+ return -code error "no key provided: the -key option is required"
+ }
+
+ set r {}
+ if {$opts(-in) == {}} {
+
+ if {[llength $args] != 1} {
+ return -code error "wrong \# args:\
+ should be \"blowfish ?options...? -key keydata plaintext\""
+ }
+
+ set data [lindex $args 0]
+ if {[string length $opts(-pad)] > 0} {
+ set data [Pad [lindex $args 0] 8 $opts(-pad)]
+ }
+ if {$accel(trf)} {
+ set r [::blowfish -dir $opts(-dir) -mode $opts(-mode) \
+ -key $opts(-key) -iv $opts(-iv) -- $data]
+ } else {
+ set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]
+ if {[string equal $opts(-dir) "encrypt"]} {
+ set r [Encrypt $Key $data]
+ } else {
+ set r [Decrypt $Key $data]
+ }
+ Final $Key
+ }
+
+ if {$opts(-out) != {}} {
+ puts -nonewline $opts(-out) $r
+ set r {}
+ }
+
+ } else {
+
+ if {[llength $args] != 0} {
+ return -code error "wrong \# args:\
+ should be \"blowfish ?options...? -key keydata -in channel\""
+ }
+
+ set Key [Init $opts(-mode) $opts(-key) $opts(-iv)]
+ upvar $Key state
+ set state(reading) 1
+ if {[string equal $opts(-dir) "encrypt"]} {
+ set state(cmd) Encrypt
+ } else {
+ set state(cmd) Decrypt
+ }
+ set state(output) ""
+ fileevent $opts(-in) readable \
+ [list [namespace origin Chunk] \
+ $Key $opts(-in) $opts(-out) $opts(-chunksize) $opts(-pad)]
+ if {[info commands ::tkwait] != {}} {
+ tkwait variable [subst $Key](reading)
+ } else {
+ vwait [subst $Key](reading)
+ }
+ if {$opts(-out) == {}} {
+ set r $state(output)
+ }
+ Final $Key
+
+ }
+
+ if {$opts(-hex)} {
+ set r [Hex $r]
+ }
+ return $r
+}
+
+# -------------------------------------------------------------------------
+
+# Try and load a compiled extension to help.
+namespace eval ::blowfish {
+ variable e {}
+ foreach e {trf} {
+ if {[LoadAccelerator $e]} break
+ }
+ unset e
+}
+
+package provide blowfish 1.0.4
+
+# -------------------------------------------------------------------------
+#
+# Local Variables:
+# mode: tcl
+# indent-tabs-mode: nil
+# End:
diff --git a/tcllib/modules/blowfish/blowfish.test b/tcllib/modules/blowfish/blowfish.test
new file mode 100644
index 0000000..a09e91d
--- /dev/null
+++ b/tcllib/modules/blowfish/blowfish.test
@@ -0,0 +1,315 @@
+# blowfish.test - Copyright (C) 2004 Pat Thoyts <patthoyts@users.sf.net>
+#
+# $Id: blowfish.test,v 1.11 2007/09/17 14:19:07 patthoyts Exp $
+
+# -------------------------------------------------------------------------
+
+source [file join \
+ [file dirname [file dirname [file join [pwd] [info script]]]] \
+ devtools testutilities.tcl]
+
+testsNeedTcl 8.2
+testsNeedTcltest 1.0
+
+testing {
+ useLocal blowfish.tcl blowfish
+}
+
+# -------------------------------------------------------------------------
+# Handle multiple implementation testing
+#
+array set preserve [array get ::blowfish::accel]
+
+proc implementations {} {
+ variable ::blowfish::accel
+ foreach {a v} [array get accel] {if {$v} {lappend r $a}}
+ lappend r tcl; set r
+}
+
+proc select_implementation {impl} {
+ variable ::blowfish::accel
+ foreach e [array names accel] { set accel($e) 0 }
+ if {[string compare "tcl" $impl] != 0} {
+ set accel($impl) 1
+ }
+}
+
+proc reset_implementation {} {
+ variable ::blowfish::accel
+ array set accel [array get ::preserve]
+}
+
+# -------------------------------------------------------------------------
+# Report versions
+#
+if {[::blowfish::LoadAccelerator trf]} {
+ puts "> Trf based"
+}
+puts "> pure Tcl"
+
+# -------------------------------------------------------------------------
+# Now the package specific tests....
+# -------------------------------------------------------------------------
+
+# -------------------------------------------------------------------------
+
+#test blowfish-1.0 {blowfish basic command options} {
+# list [catch {::blowfish::blowfish} msg] \
+# [string match "wrong # args*" $msg]
+#
+#} {1 1}
+
+# -------------------------------------------------------------------------
+
+# Test vectors from http://www.schneier.com/code/vectors.txt
+
+set vectors {
+ 0000000000000000 0000000000000000 4EF997456198DD78
+ FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF 51866FD5B85ECB8A
+ 3000000000000000 1000000000000001 7D856F9A613063F2
+ 1111111111111111 1111111111111111 2466DD878B963C9D
+ 0123456789ABCDEF 1111111111111111 61F9C3802281B096
+ 1111111111111111 0123456789ABCDEF 7D0CC630AFDA1EC7
+ 0000000000000000 0000000000000000 4EF997456198DD78
+ FEDCBA9876543210 0123456789ABCDEF 0ACEAB0FC6A0A28D
+ 7CA110454A1A6E57 01A1D6D039776742 59C68245EB05282B
+ 0131D9619DC1376E 5CD54CA83DEF57DA B1B8CC0B250F09A0
+ 07A1133E4A0B2686 0248D43806F67172 1730E5778BEA1DA4
+ 3849674C2602319E 51454B582DDF440A A25E7856CF2651EB
+ 04B915BA43FEB5B6 42FD443059577FA2 353882B109CE8F1A
+ 0113B970FD34F2CE 059B5E0851CF143A 48F4D0884C379918
+ 0170F175468FB5E6 0756D8E0774761D2 432193B78951FC98
+ 43297FAD38E373FE 762514B829BF486A 13F04154D69D1AE5
+ 07A7137045DA2A16 3BDD119049372802 2EEDDA93FFD39C79
+ 04689104C2FD3B2F 26955F6835AF609A D887E0393C2DA6E3
+ 37D06BB516CB7546 164D5E404F275232 5F99D04F5B163969
+ 1F08260D1AC2465E 6B056E18759F5CCA 4A057A3B24D3977B
+ 584023641ABA6176 004BD6EF09176062 452031C1E4FADA8E
+ 025816164629B007 480D39006EE762F2 7555AE39F59B87BD
+ 49793EBC79B3258F 437540C8698F3CFA 53C55F9CB49FC019
+ 4FB05E1515AB73A7 072D43A077075292 7A8E7BFA937E89A3
+ 49E95D6D4CA229BF 02FE55778117F12A CF9C5D7A4986ADB5
+ 018310DC409B26D6 1D9D5C5018F728C2 D1ABB290658BC778
+ 1C587F1C13924FEF 305532286D6F295A 55CB3774D13EF201
+ 0101010101010101 0123456789ABCDEF FA34EC4847B268B2
+ 1F1F1F1F0E0E0E0E 0123456789ABCDEF A790795108EA3CAE
+ E0FEE0FEF1FEF1FE 0123456789ABCDEF C39E072D9FAC631D
+ 0000000000000000 FFFFFFFFFFFFFFFF 014933E0CDAFF6E4
+ FFFFFFFFFFFFFFFF 0000000000000000 F21E9A77B71C49BC
+ 0123456789ABCDEF 0000000000000000 245946885754369A
+ FEDCBA9876543210 FFFFFFFFFFFFFFFF 6B5C5A9C5D9E0A5A
+}
+
+set n 0
+foreach impl [implementations] {
+ select_implementation $impl
+ foreach {key plain cipher} $vectors {
+ test blowfish-$impl-2.$n "blowfish ecb test vector $n (impl $impl)" {
+ list [catch {
+ string toupper \
+ [::blowfish::Hex \
+ [::blowfish::blowfish -mode ecb -dir enc \
+ -key [binary format H* $key] \
+ [binary format H* $plain]]]
+ } msg] $msg
+ } [list 0 $cipher]
+ incr n
+ }
+ reset_implementation
+}
+
+set vectors {
+ F9AD597C49DB005E F0
+ E91D21C1D961A6D6 F0E1
+ E9C2B70A1BC65CF3 F0E1D2
+ BE1E639408640F05 F0E1D2C3
+ B39E44481BDB1E6E F0E1D2C3B4
+ 9457AA83B1928C0D F0E1D2C3B4A5
+ 8BB77032F960629D F0E1D2C3B4A596
+ E87A244E2CC85E82 F0E1D2C3B4A59687
+ 15750E7A4F4EC577 F0E1D2C3B4A5968778
+ 122BA70B3AB64AE0 F0E1D2C3B4A596877869
+ 3A833C9AFFC537F6 F0E1D2C3B4A5968778695A
+ 9409DA87A90F6BF2 F0E1D2C3B4A5968778695A4B
+ 884F80625060B8B4 F0E1D2C3B4A5968778695A4B3C
+ 1F85031C19E11968 F0E1D2C3B4A5968778695A4B3C2D
+ 79D9373A714CA34F F0E1D2C3B4A5968778695A4B3C2D1E
+ 93142887EE3BE15C F0E1D2C3B4A5968778695A4B3C2D1E0F
+ 03429E838CE2D14B F0E1D2C3B4A5968778695A4B3C2D1E0F00
+ A4299E27469FF67B F0E1D2C3B4A5968778695A4B3C2D1E0F0011
+ AFD5AED1C1BC96A8 F0E1D2C3B4A5968778695A4B3C2D1E0F001122
+ 10851C0E3858DA9F F0E1D2C3B4A5968778695A4B3C2D1E0F00112233
+ E6F51ED79B9DB21F F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344
+ 64A6E14AFD36B46F F0E1D2C3B4A5968778695A4B3C2D1E0F001122334455
+ 80C7D7D45A5479AD F0E1D2C3B4A5968778695A4B3C2D1E0F00112233445566
+ 05044B62FA52D080 F0E1D2C3B4A5968778695A4B3C2D1E0F0011223344556677
+}
+
+set plain [binary format H* FEDCBA9876543210]
+foreach impl [implementations] {
+ select_implementation $impl
+ set n 0
+ foreach {cipher key} $vectors {
+ test blowfish-$impl-4.$n "blowfish ecb test variable length key (impl $impl)" {
+ list [catch {
+ string toupper \
+ [::blowfish::Hex \
+ [::blowfish::blowfish \
+ -mode ecb \
+ -dir enc \
+ -key [binary format H* $key] \
+ $plain]]
+ } msg] $msg
+ } [list 0 $cipher]
+ incr n
+ }
+ reset_implementation
+}
+
+set key [binary format H* 0123456789ABCDEFF0E1D2C3B4A59687]
+set iv [binary format H* FEDCBA9876543210]
+set plain [binary format H* \
+ 37363534333231204E6F77206973207468652074696D6520666F722000000000]
+
+foreach impl [implementations] {
+ select_implementation $impl
+ test blowfish-$impl-6.1 "blowfish cbc mode (impl $impl)" {
+ list [catch {
+ string toupper \
+ [::blowfish::Hex \
+ [::blowfish::blowfish \
+ -dir enc \
+ -mode cbc \
+ -iv $iv \
+ -key $key \
+ $plain]]
+ } msg] $msg
+ } [list 0 \
+ 6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC]
+ reset_implementation
+}
+
+#cfb E73214A2822139CAF26ECF6D2EB9E76E3DA3DE04D1517200519D57A6C3
+#ofb E73214A2822139CA62B343CC5B65587310DD908D0C241B2263C2CF80DA
+
+foreach impl [implementations] {
+ select_implementation $impl
+
+ test blowfish-$impl-7.1 {test reset of initialization vector on cbc mode} {
+ list [catch {
+ set iv [string repeat \x00 8]
+ set pt "01234567abcdefgh01234567"
+ set tok [blowfish::Init cbc secret $iv]
+ set ct1 [blowfish::Encrypt $tok $pt]
+ blowfish::Reset $tok $iv
+ set ct2 [blowfish::Encrypt $tok $pt]
+ blowfish::Final $tok
+ string equal $ct1 $ct2
+ } msg] $msg
+ } {0 1}
+
+ test blowfish-$impl-7.2 {test reset of initialization vector on cbc mode} {
+ list [catch {
+ set pt "01234567abcdefgh01234567"
+ set tok [blowfish::Init cbc secret [string repeat \x00 8]]
+ set ct1 [blowfish::Encrypt $tok $pt]
+ blowfish::Reset $tok [string repeat \x01 8]
+ set ct2 [blowfish::Encrypt $tok $pt]
+ blowfish::Final $tok
+ string equal $ct1 $ct2
+ } msg] $msg
+ } {0 0}
+
+ test blowfish-$impl-8.0 {check hyphen in crypt data} {
+ list [catch {
+ set key "uP/AD/oGb6q/"
+ set text "ececho cleardata"
+ set cipher [blowfish::blowfish -mode ecb -key $key -dir encrypt $text]
+ set plain [blowfish::blowfish -mode ecb -key $key -dir decrypt $cipher]
+ string compare $plain $text
+ } msg] $msg
+ } {0 0}
+
+ test blowfish-$impl-8.1 {check hyphen in plaintext} {
+ list [catch {
+ set key "uP/AD/oGb6q/"
+ set text "-cecho cleardata"
+ set cipher [blowfish::blowfish -mode ecb -key $key -dir encrypt $text]
+ set plain [blowfish::blowfish -mode ecb -key $key -dir decrypt $cipher]
+ string compare $plain $text
+ } msg] $msg
+ } {0 0}
+
+ test blowfish-$impl-8.2 {check hyphen in key} {
+ list [catch {
+ set key "-P/AD/oGb6q/"
+ set text "ececho cleardata"
+ set cipher [blowfish::blowfish -mode ecb -key $key -dir encrypt $text]
+ set plain [blowfish::blowfish -mode ecb -key $key -dir decrypt $cipher]
+ string compare $plain $text
+ } msg] $msg
+ } {0 0}
+
+ test blowfish-$impl-8.3 {check option termination} {
+ list [catch {
+ set key "uP/AD/oGb6q/"
+ set text "ececho cleardata"
+ set cipher [blowfish::blowfish -mode ecb -key $key -dir encrypt -- $text]
+ set plain [blowfish::blowfish -mode ecb -key $key -dir decrypt -- $cipher]
+ string compare $plain $text
+ } msg] $msg
+ } {0 0}
+
+ test blowfish-$impl-9.0 {check -pad option} {
+ list [catch {
+ set key "uP/AD/oGb6q/"
+ set text "01234"
+ set cipher [blowfish::blowfish -mode ecb -hex -key $key \
+ -dir encrypt -pad a -- $text]
+ } msg] $msg
+ } {0 8927243c2d7d568c}
+
+ test blowfish-$impl-9.1 {check -pad option} {
+ list [catch {
+ set key "uP/AD/oGb6q/"
+ set text "01234"
+ set cipher [blowfish::blowfish -mode ecb -hex -key $key \
+ -dir encrypt -pad { } -- $text]
+ } msg] $msg
+ } {0 3fc711286b8eca79}
+
+ test blowfish-$impl-9.2 {check -pad option} {
+ list [catch {
+ set key "uP/AD/oGb6q/"
+ set text "01234"
+ set cipher [blowfish::blowfish -mode ecb -hex -key $key \
+ -dir encrypt -pad "" -- $text]
+ } msg] \
+ [expr {
+ [string equal $msg \
+ {invalid block size: blocks must be 8 bytes}] \
+ || [string equal $msg \
+ {can not encrypt incomplete block at end of input}]}]
+ } {1 1}
+
+ test blowfish-$impl-9.3 {check -dir option default is encrypt} {
+ list [catch {
+ set key "04B915BA43FEB5B6"
+ set text "42FD443059577FA2"
+ set cipher [blowfish::blowfish -mode ecb -pad "" -hex\
+ -key [binary format H* $key]\
+ -- [binary format H* $text]]
+ } msg] $msg
+ } {0 353882b109ce8f1a}
+
+ reset_implementation
+}
+
+# -------------------------------------------------------------------------
+
+testsuiteCleanup
+
+# Local variables:
+# mode: tcl
+# indent-tabs-mode: nil
+# End:
diff --git a/tcllib/modules/blowfish/pkgIndex.tcl b/tcllib/modules/blowfish/pkgIndex.tcl
new file mode 100644
index 0000000..d9db123
--- /dev/null
+++ b/tcllib/modules/blowfish/pkgIndex.tcl
@@ -0,0 +1,5 @@
+if {![package vsatisfies [package provide Tcl] 8.2]} {
+ # PRAGMA: returnok
+ return
+}
+package ifneeded blowfish 1.0.4 [list source [file join $dir blowfish.tcl]]