Module: Bitcoin::BIP324::ChaCha20
- Defined in:
- lib/bitcoin/bip324/fs_chacha20.rb
Constant Summary collapse
- INDICES =
[ [0, 4, 8, 12], [1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15], [0, 5, 10, 15], [1, 6, 11, 12], [2, 7, 8, 13], [3, 4, 9, 14] ]
- CONSTANTS =
[0x61707865, 0x3320646e, 0x79622d32, 0x6b206574]
Class Method Summary collapse
-
.block(key, nonce, count) ⇒ String
Compute the 64-byte output of the ChaCha20 block function.
-
.double_round(s) ⇒ Object
Apply a ChaCha20 double round to 16-element state array
s
. -
.rotl32(v, bits) ⇒ Integer
Rotate the 32-bit value v left by bits bits.
Class Method Details
.block(key, nonce, count) ⇒ String
Compute the 64-byte output of the ChaCha20 block function.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/bitcoin/bip324/fs_chacha20.rb', line 47 def block(key, nonce, count) raise Bitcoin::BIP324::Error, "key must be 32 byte string" if !key.is_a?(String) || key.bytesize != 32 raise Bitcoin::BIP324::Error, "nonce must be 12 byte string" if !nonce.is_a?(String) || nonce.bytesize != 12 raise Bitcoin::BIP324::Error, "count must be integer" unless count.is_a?(Integer) # Initialize state init = Array.new(16, 0) 4.times {|i| init[i] = CONSTANTS[i]} key = key.unpack("V*") 8.times {|i| init[4 + i] = key[i]} init[12] = count nonce = nonce.unpack("V*") 3.times {|i| init[13 + i] = nonce[i]} # Perform 20 rounds state = init.dup 10.times do state = double_round(state) end # Add initial values back into state. 16.times do |i| state[i] = (state[i] + init[i]) & 0xffffffff end state.pack("V16") end |
.double_round(s) ⇒ Object
Apply a ChaCha20 double round to 16-element state array s
.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/bitcoin/bip324/fs_chacha20.rb', line 27 def double_round(s) raise Bitcoin::BIP324::Error, "s must be Array" unless s.is_a?(Array) INDICES.each do |a, b, c, d| s[a] = (s[a] + s[b]) & 0xffffffff s[d] = rotl32(s[d] ^ s[a], 16) s[c] = (s[c] + s[d]) & 0xffffffff s[b] = rotl32(s[b] ^ s[c], 12) s[a] = (s[a] + s[b]) & 0xffffffff s[d] = rotl32(s[d] ^ s[a], 8) s[c] = (s[c] + s[d]) & 0xffffffff s[b] = rotl32(s[b] ^ s[c], 7) end s end |
.rotl32(v, bits) ⇒ Integer
Rotate the 32-bit value v left by bits bits.
18 19 20 21 22 |
# File 'lib/bitcoin/bip324/fs_chacha20.rb', line 18 def rotl32(v, bits) raise Bitcoin::BIP324::Error, "v must be integer" unless v.is_a?(Integer) raise Bitcoin::BIP324::Error, "bits must be integer" unless bits.is_a?(Integer) ((v << bits) & 0xffffffff) | (v >> (32 - bits)) end |