gost_magma 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,44 @@
1
+ module GostMagma
2
+ class MagmaCbc < Magma
3
+ def initialize(key, iv)
4
+ @key = key.dup.force_encoding('BINARY')
5
+ @keys = []
6
+ (0...8).each do |i|
7
+ @keys << self.class.uint8ToUint32(@key[i*4...(i+1)*4].reverse)
8
+ end
9
+
10
+ @ctxR = iv.dup.force_encoding('BINARY')
11
+ end
12
+
13
+ def encrypt(data)
14
+ data_len = data.length
15
+ outdata = ''
16
+ (0...(data_len / BlockLengthInBytes)).each do |i|
17
+ encr_block = data[(i * BlockLengthInBytes)...((i+1) * BlockLengthInBytes)]
18
+ (0...BlockLengthInBytes).each do |j|
19
+ encr_block[j] = (@ctxR[j].ord ^ data[i * BlockLengthInBytes + j].ord).chr
20
+ end
21
+ encr_block = self.class.encryptBlock(encr_block, @keys)
22
+ outdata += encr_block
23
+ @ctxR = @ctxR[BlockLengthInBytes..-1] + encr_block
24
+ end
25
+ outdata
26
+ end
27
+
28
+ def decrypt(data)
29
+ data_len = data.length
30
+ outdata = ''
31
+ (0...(data_len / BlockLengthInBytes)).each do |i|
32
+ encr_block = data[(i * BlockLengthInBytes)...((i+1) * BlockLengthInBytes)]
33
+ decr_block = self.class.decryptBlock(encr_block, @keys)
34
+ (0...BlockLengthInBytes).each do |j|
35
+ decr_block[j] = (@ctxR[j].ord ^ decr_block[j].ord).chr
36
+ end
37
+ outdata += decr_block
38
+ @ctxR = @ctxR[BlockLengthInBytes..-1] + encr_block
39
+ end
40
+ outdata
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,146 @@
1
+ module GostMagma
2
+ class MagmaCfb < Magma
3
+ def initialize(key, iv, gamma_s)
4
+ @key = key.dup.force_encoding('BINARY')
5
+ @keys = []
6
+ (0...8).each do |i|
7
+ @keys << self.class.uint8ToUint32(@key[i*4...(i+1)*4].reverse)
8
+ end
9
+
10
+ @gamma_s = gamma_s
11
+ @ctxR = iv.dup.force_encoding('BINARY')
12
+ tmp_block = @ctxR[0...BlockLengthInBytes]
13
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
14
+ @incomplete_block = ''
15
+ @incomplete_block_len = 0
16
+ end
17
+
18
+ def encrypt(data)
19
+ data_len = data.length
20
+ left_data_len = data_len
21
+ outdata = ''
22
+ if @incomplete_block_len > 0 then
23
+ # use old @gamma_block
24
+ if data_len < @gamma_s - @incomplete_block_len then
25
+ # incomplete block yet
26
+ encr_data = data.dup
27
+ (0...data_len).each do |j|
28
+ encr_data[j] = (@gamma_block[@incomplete_block_len + j].ord ^ encr_data[j].ord).chr
29
+ end
30
+ @incomplete_block_len += data_len
31
+ @incomplete_block += encr_data
32
+ return encr_data
33
+ else
34
+ encr_data = data[0...(@gamma_s - @incomplete_block_len)]
35
+ (0...encr_data.length).each do |j|
36
+ encr_data[j] = (@gamma_block[@incomplete_block_len + j].ord ^ encr_data[j].ord).chr
37
+ end
38
+ outdata += encr_data
39
+ # complete block - gamma update
40
+ @incomplete_block += encr_data
41
+ left_data_len -= encr_data.length
42
+ @ctxR = @ctxR[@gamma_s..-1] + @incomplete_block
43
+ tmp_block = @ctxR[0...BlockLengthInBytes]
44
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
45
+ @incomplete_block = ''
46
+ end
47
+ end
48
+
49
+ (0...(left_data_len / @gamma_s)).each do |i|
50
+ if @incomplete_block_len > 0 then
51
+ encr_data = data[((i + 1) * @gamma_s - @incomplete_block_len)...((i + 2) * @gamma_s - @incomplete_block_len)]
52
+ else
53
+ encr_data = data[(i * @gamma_s)...((i + 1) * @gamma_s)]
54
+ end
55
+ (0...@gamma_s).each do |j|
56
+ encr_data[j] = (@gamma_block[j].ord ^ encr_data[j].ord).chr
57
+ end
58
+ outdata += encr_data
59
+ # complete block - gamma update
60
+ @ctxR = @ctxR[@gamma_s..-1] + encr_data
61
+ tmp_block = @ctxR[0...BlockLengthInBytes]
62
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
63
+ end
64
+
65
+ left_data_len %= @gamma_s
66
+ if left_data_len > 0 then
67
+ # incomplete block start
68
+ encr_data = data[-left_data_len..-1]
69
+ (0...left_data_len).each do |j|
70
+ encr_data[j] = (@gamma_block[j].ord ^ encr_data[j].ord).chr
71
+ end
72
+ outdata += encr_data
73
+ @incomplete_block_len = left_data_len
74
+ @incomplete_block = encr_data
75
+ end
76
+ outdata
77
+ end
78
+
79
+ # Use input encrypted text to gamma update
80
+ def decrypt(data)
81
+ data_len = data.length
82
+ left_data_len = data_len
83
+ outdata = ''
84
+ if @incomplete_block_len > 0 then
85
+ # use old @gamma_block
86
+ if data_len < @gamma_s - @incomplete_block_len then
87
+ # incomplete block yet
88
+ encr_data = data.dup
89
+ decr_data = data.dup
90
+ (0...data_len).each do |j|
91
+ decr_data[j] = (@gamma_block[@incomplete_block_len + j].ord ^ encr_data[j].ord).chr
92
+ end
93
+ @incomplete_block_len += data_len
94
+ @incomplete_block += encr_data
95
+ return decr_data
96
+ else
97
+ encr_data = data[0...(@gamma_s - @incomplete_block_len)]
98
+ decr_data = encr_data.dup
99
+ (0...encr_data.length).each do |j|
100
+ decr_data[j] = (@gamma_block[@incomplete_block_len + j].ord ^ encr_data[j].ord).chr
101
+ end
102
+ outdata += decr_data
103
+ # complete block - gamma update
104
+ @incomplete_block += encr_data
105
+ left_data_len -= encr_data.length
106
+ @ctxR = @ctxR[@gamma_s..-1] + @incomplete_block
107
+ tmp_block = @ctxR[0...BlockLengthInBytes]
108
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
109
+ @incomplete_block = ''
110
+ end
111
+ end
112
+
113
+ (0...(left_data_len / @gamma_s)).each do |i|
114
+ if @incomplete_block_len > 0 then
115
+ encr_data = data[((i + 1) * @gamma_s - @incomplete_block_len)...((i + 2) * @gamma_s - @incomplete_block_len)]
116
+ else
117
+ encr_data = data[(i * @gamma_s)...((i + 1) * @gamma_s)]
118
+ end
119
+ decr_data = encr_data.dup
120
+ (0...@gamma_s).each do |j|
121
+ decr_data[j] = (@gamma_block[j].ord ^ encr_data[j].ord).chr
122
+ end
123
+ outdata += decr_data
124
+ # complete block - gamma update
125
+ @ctxR = @ctxR[@gamma_s..-1] + encr_data
126
+ tmp_block = @ctxR[0...BlockLengthInBytes]
127
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
128
+ end
129
+
130
+ left_data_len %= @gamma_s
131
+ if left_data_len > 0 then
132
+ # incomplete block start
133
+ encr_data = data[-left_data_len..-1]
134
+ decr_data = encr_data.dup
135
+ (0...left_data_len).each do |j|
136
+ decr_data[j] = (@gamma_block[j].ord ^ encr_data[j].ord).chr
137
+ end
138
+ outdata += decr_data
139
+ @incomplete_block_len = left_data_len
140
+ @incomplete_block = encr_data
141
+ end
142
+ outdata
143
+ end
144
+
145
+ end
146
+ end
@@ -0,0 +1,73 @@
1
+ module GostMagma
2
+ class MagmaCtr < Magma
3
+ def initialize(key, iv, gamma_s)
4
+ @key = key.dup.force_encoding('BINARY')
5
+ @keys = []
6
+ (0...8).each do |i|
7
+ @keys << self.class.uint8ToUint32(@key[i*4...(i+1)*4].reverse)
8
+ end
9
+
10
+ @gamma_s = gamma_s
11
+ @iv = iv.dup.force_encoding('BINARY')
12
+ @prev_len = 0
13
+ @bytes_count = 0
14
+ @tmp_block = self.class.zeroBlock
15
+ if @iv.length < BlockLengthInBytes/2 then
16
+ @iv += self.class.zeroBytes(BlockLengthInBytes/2 - @iv.length)
17
+ end
18
+ @counter = @iv[0...(BlockLengthInBytes/2)]
19
+ @counter += self.class.zeroBytes(BlockLengthInBytes/2)
20
+ end
21
+
22
+ def encrypt(indata)
23
+ data_len = indata.length
24
+ outdata = self.class.zeroBytes(data_len)
25
+ data_index = 0
26
+ if @prev_len > 0 then
27
+ if data_len < (@gamma_s - @prev_len) then
28
+ (0...data_len).each do |j|
29
+ outdata[j] = (indata[j].ord ^ @tmp_block[j + @prev_len].ord).chr
30
+ end
31
+ @prev_len += data_len
32
+ @bytes_count += data_len
33
+ return outdata
34
+ else
35
+ (0...(@gamma_s - @prev_len)).each do |j|
36
+ outdata[j] = (indata[j].ord ^ @tmp_block[j + @prev_len].ord).chr
37
+ end
38
+ data_index += @gamma_s - @prev_len
39
+ @bytes_count += @gamma_s - @prev_len
40
+ data_len -= @gamma_s - @prev_len
41
+ self.class.incrementModulo(@counter, BlockLengthInBytes)
42
+ @prev_len = 0
43
+ end
44
+ end
45
+ (0...(data_len / @gamma_s)).each do |i|
46
+ @tmp_block = self.class.encryptBlock(@counter, @keys)
47
+ (0...@gamma_s).each do |j|
48
+ outdata[data_index + j] = (indata[data_index + j].ord ^ @tmp_block[j].ord).chr
49
+ end
50
+ data_index += @gamma_s
51
+ @bytes_count += @gamma_s
52
+ data_len -= @gamma_s
53
+ self.class.incrementModulo(@counter, BlockLengthInBytes)
54
+ @prev_len = 0
55
+ end
56
+ if data_len > 0 then
57
+ @tmp_block = self.class.encryptBlock(@counter, @keys)
58
+ (0...data_len).each do |j|
59
+ outdata[data_index + j] = (indata[data_index + j].ord ^ @tmp_block[j].ord).chr
60
+ end
61
+ @bytes_count += data_len
62
+ @prev_len = data_len
63
+ end
64
+ return outdata
65
+ end
66
+
67
+ def decrypt(data)
68
+ encrypt(data)
69
+ end
70
+
71
+ end
72
+ end
73
+
@@ -0,0 +1,91 @@
1
+ module GostMagma
2
+ class MagmaCtrAcpkm < Magma
3
+ def initialize(key, iv, gamma_s, section_N)
4
+ @key = key.dup.force_encoding('BINARY')
5
+ @keys = []
6
+ (0...8).each do |i|
7
+ @keys << self.class.uint8ToUint32(@key[i*4...(i+1)*4].reverse)
8
+ end
9
+
10
+ @iv = iv.dup.force_encoding('BINARY')
11
+ @gamma_s = gamma_s
12
+ @section_N = section_N
13
+ @gamma_bytes = 0
14
+ @section_bytes = 0
15
+ @block_bytes = 0
16
+ @bytes_count = 0
17
+ if @iv.length < BlockLengthInBytes/2 then
18
+ @iv += 0.chr * (BlockLengthInBytes/2 - @iv.length)
19
+ end
20
+ @counter = @iv[0...(BlockLengthInBytes/2)]
21
+ @counter += 0.chr * (BlockLengthInBytes/2)
22
+ @gamma = self.class.encryptBlock(@counter, @keys)
23
+ self.class.incrementModulo(@counter, BlockLengthInBytes)
24
+ end
25
+
26
+ def encrypt(indata)
27
+ data_len = indata.length
28
+ if data_len > 0 then
29
+ outdata = self.class.zeroBytes(data_len)
30
+ (0...data_len).each do |i|
31
+ if @section_bytes == @section_N then
32
+ acpkmCtrKey
33
+ @gamma = self.class.encryptBlock(@counter, @keys)
34
+ self.class.incrementModulo(@counter, BlockLengthInBytes)
35
+ @section_bytes = 0
36
+ @block_bytes = 0
37
+ @gamma_bytes = 0
38
+ else
39
+ if @gamma_bytes == @gamma_s then
40
+ @gamma = self.class.encryptBlock(@counter, @keys)
41
+ self.class.incrementModulo(@counter, BlockLengthInBytes)
42
+ @gamma_bytes = 0
43
+ end
44
+ if @block_bytes == BlockLengthInBytes then
45
+ @block_bytes = 0
46
+ end
47
+ end
48
+ outdata[i] = (indata[i].ord ^ @gamma[@gamma_bytes].ord).chr
49
+ @gamma_bytes += 1
50
+ @block_bytes += 1
51
+ @section_bytes += 1
52
+ @bytes_count += 1
53
+ end
54
+ return outdata
55
+ else
56
+ return ''
57
+ end
58
+ end
59
+
60
+ def decrypt(indata)
61
+ encrypt(indata)
62
+ end
63
+
64
+ protected
65
+
66
+ W1 = [
67
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87
68
+ ].pack('C*').freeze
69
+ W2 = [
70
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f
71
+ ].pack('C*').freeze
72
+ W3 = [
73
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97
74
+ ].pack('C*').freeze
75
+ W4 = [
76
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f
77
+ ].pack('C*').freeze
78
+
79
+ def acpkmCtrKey
80
+ @key = self.class.encryptBlock(W1, @keys) +
81
+ self.class.encryptBlock(W2, @keys) +
82
+ self.class.encryptBlock(W3, @keys) +
83
+ self.class.encryptBlock(W4, @keys)
84
+ @keys = []
85
+ (0...8).each do |i|
86
+ @keys << self.class.uint8ToUint32(@key[i*4...(i+1)*4].reverse)
87
+ end
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,47 @@
1
+ module GostMagma
2
+ class MagmaEcb < Magma
3
+ # key = 32-byte string
4
+ def initialize(key)
5
+ @key = key.dup.force_encoding('BINARY')
6
+ @keys = []
7
+ (0...8).each do |i|
8
+ @keys << self.class.uint8ToUint32(@key[i*4...(i+1)*4].reverse)
9
+ end
10
+ end
11
+
12
+ # returns encrypted text string
13
+ def encrypt(plain_text)
14
+ len = plain_text.length
15
+ if (len == 0) || (len % BlockLengthInBytes > 0) then
16
+ puts "(plain_text.length == 0) || (plain_text.length % BlockLengthInBytes > 0)"
17
+ return nil
18
+ end
19
+ blocks = plain_text.scan(/.{8}/m)
20
+ encrypted_blocks = []
21
+ blocks.each do |block|
22
+ encryptedBlock = self.class.encryptBlock(block, @keys)
23
+ encrypted_blocks << encryptedBlock
24
+ end
25
+ output = encrypted_blocks.join
26
+ return output
27
+ end
28
+
29
+ # returns decrypted text string
30
+ def decrypt(encrypted_text)
31
+ len = encrypted_text.length
32
+ if (len == 0) || (len % BlockLengthInBytes > 0) then
33
+ puts "(encrypted_text.length == 0) || (encrypted_text.length % BlockLengthInBytes > 0)"
34
+ return nil
35
+ end
36
+ blocks = encrypted_text.scan(/.{8}/m)
37
+ decrypted_blocks = []
38
+ blocks.each do |block|
39
+ decryptedBlock = self.class.decryptBlock(block, @keys)
40
+ decrypted_blocks << decryptedBlock
41
+ end
42
+ output = decrypted_blocks.join
43
+ return output
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,22 @@
1
+ module GostMagma
2
+ class MagmaKeyExpImp < Magma
3
+ def self.export(key, key_mac, key_enc, iv)
4
+ mac = MagmaOmac.new(key_mac, BlockLengthInBytes).update(iv+key).final
5
+ ctr = MagmaCtr.new(key_enc, iv, BlockLengthInBytes)
6
+ encr_key = ctr.encrypt(key)
7
+ encr_mac = ctr.encrypt(mac)
8
+ encr_key += encr_mac
9
+ end
10
+
11
+ def self.import(encr_key, key_mac, key_enc, iv)
12
+ buf = MagmaCtr.new(key_enc, iv, BlockLengthInBytes).decrypt(encr_key)
13
+ decr_key = buf[0...-BlockLengthInBytes]
14
+ decr_mac = buf[decr_key.length..-1]
15
+ mac = MagmaOmac.new(key_mac, BlockLengthInBytes).update(iv+decr_key).final
16
+ if mac != decr_mac then
17
+ decr_key = nil
18
+ end
19
+ decr_key
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,79 @@
1
+ module GostMagma
2
+ class MagmaOfb < Magma
3
+ def initialize(key, iv, gamma_s)
4
+ @key = key.dup.force_encoding('BINARY')
5
+ @keys = []
6
+ (0...8).each do |i|
7
+ @keys << self.class.uint8ToUint32(@key[i*4...(i+1)*4].reverse)
8
+ end
9
+
10
+ @gamma_s = gamma_s
11
+ @ctxR = iv.dup.force_encoding('BINARY')
12
+ tmp_block = @ctxR[0...BlockLengthInBytes]
13
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
14
+ @ctxR = @ctxR[BlockLengthInBytes..-1] + @gamma_block
15
+ @incomplete_block_len = 0
16
+ end
17
+
18
+ def encrypt(data)
19
+ data_len = data.length
20
+ outdata = ''
21
+ left_data_len = data_len
22
+ if @incomplete_block_len > 0 then
23
+ # use old @gamma_block
24
+ if data_len < @gamma_s - @incomplete_block_len then
25
+ # incomplete block yet
26
+ outdata = data.dup
27
+ (0...data_len).each do |j|
28
+ outdata[j] = (@gamma_block[@incomplete_block_len + j].ord ^ outdata[j].ord).chr
29
+ end
30
+ @incomplete_block_len += data_len
31
+ return outdata
32
+ else
33
+ outdata = data[0...(@gamma_s - @incomplete_block_len)]
34
+ (0...outdata.length).each do |j|
35
+ outdata[j] = (@gamma_block[@incomplete_block_len + j].ord ^ outdata[j].ord).chr
36
+ end
37
+ # complete block - update gamma block
38
+ tmp_block = @ctxR[0...BlockLengthInBytes]
39
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
40
+ @ctxR = @ctxR[BlockLengthInBytes..-1] + @gamma_block
41
+ left_data_len -= outdata.length
42
+ end
43
+ end
44
+
45
+ (0...(left_data_len / @gamma_s)).each do |i|
46
+ if @incomplete_block_len > 0 then
47
+ encr_data = data[((i + 1) * @gamma_s - @incomplete_block_len)...((i + 2) * @gamma_s - @incomplete_block_len)]
48
+ else
49
+ encr_data = data[(i * @gamma_s)...((i + 1) * @gamma_s)]
50
+ end
51
+ (0...@gamma_s).each do |j|
52
+ encr_data[j] = (@gamma_block[j].ord ^ encr_data[j].ord).chr
53
+ end
54
+ outdata += encr_data
55
+ # complete block - update gamma block
56
+ tmp_block = @ctxR[0...BlockLengthInBytes]
57
+ @gamma_block = self.class.encryptBlock(tmp_block, @keys)
58
+ @ctxR = @ctxR[BlockLengthInBytes..-1] + @gamma_block
59
+ left_data_len -= @gamma_s
60
+ end
61
+
62
+ if left_data_len > 0 then
63
+ # incomplete block start
64
+ encr_data = data[-left_data_len..-1]
65
+ (0...left_data_len).each do |j|
66
+ encr_data[j] = (@gamma_block[j].ord ^ encr_data[j].ord).chr
67
+ end
68
+ outdata += encr_data
69
+ @incomplete_block_len = left_data_len
70
+ end
71
+ outdata
72
+ end
73
+
74
+ def decrypt(data)
75
+ encrypt(data)
76
+ end
77
+
78
+ end
79
+ end