bicrypt 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +205 -674
- data/README.rdoc +19 -7
- data/lib/bicrypt.rb +182 -164
- data/meta/package +8 -1
- data/meta/profile +21 -0
- data/qed/01_example.rb +57 -0
- data/qed/applique/setup.rb +10 -0
- metadata +59 -29
- data/MANIFEST +0 -18
- data/meta/authors +0 -1
- data/meta/created +0 -1
- data/meta/description +0 -1
- data/meta/homepage +0 -1
- data/meta/license +0 -1
- data/meta/released +0 -1
- data/meta/repository +0 -1
- data/meta/summary +0 -1
- data/meta/version +0 -1
    
        data/README.rdoc
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            = BiCrypt
         | 
| 2 2 |  | 
| 3 | 
            -
             | 
| 3 | 
            +
            * docs: http://rubydoc.info/gems/bicrypt
         | 
| 4 | 
            +
            * code: http://rubyworks.github.com/bicrypt
         | 
| 4 5 |  | 
| 5 6 |  | 
| 6 7 | 
             
            == DESCRIPTION
         | 
| @@ -10,17 +11,18 @@ BiCrypt is a simple two-way encryption class. | |
| 10 11 |  | 
| 11 12 | 
             
            == FEATURES/ISSUES
         | 
| 12 13 |  | 
| 13 | 
            -
            *  | 
| 14 | 
            +
            * Simple to use.
         | 
| 15 | 
            +
            * Good for light-weight "deterence" applications.
         | 
| 14 16 |  | 
| 15 17 |  | 
| 16 18 | 
             
            == RELEASE NOTES
         | 
| 17 19 |  | 
| 18 | 
            -
            Please see  | 
| 20 | 
            +
            Please see HISTORY.rdoc file.
         | 
| 19 21 |  | 
| 20 22 |  | 
| 21 | 
            -
            ==  | 
| 23 | 
            +
            == USAGE
         | 
| 22 24 |  | 
| 23 | 
            -
             | 
| 25 | 
            +
            See QED example[qed/01_example] document.
         | 
| 24 26 |  | 
| 25 27 |  | 
| 26 28 | 
             
            == HOW TO INSTALL
         | 
| @@ -43,9 +45,19 @@ Windows users use 'ruby setup.rb all'. | |
| 43 45 |  | 
| 44 46 | 
             
            == COPYING
         | 
| 45 47 |  | 
| 46 | 
            -
            Copyright (c) 2007  | 
| 48 | 
            +
            Copyright (c) 2007 Thomas Sawyer
         | 
| 47 49 |  | 
| 48 | 
            -
             | 
| 50 | 
            +
            Licensed under the Apache License, Version 2.0 (the "License");
         | 
| 51 | 
            +
            you may not use this file except in compliance with the License.
         | 
| 52 | 
            +
            You may obtain a copy of the License at
         | 
| 53 | 
            +
             | 
| 54 | 
            +
              http://www.apache.org/licenses/LICENSE-2.0
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            Unless required by applicable law or agreed to in writing, software
         | 
| 57 | 
            +
            distributed under the License is distributed on an "AS IS" BASIS,
         | 
| 58 | 
            +
            WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 59 | 
            +
            See the License for the specific language governing permissions and
         | 
| 60 | 
            +
            limitations under the License.
         | 
| 49 61 |  | 
| 50 62 | 
             
            See LICENSE file for details.
         | 
| 51 63 |  | 
    
        data/lib/bicrypt.rb
    CHANGED
    
    | @@ -1,23 +1,18 @@ | |
| 1 | 
            -
            #  | 
| 2 | 
            -
            #
         | 
| 3 | 
            -
            # A simple two-way encryption class.
         | 
| 4 | 
            -
            #
         | 
| 5 | 
            -
            # == Authors
         | 
| 6 | 
            -
            #
         | 
| 7 | 
            -
            # * Trans
         | 
| 8 | 
            -
            #
         | 
| 9 | 
            -
            # == Copying
         | 
