crypt-tea 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,11 @@
1
+ === 1.1.0 / 2009-04-06
2
+
3
+ * BUGFIX
4
+
5
+ * ensure extra characters on the end of decrypted strings are removed
6
+ * Thanks to James Zhang for reporting this
7
+
8
+
1
9
  === 1.0.0 / 2008-04-02
2
10
 
3
11
  * 1 major enhancement
@@ -1,8 +1,23 @@
1
1
  module Crypt
2
2
  class XXTEA
3
- VERSION = '1.0.0'
3
+ VERSION = '1.1.0'
4
4
  DELTA = 0x9E3779B9
5
5
 
6
+ def initialize(new_key)
7
+ @key = str_to_longs(new_key)
8
+
9
+ if @key.length > 4
10
+ raise 'Key is too long (no more than 16 chars)'
11
+
12
+ elsif @key.length == 0
13
+ raise 'Key cannot be empty'
14
+
15
+ elsif @key.length < 4
16
+ @key.length.upto(4) { |i| @key[i] = 0 }
17
+
18
+ end
19
+ end
20
+
6
21
  def self.str_to_longs(s, include_count = false)
7
22
  length = s.length
8
23
  ((4 - s.length % 4) & 3).times { s << "\0" } # Pad to a multiple of 4
@@ -11,76 +26,70 @@ module Crypt
11
26
  unpacked
12
27
  end
13
28
 
14
- def self.longs_to_str(l, unpad = false) # convert array of longs back to string
29
+ def str_to_longs(s, include_count = false)
30
+ self.class.str_to_longs s, include_count
31
+ end
32
+
33
+
34
+ ##
35
+ # convert array of longs back to string
36
+ def self.longs_to_str(l, count_included = false)
15
37
  s = l.pack('V*')
16
- s = s.gsub(/[\000-\037]/,'') if unpad
38
+ s = s[0...(l[-1])] if count_included
17
39
  s
18
40
  end
19
41
 
42
+ def longs_to_str(l, count_included = false)
43
+ self.class.longs_to_str l, count_included
44
+ end
45
+
20
46
 
21
47
  def self.int32(n)
22
- n -= 4294967296 while (n >= 2147483648)
23
- n += 4294967296 while (n <= -2147483649)
48
+ n -= 4_294_967_296 while (n >= 2_147_483_648)
49
+ n += 4_294_967_296 while (n <= -2_147_483_648)
24
50
  n.to_i
25
51
  end
26
52
 
53
+ def int32(n)
54
+ self.class.int32 n
55
+ end
27
56
 
28
- def initialize(new_key)
29
- @key = self.class.str_to_longs(new_key, false)
30
-
31
- if @key.length > 4
32
- raise 'Key is too long (no more than 16 chars)'
33
-
34
- elsif @key.length == 0
35
- raise 'Key cannot be empty'
36
-
37
- elsif @key.length < 4
38
- @key.length.upto(4) { |i| @key[i] = 0 }
39
-
40
- end
57
+ def mx(z, y, sum, p, e)
58
+ int32(
59
+ ((z >> 5 & 0x07FFFFFF) ^ (y << 2)) +
60
+ ((y >> 3 & 0x1FFFFFFF) ^ (z << 4))
61
+ ) ^ int32((sum ^ y) + (@key[(p & 3) ^ e] ^ z))
41
62
  end
42
63
 
43
64
  def encrypt(plaintext)
44
65
  return '' if plaintext.length == 0
45
66
 
46
- v = self.class.str_to_longs(plaintext, true)
67
+ v = str_to_longs(plaintext, true)
47
68
  v[1] = 0 if v.length == 1
48
69
 
49
70
  n = v.length - 1
50
71
 
51
72
  z = v[n]
52
73
  y = v[0]
53
- q = (6 + 52/ (n + 1)).floor
74
+ q = (6 + 52 / (n + 1)).floor
54
75
  sum = 0
55
76
  p = 0
56
77
 
57
78
  while(0 <= (q -= 1)) do
58
- sum = self.class.int32(sum + DELTA)
79
+ sum = int32(sum + DELTA)
59
80
  e = sum >> 2 & 3
60
81
 
61
- (0...n).each do |p|
82
+ n.times do |p|
62
83
  y = v[p + 1];
63
- mx =
64
- self.class.int32(
65
- ((z >> 5 & 0x07FFFFFF) ^ y << 2) +
66
- ((y >> 3 & 0x1FFFFFFF) ^ z << 4)
67
- ) ^ self.class.int32((sum ^ y) + (@key[p & 3 ^ e] ^ z))
68
-
69
- z = v[p] = self.class.int32(v[p] + mx)
84
+ z = v[p] = int32(v[p] + mx(z, y, sum, p, e))
70
85
  end
71
86
 
72
87
  p += 1
73
88
  y = v[0];
74
- mx =
75
- self.class.int32(
76
- ((z >> 5 & 0x07FFFFFF) ^ y << 2) +
77
- ((y >> 3 & 0x1FFFFFFF) ^ z << 4)
78
- ) ^ self.class.int32((sum ^ y) + (@key[p & 3 ^ e] ^ z))
79
-
80
- z = v[p] = self.class.int32(v[p] + mx)
89
+ z = v[p] = int32(v[p] + mx(z, y, sum, p, e))
81
90
  end
82
91
 
83
- self.class.longs_to_str(v).unpack('a*').pack('m').delete("\n") # base64 encode it without newlines
92
+ longs_to_str(v).unpack('a*').pack('m').delete("\n") # base64 encode it without newlines
84
93
  end
85
94
 
86
95
  #
