Module: Lightning::Onion::ChaCha20
- Defined in:
- lib/lightning/onion/chacha20.rb
Class Method Summary collapse
-
.chacha20_block(key, counter, nonce) ⇒ Object
key: 32 bytes counter: integer (4 bytes) nonce: 12 bytes.
- .chacha20_encrypt(key, counter, nonce, plaintext) ⇒ Object
- .constants ⇒ Object
- .inner_block(x) ⇒ Object
- .plus(x, y) ⇒ Object
- .plus_for_string(a, b) ⇒ Object
- .quater_round(a, b, c, d) ⇒ Object
- .rotate(x, n) ⇒ Object
- .xor(a, b) ⇒ Object
Class Method Details
.chacha20_block(key, counter, nonce) ⇒ Object
key: 32 bytes counter: integer (4 bytes) nonce: 12 bytes
36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/lightning/onion/chacha20.rb', line 36 def self.chacha20_block(key, counter, nonce) # reverse order key = key.unpack('V*').pack('N*') counter = [counter].pack('N*') nonce = nonce.unpack('V*').pack('N*') state = constants + key + counter + nonce working_state = state.unpack('N*') 10.times do inner_block(working_state) end plus_for_string(state, working_state) end |
.chacha20_encrypt(key, counter, nonce, plaintext) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/lightning/onion/chacha20.rb', line 10 def self.chacha20_encrypt(key, counter, nonce, plaintext) = +'' (plaintext.length / 64).times do |i| key_stream = chacha20_block(key, counter + i, nonce) block = plaintext[(i * 64)...(i + 1) * 64] += xor(block, key_stream) end if plaintext.length % 64 != 0 i = plaintext.length / 64 key_stream = chacha20_block(key, counter + i, nonce) block = plaintext[(i * 64)...plaintext.length] block = block.ljust(64, "\x00") += xor(block, key_stream)[0...(plaintext.length % 64)] end end |
.constants ⇒ Object
6 7 8 |
# File 'lib/lightning/onion/chacha20.rb', line 6 def self.constants [0x61707865, 0x3320646e, 0x79622d32, 0x6b206574].pack('N*') end |
.inner_block(x) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/lightning/onion/chacha20.rb', line 49 def self.inner_block(x) # column rounds x[0], x[4], x[8], x[12] = quater_round(x[0], x[4], x[8], x[12]) x[1], x[5], x[9], x[13] = quater_round(x[1], x[5], x[9], x[13]) x[2], x[6], x[10], x[14] = quater_round(x[2], x[6], x[10], x[14]) x[3], x[7], x[11], x[15] = quater_round(x[3], x[7], x[11], x[15]) # diagonal rounds x[0], x[5], x[10], x[15] = quater_round(x[0], x[5], x[10], x[15]) x[1], x[6], x[11], x[12] = quater_round(x[1], x[6], x[11], x[12]) x[2], x[7], x[8], x[13] = quater_round(x[2], x[7], x[8], x[13]) x[3], x[4], x[9], x[14] = quater_round(x[3], x[4], x[9], x[14]) end |
.plus(x, y) ⇒ Object
68 69 70 |
# File 'lib/lightning/onion/chacha20.rb', line 68 def self.plus(x, y) (x + y) & 0xffffffff end |
.plus_for_string(a, b) ⇒ Object
62 63 64 65 66 |
# File 'lib/lightning/onion/chacha20.rb', line 62 def self.plus_for_string(a, b) a.unpack('N*').map.with_index do |x, i| plus(x, b[i]) end.pack('V*') end |
.quater_round(a, b, c, d) ⇒ Object
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/lightning/onion/chacha20.rb', line 78 def self.quater_round(a, b, c, d) a = plus(a, b) d ^= a d = rotate(d, 16) c = plus(c, d) b ^= c b = rotate(b, 12) a = plus(a, b) d ^= a d = rotate(d, 8) c = plus(c, d) b ^= c b = rotate(b, 7) [a, b, c, d] end |
.rotate(x, n) ⇒ Object
72 73 74 75 76 |
# File 'lib/lightning/onion/chacha20.rb', line 72 def self.rotate(x, n) y = x << n z = x >> (32 - n) (y | z) & 0xffffffff end |
.xor(a, b) ⇒ Object
27 28 29 30 31 |
# File 'lib/lightning/onion/chacha20.rb', line 27 def self.xor(a, b) a = a.unpack('N*') b = b.unpack('N*') a.zip(b).map { |x, y| (x ^ y) & 0xffffffff }.pack('N*') end |