| 1 | 
            +
            # BiCrypt - A Simple Two-Way Encryption Class
         | 
| 10 2 | 
             
            #
         | 
| 11 3 | 
             
            # Copyright (c) 2007 Trans
         | 
| 12 4 | 
             
            #
         | 
| 13 | 
            -
            #  | 
| 5 | 
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         | 
| 6 | 
            +
            # you may not use this file except in compliance with the License.
         | 
| 7 | 
            +
            # You may obtain a copy of the License at
         | 
| 14 8 | 
             
            #
         | 
| 15 | 
            -
            # | 
| 16 | 
            -
            # software under the same terms as Ruby.
         | 
| 9 | 
            +
            #   http://www.apache.org/licenses/LICENSE-2.0
         | 
| 17 10 | 
             
            #
         | 
| 18 | 
            -
            #  | 
| 19 | 
            -
            #  | 
| 20 | 
            -
            #  | 
| 11 | 
            +
            # Unless required by applicable law or agreed to in writing, software
         | 
| 12 | 
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         | 
| 13 | 
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 14 | 
            +
            # See the License for the specific language governing permissions and
         | 
| 15 | 
            +
            # limitations under the License.
         | 
| 21 16 |  | 
| 22 17 | 
             
            require 'stringio'
         | 
| 23 18 |  | 
| @@ -25,145 +20,64 @@ require 'stringio' | |
| 25 20 | 
             
            #
         | 
| 26 21 | 
             
            # A simple two-way encryption class.
         | 
| 27 22 | 
             
            #
         | 
| 23 | 
            +
            # This class is based on algorithms given in Applied Cryptography 2nd Ed.
         | 
| 24 | 
            +
            #
         | 
| 25 | 
            +
            # If subclassed, the new encryption class must provide three methods:
         | 
| 26 | 
            +
            #
         | 
| 27 | 
            +
            # * encrypt_block(block)
         | 
| 28 | 
            +
            # * decrypt_block(block)
         | 
| 29 | 
            +
            # * block_size()
         | 
| 30 | 
            +
            #
         | 
| 28 31 | 
             
            class BiCrypt
         | 
| 29 32 |  | 
| 30 33 | 
             
              ULONG   = 0x100000000
         | 
| 31 34 |  | 
| 32 | 
            -
               | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            +
              # These are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
         | 
