9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
# File 'lib/rmega/crypto/aes_ctr.rb', line 9
def decrypt(key, nonce, data)
raise "invalid nonce" if nonce.size != 4 or !nonce.respond_to?(:pack)
raise "invalid key" if key.size != 4 or !key.respond_to?(:pack)
mac = [nonce[0], nonce[1], nonce[0], nonce[1]]
enc = nil
a32 = Utils.str_to_a32 data
len = a32.size - 3
last_i = 0
(0..len).step(4) do |i|
enc = Aes.encrypt key, nonce
4.times do |m|
a32[i+m] = (a32[i+m] || 0) ^ (enc[m] || 0)
mac[m] = (mac[m] || 0) ^ (a32[i+m] || 0)
end
mac = Aes.encrypt key, mac
nonce[3] += 1
nonce[2] += 1 if nonce[3] == 0
last_i = i + 4
end
if last_i < a32.size
v = [0, 0, 0, 0]
(last_i..a32.size - 1).step(1) { |m| v[m-last_i] = a32[m] || 0 }
enc = Aes.encrypt key, nonce
4.times { |m| v[m] = v[m] ^ enc[m] }
j = data.size & 15
m = Utils.str_to_a32 Array.new(j+1).join(255.chr)+Array.new(17-j).join(0.chr)
4.times { |x| mac[x] = mac[x] ^ (v[x] & m[x]) }
mac = Aes.encrypt key, mac
(last_i..a32.size - 1).step(1) { |j| a32[j] = v[j - last_i] || 0 }
end
decrypted_data = Utils.a32_to_str(a32, data.size)
{data: decrypted_data, mac: mac}
end
|