Class: Rex::Crypto::Chacha20

Inherits:
Object
  • Object
show all
Defined in:
lib/rex/crypto/chacha20.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(key, iv) ⇒ Chacha20

Returns a new instance of Chacha20.

Raises:

  • (TypeError)

8
9
10
11
12
13
# File 'lib/rex/crypto/chacha20.rb', line 8

def initialize(key, iv)
  raise TypeError unless key.is_a? String
  raise TypeError unless iv.is_a? String

  @chacha_ctx = chacha20_ctx_setup(key, iv)
end

Instance Attribute Details

#chacha_ctxObject (readonly)

Returns the value of attribute chacha_ctx


6
7
8
# File 'lib/rex/crypto/chacha20.rb', line 6

def chacha_ctx
  @chacha_ctx
end

Instance Method Details

#chacha20_block_funcObject


56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rex/crypto/chacha20.rb', line 56

def chacha20_block_func
  chacha_state = @chacha_ctx.dup

  (1..10).each do |round|
    quarter_round(chacha_state, 0, 4, 8, 12)
    quarter_round(chacha_state, 1, 5, 9, 13)
    quarter_round(chacha_state, 2, 6, 10, 14)
    quarter_round(chacha_state, 3, 7, 11, 15)
    quarter_round(chacha_state, 0, 5, 10, 15)
    quarter_round(chacha_state, 1, 6, 11, 12)
    quarter_round(chacha_state, 2, 7, 8, 13)
    quarter_round(chacha_state, 3, 4, 9, 14)
  end

  keystream_arr = []
  (0..15).each do |index|
    keystream_ch = (chacha_state[index] + @chacha_ctx[index]) & 0xffffffff
    keystream_arr << (keystream_ch & 0xff)
    keystream_arr << (keystream_ch >> 8 & 0xff)
    keystream_arr << (keystream_ch >> 16 & 0xff)
    keystream_arr << (keystream_ch >> 24 & 0xff)
  end

  keystream_arr
end

#chacha20_crypt(data) ⇒ Object


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/rex/crypto/chacha20.rb', line 34

def chacha20_crypt(data)
  num_blocks = data.length / 64
  if data.length % 64 != 0
   num_blocks += 1
  end

  keystream = []
  (1..num_blocks).each do |block|
    keystream << chacha20_block_func
    chacha20_update_ctx
  end
  keystream = keystream.flatten

  enc = []
  i = 0
  data.unpack("c*").each do |a|
    enc << (a.ord ^ keystream[i])
    i += 1
  end
  enc.pack("c*").force_encoding('ASCII-8BIT')
end

#chacha20_ctx_setup(key, iv, position = 1) ⇒ Object


23
24
25
26
27
28
29
30
31
32
# File 'lib/rex/crypto/chacha20.rb', line 23

def chacha20_ctx_setup(key, iv, position=1)
  chacha_constants = [1634760805, 857760878, 2036477234, 1797285236]
  chacha_ctx = chacha_constants

  chacha_ctx += key.unpack('V8')
  chacha_ctx[12] = position
  chacha_ctx += iv.unpack('VVV')

  chacha_ctx
end

#chacha20_update_ctxObject


19
20
21
# File 'lib/rex/crypto/chacha20.rb', line 19

def chacha20_update_ctx
  @chacha_ctx[12] = (@chacha_ctx[12] + 1) & 0xffffffff
end

#quarter_round(x, a, b, c, d) ⇒ Object


86
87
88
89
90
91
92
93
94
95
# File 'lib/rex/crypto/chacha20.rb', line 86

def quarter_round(x, a, b, c, d)
  x[a] = (x[a] + x[b]) & 0xffffffff
  x[d] = rotate(x[d] ^ x[a], 16)
  x[c] = (x[c] + x[d]) & 0xffffffff
  x[b] = rotate(x[b] ^ x[c], 12)
  x[a] = (x[a] + x[b]) & 0xffffffff
  x[d] = rotate(x[d] ^ x[a], 8)
  x[c] = (x[c] + x[d]) & 0xffffffff
  x[b] = rotate(x[b] ^ x[c], 7)
end

#reset_cipher(key, iv) ⇒ Object


15
16
17
# File 'lib/rex/crypto/chacha20.rb', line 15

def reset_cipher(key, iv)
  @chacha_ctx = chacha20_ctx_setup(key, iv)
end

#rotate(v, c) ⇒ Object


82
83
84
# File 'lib/rex/crypto/chacha20.rb', line 82

def rotate(v, c)
  ((v << c) & 0xffffffff) | v >> (32 - c)
end