Class: CryptoToolchain::Tools::RSAPaddingOracleAttack

Inherits:
Object
  • Object
show all
Defined in:
lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb,
lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(oracle: BlackBoxes::RSAPaddingOracle.new, n:, e: 3) ⇒ RSAPaddingOracleAttack

Returns a new instance of RSAPaddingOracleAttack.



10
11
12
13
14
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 10

def initialize(oracle: BlackBoxes::RSAPaddingOracle.new, n: , e: 3)
  @oracle = oracle
  @n = n
  @e = e
end

Instance Attribute Details

#eObject (readonly)

Returns the value of attribute e.



15
16
17
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 15

def e
  @e
end

#nObject (readonly)

Returns the value of attribute n.



15
16
17
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 15

def n
  @n
end

#oracleObject (readonly)

Returns the value of attribute oracle.



15
16
17
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 15

def oracle
  @oracle
end

Instance Method Details

#add_interval(intervals, lower, upper) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 72

def add_interval(intervals, lower, upper)
  matched = false
  new_intervals = intervals.map do |a, b|
    if b < lower || a > upper
      # interval to be added does not overlap an existing interval - persist the existing interval
      # if we never overlap an interval, we'll add the [lower, upper] interval later
      [a, b]
    else
      # interval to be added overlaps - extend that interval according to [lower, upper]
      matched = true
      [
        [lower, a].min,
        [upper, b].max
      ]
    end
  end
  if matched
    new_intervals
  else
    new_intervals.push([lower, upper])
  end
end

#big_bObject



120
121
122
123
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 120

def big_b
  k = oracle.keypair.bits / 8
  2**(8 * (k - 2))
end

#calculate_intervals(intervals, s) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 57

def calculate_intervals(intervals, s)
  new_intervals = []
  intervals.each do |a, b|
    min_r = (a * s - 3 * big_b + 1).updiv(n)
    max_r = (b * s - 2 * big_b) / n
    (min_r..max_r).each do |r|
      aa = [a, (2 * big_b + r * n).updiv(s)].max
      bb = [b, ((3 * big_b - 1 + r * n) / s)].min

      new_intervals = add_interval(new_intervals, aa, bb)
    end
  end
  new_intervals
end

#check(int) ⇒ Object



17
18
19
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 17

def check(int)
  oracle.execute(str_for(int))
end

#execute(ciphertext) ⇒ Object



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
52
53
54
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 27

def execute(ciphertext)
  s = 1
  @c0 = ciphertext.to_number
  intervals = [ [ (2*big_b), (3*big_b ) ] ]
  i = 1
  loop do
    if i == 1
      #2a
      s = start_search()
    elsif intervals.length > 1
      #2b
      s += 1
      s += 1 until check((@c0 * s.modpow(e, n)) % n)
    elsif intervals.length == 1
      #2c
      a, b = intervals.first

      if a == b
        return str_for(a)
      end
      s = search_with_single_interval(a, b, s)
    end

    # 3
    intervals = calculate_intervals(intervals, s)
    i += 1
  end
end

#search_with_single_interval(a, b, s) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 106

def search_with_single_interval(a, b, s)
  r = (2 * (b * s - 2 * big_b)) / (n)
  s = (2 * big_b + r * n) / (b)

  until check((@c0 * s.modpow(e,n)) % n)
    s += 1
    if s > (3 * big_b + r * n) / a
      r += 1
      s = (2 * big_b + r * n) / b
    end
  end
  s
end

#start_searchObject



95
96
97
98
99
100
101
102
103
104
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 95

def start_search
  s1 = n.updiv(3 * big_b)
  loop do
    c = (@c0 * s1.modpow(e, n)) % n
    if check(c)
      return s1
    end
    s1 += 1
  end
end

#str_for(int) ⇒ Object



21
22
23
24
25
# File 'lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb', line 21

def str_for(int)
  str = int.to_bin_string
  pad = "\x00" * (n.bit_length.updiv(8) - str.bytesize)
  "#{pad}#{str}"
end