block-tea 1.3.1

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/README.rdoc ADDED
@@ -0,0 +1,45 @@
1
+ = Crypt::BlockTEA
2
+
3
+ This is a fork of * http://crypt-tea.rubyforge.org/
4
+
5
+ == DESCRIPTION:
6
+
7
+ An implementation of the Tiny Encryption Algorithm that's compatible with PHP's xxTEA
8
+
9
+
10
+ == USAGE:
11
+
12
+ k = Crypt::BlockTEA.new("e43f3fd0bd91bef1")
13
+ puts a = k.encrypt('Hello from the Moon')
14
+ puts k.decrypt('eEBikks7C1IlSCYA0cECdrdKSLA=')
15
+
16
+
17
+ == TODO:
18
+
19
+ Bi-directional interface to interact with JavaScript (http://www.movable-type.co.uk/scripts/tea-block.html)
20
+ Tests
21
+
22
+ == LICENSE:
23
+
24
+ (The MIT License)
25
+
26
+ Copyright (c) 2011 Mikhailov Anatoly
27
+
28
+ Permission is hereby granted, free of charge, to any person obtaining
29
+ a copy of this software and associated documentation files (the
30
+ 'Software'), to deal in the Software without restriction, including
31
+ without limitation the rights to use, copy, modify, merge, publish,
32
+ distribute, sublicense, and/or sell copies of the Software, and to
33
+ permit persons to whom the Software is furnished to do so, subject to
34
+ the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be
37
+ included in all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
40
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
42
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
43
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
44
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
45
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/bin/block_tea ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ unless (ARGV.length == 3) && (command = ARGV[0][/^enc/] ? :encrypt : (ARGV[0][/^dec/] ? :decrypt : nil))
4
+ puts ' Usage:'
5
+ puts " block_tea <command> <key> <plaintext/cyphertext>"
6
+ puts
7
+ puts " Commands:"
8
+ puts " enc, encrypt"
9
+ puts " dec, decrypt"
10
+ puts
11
+ else
12
+ require 'rubygems'
13
+ require 'block_tea'
14
+
15
+ k = Crypt::BlockTEA.new(ARGV[1].dup)
16
+ puts k.send(command, ARGV[2].dup)
17
+ end
data/lib/crypt.rb ADDED
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), *%w[crypt block_tea])
@@ -0,0 +1,113 @@
1
+ module Crypt
2
+ class BlockTEA
3
+ DELTA = 0x9E3779B9
4
+
5
+ def initialize(password)
6
+ @password = password
7
+ end
8
+
9
+
10
+ # encrypt: Use Corrected Block TEA to encrypt plaintext using password
11
+ # Return encrypted text as string
12
+ def encrypt(plaintext)
13
+ if plaintext.length == 0
14
+ return('') # nothing to encrypt
15
+ end
16
+
17
+ # 'escape' plaintext so chars outside ISO-8859-1 work in single-byte packing, but
18
+ # keep spaces as spaces (not '%20') so encrypted text doesn't grow too long, and
19
+ # convert result to longs
20
+ # v = str_to_longs(escape(plaintext).gsub(/%20/,' '))
21
+ v = str_to_longs(plaintext)
22
+
23
+ if v.length == 1
24
+ v[1] = 0 # algorithm doesn't work for n<2 so fudge by adding nulls
25
+ end
26
+
27
+ k = str_to_longs(@password.ljust(16).slice(0,16)) # simply convert first 16 chars of password as key
28
+ n = v.length
29
+
30
+ z = v[n-1]
31
+ y = v[0]
32
+ sum = 0
33
+
34
+ (6 + 52.0/n).floor.downto(1) { |q| # 6 + 52/n operations gives between 6 & 32 mixes on each word
35
+ sum = (sum + DELTA) & 0xffffffff
36
+ e = sum>>2 & 3
37
+ for p in (0...n-1)
38
+ y = v[p+1]
39
+ v[p] = (v[p] + mx(z, y, sum, k[p&3 ^ e])) & 0xffffffff
40
+ z = v[p]
41
+ end
42
+ y = v[0]
43
+ v[n-1] = (v[n-1] + mx(z, y, sum, k[(n-1)&3 ^ e])) & 0xffffffff
44
+ z = v[n-1]
45
+ }
46
+
47
+ ciphertext = longs_to_str(v)
48
+ return ciphertext.unpack('a*').pack('m').delete("\n") # base64 encode it without newlines
49
+ end
50
+
51
+
52
+ # decrypt: Use Corrected Block TEA to decrypt ciphertext using password
53
+ def decrypt(ciphertext)
54
+ if ciphertext.length == 0
55
+ return('')
56
+ end
57
+
58
+ v = str_to_longs(ciphertext.unpack('m').pack("a*")) # base64 decode and convert to array of 'longs'
59
+ k = str_to_longs(@password.ljust(16).slice(0,16))
60
+ n = v.length
61
+
62
+ z = v[n-1]
63
+ y = v[0]
64
+ q = (6 + 52.0/n).floor
65
+ sum = q*DELTA
66
+
67
+ while (sum > 0)
68
+ e = sum>>2 & 3
69
+ (n-1).downto(1) { |p|
70
+ z = v[p-1]
71
+ v[p] = (v[p] - mx(z, y, sum, k[p&3 ^ e])) & 0xffffffff
72
+ y = v[p]
73
+ }
74
+
75
+ z = v[n-1]
76
+ v[0] = (v[0] - mx(z, y, sum, k[0 ^ e])) & 0xffffffff
77
+ y = v[0]
78
+ sum -= DELTA
79
+ end
80
+
81
+ plaintext = longs_to_str(v)
82
+ # strip trailing null chars resulting from filling 4-char blocks:
83
+ plaintext = plaintext.gsub(/\0+$/,'')
84
+ return plaintext
85
+ end
86
+
87
+
88
+ private
89
+
90
+
91
+ def mx(z, y, sum, p)
92
+ ((z>>5 ^ ((y<<2)&0xffffffff)) + (y>>3 ^ ((z<<4)&0xffffffff)) ^ (sum^y) + (p ^ z)) & 0xffffffff
93
+ end
94
+
95
+ def self.str_to_longs(s, include_count = false)
96
+ s << [0,0,0].pack('c*') # Pad with at most three nulls
97
+ return s.unpack('L*')
98
+ end
99
+
100
+ def str_to_longs(s, include_count = false) # :nodoc:
101
+ self.class.str_to_longs s, include_count
102
+ end
103
+
104
+ def self.longs_to_str(l, include_count = false) # convert array of longs back to string
105
+ l.pack('L*')
106
+ end
107
+
108
+ def longs_to_str(l, include_count = false) # :nodoc:
109
+ self.class.longs_to_str l, include_count
110
+ end
111
+
112
+ end
113
+ end
data/test/benchmark.rb ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'benchmark'
3
+ require File.join(File.dirname(__FILE__), *%w[.. lib crypt])
4
+
5
+ KEY = Crypt::BlockTEA.new 'abigfattestkey'
6
+ STRINGS = {}
7
+
8
+ CHARS = [('a'..'z'),('A'..'Z'),('0'..'9')].map{|i| i.to_a}.flatten
9
+ def rand_string(size)
10
+ (0...size).map { CHARS[rand(CHARS.length)] }.join
11
+ end
12
+
13
+ Benchmark.bm do |x|
14
+ [1, 10, 100, 1_000, 10_000, 100_000].each do |size|
15
+ STRINGS[size] = rand_string(size)
16
+ x.report(size.to_s.rjust(6)) { KEY.decrypt(KEY.encrypt(STRINGS[size])) }
17
+ end
18
+ end
19
+
20
+ __END__
21
+
22
+ Ruby 1.8.6
23
+ user system total real
24
+ 1 0.000000 0.000000 0.000000 ( 0.002733)
25
+ 10 0.000000 0.000000 0.000000 ( 0.003002)
26
+ 100 0.010000 0.010000 0.020000 ( 0.007730)
27
+ 1000 0.070000 0.000000 0.070000 ( 0.077805)
28
+ 10000 0.720000 0.010000 0.730000 ( 0.738411)
29
+ 100000 7.780000 0.040000 7.820000 ( 7.932519)
30
+
31
+ Ruby 1.9.1p129
32
+ user system total real
33
+ 1 0.010000 0.000000 0.010000 ( 0.013437)
34
+ 10 0.000000 0.000000 0.000000 ( 0.001345)
35
+ 100 0.000000 0.000000 0.000000 ( 0.003279)
36
+ 1000 0.040000 0.000000 0.040000 ( 0.040562)
37
+ 10000 0.390000 0.010000 0.400000 ( 0.402591)
38
+ 100000 3.170000 0.020000 3.190000 ( 3.243170)
39
+
40
+ jRuby 1.2.0
41
+ user system total real
42
+ 1 0.026000 0.000000 0.026000 ( 0.026000)
43
+ 10 0.018000 0.000000 0.018000 ( 0.018000)
44
+ 100 0.040000 0.000000 0.040000 ( 0.040000)
45
+ 1000 0.220000 0.000000 0.220000 ( 0.220000)
46
+ 10000 0.682000 0.000000 0.682000 ( 0.682000)
47
+ 100000 1.281000 0.000000 1.281000 ( 1.281000)
48
+
49
+ jRuby 1.3.0RC2
50
+ user system total real
51
+ 1 0.026000 0.000000 0.026000 ( 0.025000)
52
+ 10 0.020000 0.000000 0.020000 ( 0.020000)
53
+ 100 0.040000 0.000000 0.040000 ( 0.041000)
54
+ 1000 0.255000 0.000000 0.255000 ( 0.254000)
55
+ 10000 0.499000 0.000000 0.499000 ( 0.500000)
56
+ 100000 1.805000 0.000000 1.805000 ( 1.806000)
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'minitest/spec'
3
+ require File.join(File.dirname(__FILE__), *%w[.. lib crypt])
4
+
5
+ MiniTest::Unit.autorun
6
+
7
+ describe Crypt::BlockTEA do
8
+ # before do
9
+ # @key_text = 'abigfattestkey'
10
+ # @key = Crypt::BlockTEA.new @key_text
11
+ # @plaintext = "Oh say can you see, by the dawn's early light"
12
+ # @cyphertext = "V32cYZc5yLXepm9lxzr4kgGM/eSVurwV0yQWi4uFs0uB2UBlJ19ZRKKMkbMr7DLGc3n1XQ=="
13
+ # end
14
+ #
15
+ # it 'converts strings to longs' do
16
+ # Crypt::BlockTEA.str_to_longs('testing', true).must_equal [1953719668, 6778473, 7]
17
+ # end
18
+ #
19
+ # it 'converts longs to strings' do
20
+ # Crypt::BlockTEA.longs_to_str([1953719668, 6778473, 7], true).must_equal 'testing'
21
+ # end
22
+ #
23
+ # it 'raises an error when the key is too long' do
24
+ # proc { Crypt::BlockTEA.new '12345678901234567' }.must_raise RuntimeError
25
+ # end
26
+ #
27
+ # it 'raises an error when the key is blank' do
28
+ # proc { Crypt::BlockTEA.new '' }.must_raise RuntimeError
29
+ # end
30
+ #
31
+ # it 'works properly with small keys' do
32
+ # key = Crypt::BlockTEA.new '123'
33
+ # cyphertext = key.encrypt(@plaintext)
34
+ # key.decrypt(cyphertext).must_equal @plaintext
35
+ # end
36
+ #
37
+ # it 'properly encrypts when instantiated' do
38
+ # @key.encrypt(@plaintext).must_equal @cyphertext
39
+ # end
40
+ #
41
+ # it 'properly decrypts when instantiated' do
42
+ # @key.decrypt(@cyphertext).must_equal @plaintext
43
+ # end
44
+ #
45
+ # it 'properly en/decrypts tiny text' do
46
+ # txt = '1'
47
+ # @key.decrypt(@key.encrypt(txt)).must_equal txt
48
+ # end
49
+ #
50
+ # it 'properly en/decrypts huge text' do
51
+ # str = '1234567890' * 1_000
52
+ # @key.decrypt(@key.encrypt(str)).must_equal str
53
+ # end
54
+ #
55
+ # it 'properly encrypts with a class method' do
56
+ # Crypt::BlockTEA.encrypt(@key_text, @plaintext).must_equal @cyphertext
57
+ # end
58
+ #
59
+ # it 'properly decrypts with a class method' do
60
+ # Crypt::BlockTEA.decrypt(@key_text, @cyphertext).must_equal @plaintext
61
+ # end
62
+ end
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: block-tea
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 3
9
+ - 1
10
+ version: 1.3.1
11
+ platform: ruby
12
+ authors:
13
+ - Mikhailov Anatoly
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-09 00:00:00 +06:00
19
+ default_executable: block_tea
20
+ dependencies: []
21
+
22
+ description: A fork of an implementation of the Tiny Encryption Algorithm that's compatible with PHP's xxTEA
23
+ email: mikhailov.anatoly@gmail.com
24
+ executables:
25
+ - block_tea
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.rdoc
30
+ files:
31
+ - bin/block_tea
32
+ - lib/crypt.rb
33
+ - lib/crypt/block_tea.rb
34
+ - README.rdoc
35
+ - test/benchmark.rb
36
+ - test/test_block_tea.rb
37
+ has_rdoc: true
38
+ homepage: ""
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ hash: 3
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ requirements: []
65
+
66
+ rubyforge_project: ""
67
+ rubygems_version: 1.4.2
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: xxTEA implemented in pure ruby
71
+ test_files:
72
+ - test/benchmark.rb
73
+ - test/test_block_tea.rb