| 36 | 
            +
              SBOX = [
         | 
| 37 | 
            +
                [4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
         | 
| 38 | 
            +
                [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
         | 
| 39 | 
            +
                [5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
         | 
| 40 | 
            +
                [7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
         | 
| 41 | 
            +
                [6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
         | 
| 42 | 
            +
                [4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
         | 
| 43 | 
            +
                [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
         | 
| 44 | 
            +
                [1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
         | 
| 45 | 
            +
              ]
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              # These are the S-boxes given in the GOST source code listing in Applied
         | 
| 48 | 
            +
              # Cryptography 2nd Ed., p. 644.  They appear to be from the DES S-boxes
         | 
| 49 | 
            +
              # [13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7 ],
         | 
| 50 | 
            +
              # [ 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1 ],
         | 
| 51 | 
            +
              # [12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11 ],
         | 
| 52 | 
            +
              # [ 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9 ],
         | 
| 53 | 
            +
              # [ 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15 ],
         | 
| 54 | 
            +
              # [10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8 ],
         | 
| 55 | 
            +
              # [15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10 ],
         | 
| 56 | 
            +
              # [14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7 ]
         | 
| 35 57 |  | 
| 58 | 
            +
              #
         | 
| 36 59 | 
             
              def initialize(userKey)
         | 
| 60 | 
            +
                @sBox = SBOX
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                if userKey.size < 8
         | 
| 63 | 
            +
                  userKey += '01234567'
         | 
| 64 | 
            +
                end
         | 
| 37 65 |  | 
| 38 | 
            -
                 | 
| 39 | 
            -
                @sBox = [
         | 
| 40 | 
            -
                  [4, 10, 9, 2, 13, 8, 0, 14, 6, 11, 1, 12, 7, 15, 5, 3],
         | 
| 41 | 
            -
                  [14, 11, 4, 12, 6, 13, 15, 10, 2, 3, 8, 1, 0, 7, 5, 9],
         | 
| 42 | 
            -
                  [5, 8, 1, 13, 10, 3, 4, 2, 14, 15, 12, 7, 6, 0, 9, 11],
         | 
| 43 | 
            -
                  [7, 13, 10, 1, 0, 8, 9, 15, 14, 4, 6, 12, 11, 2, 5, 3],
         | 
| 44 | 
            -
                  [6, 12, 7, 1, 5, 15, 13, 8, 4, 10, 9, 14, 0, 3, 11, 2],
         | 
| 45 | 
            -
                  [4, 11, 10, 0, 7, 2, 1, 13, 3, 6, 8, 5, 9, 12, 15, 14],
         | 
| 46 | 
            -
                  [13, 11, 4, 1, 3, 15, 5, 9, 0, 10, 14, 7, 6, 8, 2, 12],
         | 
| 47 | 
            -
                  [1, 15, 13, 0, 5, 7, 10, 4, 9, 2, 3, 14, 6, 11, 8, 12]
         | 
| 48 | 
            -
                ]
         | 
| 49 | 
            -
             | 
| 50 | 
            -
                # These are the S-boxes given in the GOST source code listing in Applied
         | 
| 51 | 
            -
                # Cryptography 2nd Ed., p. 644.  They appear to be from the DES S-boxes
         | 
| 52 | 
            -
                # [13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7 ],
         | 
| 53 | 
            -
                # [ 4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1 ],
         | 
| 54 | 
            -
                # [12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11 ],
         | 
| 55 | 
            -
                # [ 2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9 ],
         | 
| 56 | 
            -
                # [ 7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15 ],
         | 
| 57 | 
            -
                # [10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8 ],
         | 
| 58 | 
            -
                # [15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10 ],
         | 
| 59 | 
            -
                # [14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7 ]
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                # precalculate the S table
         | 
| 62 | 
            -
                @sTable = precalculate_S_table()
         | 
| 66 | 
            +
                #@sTable = precalculate_s_table()
         | 
| 63 67 |  | 
| 64 68 | 
             
                # derive the 32-byte key from the user-supplied key
         | 
| 65 69 | 
             
                userKeyLength = userKey.length
         | 
| 70 | 
            +
             | 
| 66 71 | 
             
                @key = userKey[0..31].unpack('C'*32)
         | 
| 72 | 
            +
             | 
| 67 73 | 
             
                if (userKeyLength < 32)
         | 
| 68 74 | 
             
                  userKeyLength.upto(31) { @key << 0 }
         | 
| 69 75 | 
             
                end
         | 
| 70 76 | 
             
              end
         | 
| 71 77 |  | 
| 78 | 
            +
              public
         | 
| 72 79 |  | 
| 73 | 
            -
               | 
| 74 | 
            -
                sTable = [[], [], [], []]
         | 
| 75 | 
            -
                0.upto(3) { |i|
         | 
| 76 | 
            -
                  0.upto(255) { |j|
         | 
| 77 | 
            -
                    t = @sBox[2*i][j % 16] | (@sBox[2*i+1][j/16] << 4)
         | 
| 78 | 
            -
                    u = (8*i + 11) % 32
         | 
| 79 | 
            -
                    v = (t << u) | (t >> (32-u))
         | 
| 80 | 
            -
                    sTable[i][j] = (v % ULONG)
         | 
| 81 | 
            -
                  }
         | 
| 82 | 
            -
                }
         | 
| 83 | 
            -
                return(sTable)
         | 
| 84 | 
            -
              end
         | 
| 85 | 
            -
             | 
| 86 | 
            -
             | 
| 87 | 
            -
              def f(longWord)
         | 
| 88 | 
            -
                longWord = longWord % ULONG
         | 
| 89 | 
            -
                a, b, c, d = [longWord].pack('L').unpack('CCCC')
         | 
| 90 | 
            -
                return(@sTable[3][d] ^ @sTable[2][c] ^ @sTable[1][b] ^ @sTable[0][a])
         | 
| 91 | 
            -
              end
         | 
| 92 | 
            -
             | 
| 93 | 
            -
              def encrypt_pair(xl, xr)
         | 
| 94 | 
            -
                3.times {
         | 
| 95 | 
            -
                  xr ^= f(xl+@key[0])
         | 
| 96 | 
            -
                  xl ^= f(xr+@key[1])
         | 
| 97 | 
            -
                  xr ^= f(xl+@key[2])
         | 
| 98 | 
            -
                  xl ^= f(xr+@key[3])
         | 
| 99 | 
            -
                  xr ^= f(xl+@key[4])
         | 
| 100 | 
            -
                  xl ^= f(xr+@key[5])
         | 
| 101 | 
            -
                  xr ^= f(xl+@key[6])
         | 
| 102 | 
            -
                  xl ^= f(xr+@key[7])
         | 
| 103 | 
            -
                }
         | 
| 104 | 
            -
                xr ^= f(xl+@key[7])
         | 
| 105 | 
            -
                xl ^= f(xr+@key[6])
         | 
| 106 | 
            -
                xr ^= f(xl+@key[5])
         | 
| 107 | 
            -
                xl ^= f(xr+@key[4])
         | 
| 108 | 
            -
                xr ^= f(xl+@key[3])
         | 
| 109 | 
            -
                xl ^= f(xr+@key[2])
         | 
| 110 | 
            -
                xr ^= f(xl+@key[1])
         | 
| 111 | 
            -
                xl ^= f(xr+@key[0])
         | 
| 112 | 
            -
                return([xr, xl])
         | 
| 113 | 
            -
              end
         | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
              def decrypt_pair(xl, xr)
         | 
| 117 | 
            -
                xr ^= f(xl+@key[0])
         | 
| 118 | 
            -
                xl ^= f(xr+@key[1])
         | 
| 119 | 
            -
                xr ^= f(xl+@key[2])
         | 
| 120 | 
            -
                xl ^= f(xr+@key[3])
         | 
| 121 | 
            -
                xr ^= f(xl+@key[4])
         | 
| 122 | 
            -
                xl ^= f(xr+@key[5])
         | 
| 123 | 
            -
                xr ^= f(xl+@key[6])
         | 
| 124 | 
            -
                xl ^= f(xr+@key[7])
         | 
| 125 | 
            -
                3.times {
         | 
| 126 | 
            -
                  xr ^= f(xl+@key[7])
         | 
| 127 | 
            -
                  xl ^= f(xr+@key[6])
         | 
| 128 | 
            -
                  xr ^= f(xl+@key[5])
         | 
| 129 | 
            -
                  xl ^= f(xr+@key[4])
         | 
| 130 | 
            -
                  xr ^= f(xl+@key[3])
         | 
| 131 | 
            -
                  xl ^= f(xr+@key[2])
         | 
| 132 | 
            -
                  xr ^= f(xl+@key[1])
         | 
| 133 | 
            -
                  xl ^= f(xr+@key[0])
         | 
| 134 | 
            -
                }
         | 
| 135 | 
            -
                return([xr, xl])
         | 
| 136 | 
            -
              end
         | 
| 137 | 
            -
             | 
| 138 | 
            -
              def encrypt_block(block)
         | 
| 139 | 
            -
                xl, xr = block.unpack('NN')
         | 
| 140 | 
            -
                xl, xr = encrypt_pair(xl, xr)
         | 
| 141 | 
            -
                encrypted = [xl, xr].pack('NN')
         | 
| 142 | 
            -
                return(encrypted)
         | 
| 143 | 
            -
              end
         | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
              def decrypt_block(block)
         | 
| 147 | 
            -
                xl, xr = block.unpack('NN')
         | 
| 148 | 
            -
                xl, xr = decrypt_pair(xl, xr)
         | 
| 149 | 
            -
                decrypted = [xl, xr].pack('NN')
         | 
| 150 | 
            -
                return(decrypted)
         | 
| 151 | 
            -
              end
         | 
| 152 | 
            -
             | 
| 153 | 
            -
              # When this module is mixed in with an encryption class, the class
         | 
| 154 | 
            -
              # must provide three methods: encrypt_block(block) and decrypt_block(block)
         | 
| 155 | 
            -
              # and block_size()
         | 
| 156 | 
            -
             | 
| 157 | 
            -
              def generate_initialization_vector(words)
         | 
| 158 | 
            -
                srand(Time.now.to_i)
         | 
| 159 | 
            -
                vector = ""
         | 
| 160 | 
            -
                words.times {
         | 
| 161 | 
            -
                  vector << [rand(ULONG)].pack('N')
         | 
| 162 | 
            -
                }
         | 
| 163 | 
            -
                return(vector)
         | 
| 164 | 
            -
              end
         | 
| 165 | 
            -
             | 
| 166 | 
            -
             | 
| 80 | 
            +
              # Encrypt an IO stream.
         | 
| 167 81 | 
             
              def encrypt_stream(plainStream, cryptStream)
         | 
| 168 82 | 
             
                # Cypher-block-chain mode
         | 
| 169 83 |  | 
| @@ -172,7 +86,7 @@ class BiCrypt | |
| 172 86 | 
             
                cryptStream.write(chain)
         | 
| 173 87 |  | 
| 174 88 | 
             
                while ((block = plainStream.read(block_size())) && (block.length == block_size()))
         | 
| 175 | 
            -
                  block = block  | 
| 89 | 
            +
                  block = xor(block, chain)
         | 
| 176 90 | 
             
                  encrypted = encrypt_block(block)
         | 
| 177 91 | 
             
                  cryptStream.write(encrypted)
         | 
| 178 92 | 
             
                  chain = encrypted
         | 
| @@ -189,19 +103,19 @@ class BiCrypt | |
| 189 103 | 
             
                remainingMessageBytes.upto(block_size()-2) { buffer << rand(128).chr }
         | 
| 190 104 | 
             
                buffer << remainingMessageBytes.chr
         | 
| 191 105 | 
             
                block = buffer.join('')
         | 
| 192 | 
            -
                block = block  | 
| 106 | 
            +
                block = xor(block, chain)
         | 
| 193 107 | 
             
                encrypted = encrypt_block(block)
         | 
| 194 108 | 
             
                cryptStream.write(encrypted)
         | 
| 195 109 | 
             
              end
         | 
| 196 110 |  | 
| 197 | 
            -
             | 
| 111 | 
            +
              # Decrypt an encrypted IO stream.
         | 
| 198 112 | 
             
              def decrypt_stream(cryptStream, plainStream)
         | 
| 199 113 | 
             
                # Cypher-block-chain mode
         | 
| 200 114 | 
             
                chain = cryptStream.read(block_size())
         | 
| 201 115 |  | 
| 202 116 | 
             
                while (block = cryptStream.read(block_size()))
         | 
| 203 117 | 
             
                  decrypted = decrypt_block(block)
         | 
| 204 | 
            -
                  plainText = decrypted  | 
| 118 | 
            +
                  plainText = xor(decrypted, chain)
         | 
| 205 119 | 
             
                  plainStream.write(plainText) unless cryptStream.eof?
         | 
| 206 120 | 
             
                  chain = block
         | 
| 207 121 | 
             
                end
         | 
| @@ -212,19 +126,7 @@ class BiCrypt | |
| 212 126 | 
             
                remainingMessageBytes.times { plainStream.write(buffer.shift) }
         | 
| 213 127 | 
             
              end
         | 
| 214 128 |  | 
| 215 | 
            -
             | 
| 216 | 
            -
              def carefully_open_file(filename, mode)
         | 
| 217 | 
            -
                begin
         | 
| 218 | 
            -
                  aFile = File.new(filename, mode)
         | 
| 219 | 
            -
                rescue
         | 
| 220 | 
            -
                  puts "Sorry. There was a problem opening the file <#{filename}>."
         | 
| 221 | 
            -
                  aFile.close() unless aFile.nil?
         | 
| 222 | 
            -
                  raise
         | 
| 223 | 
            -
                end
         | 
| 224 | 
            -
                return(aFile)
         | 
| 225 | 
            -
              end
         | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 129 | 
            +
              # Encrypt a file.
         | 
| 228 130 | 
             
              def encrypt_file(plainFilename, cryptFilename)
         | 
| 229 131 | 
             
                plainFile = carefully_open_file(plainFilename, 'rb')
         | 
| 230 132 | 
             
                cryptFile = carefully_open_file(cryptFilename, 'wb+')
         | 
| @@ -233,7 +135,7 @@ class BiCrypt | |
| 233 135 | 
             
                cryptFile.close unless cryptFile.closed?
         | 
| 234 136 | 
             
              end
         | 
| 235 137 |  | 
| 236 | 
            -
             | 
| 138 | 
            +
              # Decrypt an encrypted file.
         | 
| 237 139 | 
             
              def decrypt_file(cryptFilename, plainFilename)
         | 
| 238 140 | 
             
                cryptFile = carefully_open_file(cryptFilename, 'rb')
         | 
| 239 141 | 
             
                plainFile = carefully_open_file(plainFilename, 'wb+')
         | 
| @@ -242,7 +144,7 @@ class BiCrypt | |
| 242 144 | 
             
                plainFile.close unless plainFile.closed?
         | 
| 243 145 | 
             
              end
         | 
| 244 146 |  | 
| 245 | 
            -
             | 
| 147 | 
            +
              # Encrypt a string.
         | 
| 246 148 | 
             
              def encrypt_string(plainText)
         | 
| 247 149 | 
             
                plainStream = StringIO.new(plainText)
         | 
| 248 150 | 
             
                cryptStream = StringIO.new('')
         | 
| @@ -251,7 +153,7 @@ class BiCrypt | |
| 251 153 | 
             
                return(cryptText)
         | 
| 252 154 | 
             
              end
         | 
| 253 155 |  | 
| 254 | 
            -
             | 
| 156 | 
            +
              # Decrypt an encrypted string.
         | 
| 255 157 | 
             
              def decrypt_string(cryptText)
         | 
| 256 158 | 
             
                cryptStream = StringIO.new(cryptText)
         | 
| 257 159 | 
             
                plainStream = StringIO.new('')
         | 
| @@ -260,10 +162,122 @@ class BiCrypt | |
| 260 162 | 
             
                return(plainText)
         | 
| 261 163 | 
             
              end
         | 
| 262 164 |  | 
| 263 | 
            -
             | 
| 165 | 
            +
              private
         | 
| 166 | 
            +
             | 
| 167 | 
            +
              # S-boxes.
         | 
| 168 | 
            +
              attr :sBox
         | 
| 169 | 
            +
             | 
| 170 | 
            +
              # Calculated S-boxes
         | 
| 171 | 
            +
              def sTable
         | 
| 172 | 
            +
                @sTable ||= (
         | 
| 173 | 
            +
                  sTable = [[], [], [], []]
         | 
| 174 | 
            +
                  0.upto(3) { |i|
         | 
| 175 | 
            +
                    0.upto(255) { |j|
         | 
| 176 | 
            +
                      t = sBox[2*i][j % 16] | (sBox[2*i+1][j/16] << 4)
         | 
| 177 | 
            +
                      u = (8*i + 11) % 32
         | 
| 178 | 
            +
                      v = (t << u) | (t >> (32-u))
         | 
| 179 | 
            +
                      sTable[i][j] = (v % ULONG)
         | 
| 180 | 
            +
                    }
         | 
| 181 | 
            +
                  }
         | 
| 182 | 
            +
                  sTable
         | 
| 183 | 
            +
                )
         | 
| 184 | 
            +
              end
         | 
| 264 185 |  | 
| 186 | 
            +
              #
         | 
| 187 | 
            +
              def encrypt_block(block)
         | 
| 188 | 
            +
                xl, xr = block.unpack('NN')
         | 
| 189 | 
            +
                xl, xr = encrypt_pair(xl, xr)
         | 
| 190 | 
            +
                encrypted = [xl, xr].pack('NN')
         | 
| 191 | 
            +
                return(encrypted)
         | 
| 192 | 
            +
              end
         | 
| 265 193 |  | 
| 266 | 
            -
             | 
| 194 | 
            +
              #
         | 
| 195 | 
            +
              def decrypt_block(block)
         | 
| 196 | 
            +
                xl, xr = block.unpack('NN')
         | 
| 197 | 
            +
                xl, xr = decrypt_pair(xl, xr)
         | 
| 198 | 
            +
                decrypted = [xl, xr].pack('NN')
         | 
| 199 | 
            +
                return(decrypted)
         | 
| 200 | 
            +
              end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
              #
         | 
| 203 | 
            +
              def block_size
         | 
| 204 | 
            +
                8
         | 
| 205 | 
            +
              end
         | 
| 206 | 
            +
             | 
| 207 | 
            +
              #
         | 
| 208 | 
            +
              def encrypt_pair(xl, xr)
         | 
| 209 | 
            +
                3.times {
         | 
| 210 | 
            +
                  xr ^= f(xl+@key[0])
         | 
| 211 | 
            +
                  xl ^= f(xr+@key[1])
         | 
| 212 | 
            +
                  xr ^= f(xl+@key[2])
         | 
| 213 | 
            +
                  xl ^= f(xr+@key[3])
         | 
| 214 | 
            +
                  xr ^= f(xl+@key[4])
         | 
| 215 | 
            +
                  xl ^= f(xr+@key[5])
         | 
| 216 | 
            +
                  xr ^= f(xl+@key[6])
         | 
| 217 | 
            +
                  xl ^= f(xr+@key[7])
         | 
| 218 | 
            +
                }
         | 
| 219 | 
            +
                xr ^= f(xl+@key[7])
         | 
| 220 | 
            +
                xl ^= f(xr+@key[6])
         | 
| 221 | 
            +
                xr ^= f(xl+@key[5])
         | 
| 222 | 
            +
                xl ^= f(xr+@key[4])
         | 
| 223 | 
            +
                xr ^= f(xl+@key[3])
         | 
| 224 | 
            +
                xl ^= f(xr+@key[2])
         | 
| 225 | 
            +
                xr ^= f(xl+@key[1])
         | 
| 226 | 
            +
                xl ^= f(xr+@key[0])
         | 
| 227 | 
            +
                return([xr, xl])
         | 
| 228 | 
            +
              end
         | 
| 229 | 
            +
             | 
| 230 | 
            +
              #
         | 
| 231 | 
            +
              def decrypt_pair(xl, xr)
         | 
| 232 | 
            +
                xr ^= f(xl+@key[0])
         | 
| 233 | 
            +
                xl ^= f(xr+@key[1])
         | 
| 234 | 
            +
                xr ^= f(xl+@key[2])
         | 
| 235 | 
            +
                xl ^= f(xr+@key[3])
         | 
| 236 | 
            +
                xr ^= f(xl+@key[4])
         | 
| 237 | 
            +
                xl ^= f(xr+@key[5])
         | 
| 238 | 
            +
                xr ^= f(xl+@key[6])
         | 
| 239 | 
            +
                xl ^= f(xr+@key[7])
         | 
| 240 | 
            +
                3.times {
         | 
| 241 | 
            +
                  xr ^= f(xl+@key[7])
         | 
| 242 | 
            +
                  xl ^= f(xr+@key[6])
         | 
| 243 | 
            +
                  xr ^= f(xl+@key[5])
         | 
| 244 | 
            +
                  xl ^= f(xr+@key[4])
         | 
| 245 | 
            +
                  xr ^= f(xl+@key[3])
         | 
| 246 | 
            +
                  xl ^= f(xr+@key[2])
         | 
| 247 | 
            +
                  xr ^= f(xl+@key[1])
         | 
| 248 | 
            +
                  xl ^= f(xr+@key[0])
         | 
| 249 | 
            +
                }
         | 
| 250 | 
            +
                return([xr, xl])
         | 
| 251 | 
            +
              end
         | 
| 252 | 
            +
             | 
| 253 | 
            +
              #
         | 
| 254 | 
            +
              def f(longWord)
         | 
| 255 | 
            +
                longWord = longWord % ULONG
         | 
| 256 | 
            +
                a, b, c, d = [longWord].pack('L').unpack('CCCC')
         | 
| 257 | 
            +
                return(sTable[3][d] ^ sTable[2][c] ^ sTable[1][b] ^ sTable[0][a])
         | 
| 258 | 
            +
              end
         | 
| 259 | 
            +
             | 
| 260 | 
            +
              #
         | 
| 261 | 
            +
              def generate_initialization_vector(words)
         | 
| 262 | 
            +
                srand(Time.now.to_i)
         | 
| 263 | 
            +
                vector = ""
         | 
| 264 | 
            +
                words.times {
         | 
| 265 | 
            +
                  vector << [rand(ULONG)].pack('N')
         | 
| 266 | 
            +
                }
         | 
| 267 | 
            +
                return(vector)
         | 
| 268 | 
            +
              end
         | 
| 269 | 
            +
             | 
| 270 | 
            +
              #
         | 
| 271 | 
            +
              def carefully_open_file(filename, mode)
         | 
| 272 | 
            +
                begin
         | 
| 273 | 
            +
                  aFile = File.new(filename, mode)
         | 
| 274 | 
            +
                rescue
         | 
| 275 | 
            +
                  puts "Sorry. There was a problem opening the file <#{filename}>."
         | 
| 276 | 
            +
                  aFile.close() unless aFile.nil?
         | 
| 277 | 
            +
                  raise
         | 
| 278 | 
            +
                end
         | 
| 279 | 
            +
                return(aFile)
         | 
| 280 | 
            +
              end
         | 
| 267 281 |  | 
| 268 282 | 
             
              # Binary XOR of two strings. 
         | 
| 269 283 | 
             
              #
         | 
| @@ -275,17 +289,21 @@ class String | |
| 275 289 | 
             
              #   "\000\001\001\000"
         | 
| 276 290 | 
             
              #   "\003\002\001"
         | 
| 277 291 | 
             
              #
         | 
| 278 | 
            -
               | 
| 279 | 
            -
             | 
| 280 | 
            -
             | 
| 292 | 
            +
              #--
         | 
| 293 | 
            +
              # NOTE: This used to be a String#^ extension in v1.0. So if
         | 
| 294 | 
            +
              # an uncaught bug should arise check this first.
         | 
| 295 | 
            +
              #++
         | 
| 296 | 
            +
              def xor(str1, str2)
         | 
| 297 | 
            +
                a = str1.unpack('C'*(str1.length)) #.bytes.to_a
         | 
| 298 | 
            +
                b = str2.unpack('C'*(str2.length)) #.bytes.to_a
         | 
| 281 299 | 
             
                if (b.length < a.length)
         | 
| 282 300 | 
             
                  (a.length - b.length).times { b << 0 }
         | 
| 283 301 | 
             
                end
         | 
| 284 302 | 
             
                xor = ""
         | 
| 285 | 
            -
                0.upto(a.length-1)  | 
| 303 | 
            +
                0.upto(a.length - 1) do |pos|
         | 
| 286 304 | 
             
                  x = a[pos] ^ b[pos]
         | 
| 287 305 | 
             
                  xor << x.chr()
         | 
| 288 | 
            -
                 | 
| 306 | 
            +
                end
         | 
| 289 307 | 
             
                return(xor)
         | 
| 290 308 | 
             
              end
         | 
| 291 309 |  |