block-tea 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
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