@@ -89,40 +98,28 @@ module Crypt
89
98
  def decrypt(ciphertext)
90
99
  return '' if ciphertext.length == 0
91
100
 
92
- v = self.class.str_to_longs(ciphertext.unpack('m').pack("a*")) # base64 decode and convert to array of 'longs'
101
+ v = str_to_longs(ciphertext.unpack('m').pack("a*")) # base64 decode and convert to array of 'longs'
93
102
  n = v.length - 1
94
103
  z = v[n]
95
104
  y = v[0]
96
105
  q = (6 + 52 / (n + 1)).floor
97
- sum = self.class.int32(q * DELTA)
106
+ sum = int32(q * DELTA)
98
107
  p = 0
99
108
 
100
109
  while (sum != 0) do
101
110
  e = sum >> 2 & 3
102
111
  n.downto(1) do |p|
103
112
  z = v[p - 1]
104
- mx =
105
- self.class.int32(
106
- ((z >> 5 & 0x07FFFFFF) ^ y << 2) +
107
- ((y >> 3 & 0x1FFFFFFF) ^ z << 4)
108
- ) ^ self.class.int32((sum ^ y) + (@key[p & 3 ^ e] ^ z))
109
-
110
- y = v[p] = self.class.int32(v[p] - mx)
113
+ y = v[p] = int32(v[p] - mx(z, y, sum, p, e))
111
114
  end
112
115
 
113
116
  p -= 1
114
117
  z = v[n]
115
- mx =
116
- self.class.int32(
117
- ((z >> 5 & 0x07FFFFFF) ^ y << 2) +
118
- ((y >> 3 & 0x1FFFFFFF) ^ z << 4)
119
- ) ^ self.class.int32((sum ^ y) + (@key[p & 3 ^ e] ^ z))
120
-
121
- y = v[0] = self.class.int32(v[0] - mx)
122
- sum = self.class.int32(sum - DELTA)
118
+ y = v[0] = int32(v[0] - mx(z, y, sum, p, e))
119
+ sum = int32(sum - DELTA)
123
120
  end
124
121
 
125
- self.class.longs_to_str(v, true)
122
+ longs_to_str(v, true)
126
123
  end
127
124
 
128
125
  end
@@ -5,15 +5,17 @@ require 'crypt_tea'
5
5
 
6
6
  class XXTEATest < Test::Unit::TestCase
7
7
  def setup
8
- @key = Crypt::XXTEA.new 'testkey'
8
+ @key = Crypt::XXTEA.new 'abigfattestkey'
9
+ @plaintext = "Oh say can you see, by the dawn's early light"
10
+ @cyphertext = "V32cYZc5yLXepm9lxzr4kgGM/eSVurwV0yQWi4uFs0uB2UBlJ19ZRKKMkbMr7DLGc3n1XQ=="
9
11
  end
10
12
 
11
13
  def test_str_to_long
12
- assert_equal [1953719668, 6778473], Crypt::XXTEA.str_to_longs('testing')
14
+ assert_equal [1953719668, 6778473, 7], Crypt::XXTEA.str_to_longs('testing', true)
13
15
  end
14
16
 
15
17
  def test_longs_to_str
16
- assert_equal 'testing', Crypt::XXTEA.longs_to_str([1953719668, 6778473], true)
18
+ assert_equal 'testing', Crypt::XXTEA.longs_to_str([1953719668, 6778473, 7], true)
17
19
  end
18
20
 
19
21
  def test_key_length
@@ -22,10 +24,19 @@ class XXTEATest < Test::Unit::TestCase
22
24
  end
23
25
 
24
26
  def test_encrypt
25
- assert_equal 'qYkeGc3ignEvPGM7RS06iQ==', @key.encrypt('plaintext')
27
+ assert_equal @cyphertext, @key.encrypt(@plaintext)
26
28
  end
27
29
 
28
30
  def test_decrypt
29
- assert_equal 'plaintext', @key.decrypt('qYkeGc3ignEvPGM7RS06iQ==')
31
+ assert_equal @plaintext, @key.decrypt(@cyphertext)
32
+ end
33
+
34
+ def test_tiny_plaintext
35
+ assert_equal '1', @key.decrypt(@key.encrypt('1'))
36
+ end
37
+
38
+ def test_huge_plaintext
39
+ str = '1234567890' * 1_000
40
+ assert_equal str, @key.decrypt(@key.encrypt(str))
30
41
  end
31
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crypt-tea
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Smick
@@ -30,17 +30,18 @@ cert_chain:
30
30
  M6zkPH2hkWs=
31
31
  -----END CERTIFICATE-----
32
32
 
33
- date: 2008-04-14 00:00:00 -07:00
33
+ date: 2009-04-06 00:00:00 -07:00
34
34
  default_executable:
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: hoe
38
+ type: :development
38
39
  version_requirement:
39
40
  version_requirements: !ruby/object:Gem::Requirement
40
41
  requirements:
41
42
  - - ">="
42
43
  - !ruby/object:Gem::Version
43
- version: 1.5.1
44
+ version: 1.11.0
44
45
  version:
45
46
  description: An implementation of the Tiny Encryption Algorithm that's compatible with PHP's xxTEA
46
47
  email:
@@ -85,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
85
86
  requirements: []
86
87
 
87
88
  rubyforge_project: crypt-tea
88
- rubygems_version: 1.1.1
89
+ rubygems_version: 1.3.1
89
90
  signing_key:
90
91
  specification_version: 2
91
92
  summary: An implementation of the Tiny Encryption Algorithm that's compatible with PHP's xxTEA
metadata.gz.sig CHANGED
Binary file