crypto-toolbox 0.2.7 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/break-padding-oracle +3 -1
- data/lib/crypto-toolbox.rb +9 -1
- data/lib/crypto-toolbox/analyzers/cbc_mutating_encryption.rb +20 -0
- data/lib/crypto-toolbox/analyzers/ecb_string_appender.rb +2 -1
- data/lib/crypto-toolbox/analyzers/padding_oracle/analyzer.rb +12 -16
- data/lib/crypto-toolbox/ciphers/aes.rb +41 -21
- data/lib/crypto-toolbox/crypt_buffer/concerns/padding.rb +21 -9
- data/lib/crypto-toolbox/crypt_buffer_input_converter.rb +9 -2
- data/lib/crypto-toolbox/matasano/sets/set2.rb +9 -0
- data/lib/crypto-toolbox/matasano/sets/set3.rb +11 -0
- data/lib/crypto-toolbox/matasano/solver.rb +2 -0
- data/lib/crypto-toolbox/oracles/cbc_mutating_encryption_oracle.rb +44 -0
- data/lib/crypto-toolbox/{analyzers/padding_oracle/oracles → oracles/padding_oracle}/http_oracle.rb +3 -4
- data/lib/crypto-toolbox/oracles/padding_oracle/memory_oracle.rb +69 -0
- data/lib/crypto-toolbox/{analyzers/padding_oracle/oracles → oracles/padding_oracle}/tcp_oracle.rb +3 -8
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac647d6b3c258b6a0f67e6f842c417e05fa9d432
|
4
|
+
data.tar.gz: b23897bb84b56a1ca9ad119a87bd562568ff555e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48140f890a028bf4f43c9f482141edc90c4617b5fba729a958b6b621cbe51e6775c5820611930b474cb0c7ef0a06e8bce0a06d574420fbca77f870a6aa7ad848
|
7
|
+
data.tar.gz: 448b241d14ca70b2b8b8a5174da29d5a79664c8ccc1b29523b5390e41be20495b504ae8aa41017c5d0c028d61499e15d5dcd4bf3291c86a540d4ff0145497756
|
data/bin/break-padding-oracle
CHANGED
data/lib/crypto-toolbox.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
-
|
1
|
+
require 'base64'
|
2
|
+
|
2
3
|
require 'crypto-toolbox/utils/reporting/console.rb'
|
3
4
|
require 'crypto-toolbox/utils/hamming_distance_filter.rb'
|
4
5
|
require 'crypto-toolbox/utils/ecb_detector.rb'
|
5
6
|
require 'crypto-toolbox/utils/ecb_oracle.rb'
|
6
7
|
|
7
8
|
require 'crypto-toolbox/oracles/user_profile_encryption_oracle.rb'
|
9
|
+
require 'crypto-toolbox/oracles/cbc_mutating_encryption_oracle.rb'
|
10
|
+
|
11
|
+
require 'crypto-toolbox/oracles/padding_oracle/tcp_oracle.rb'
|
12
|
+
require 'crypto-toolbox/oracles/padding_oracle/http_oracle.rb'
|
13
|
+
require 'crypto-toolbox/oracles/padding_oracle/memory_oracle.rb'
|
14
|
+
|
8
15
|
|
9
16
|
|
10
17
|
|
@@ -22,6 +29,7 @@ require 'crypto-toolbox/analyzers/padding_oracle.rb'
|
|
22
29
|
require 'crypto-toolbox/analyzers/cbc_mac.rb'
|
23
30
|
require 'crypto-toolbox/analyzers/vigenere_xor.rb'
|
24
31
|
require 'crypto-toolbox/analyzers/ecb_string_appender.rb'
|
32
|
+
require 'crypto-toolbox/analyzers/cbc_mutating_encryption.rb'
|
25
33
|
|
26
34
|
|
27
35
|
require 'crypto-toolbox/ciphers/aes.rb'
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module CryptoToolbox
|
2
|
+
module Analyzers
|
3
|
+
class CbcMutatingEncryption
|
4
|
+
attr_reader :oracle
|
5
|
+
def initialize(oracle)
|
6
|
+
@oracle = oracle
|
7
|
+
end
|
8
|
+
|
9
|
+
def assemble_attack_message
|
10
|
+
# we are lazy thus we use 0 as a byte which is neutral to xor,
|
11
|
+
# thus we dont have to cancel it before adding admin=true.
|
12
|
+
input = "\0" * 32
|
13
|
+
blocks = @oracle.encrypted_message_for(input).chunks_of(16)
|
14
|
+
fake = blocks[2].xor(";admin=true;",expand_input: false )
|
15
|
+
blocks[2] = fake
|
16
|
+
ciphertext = blocks.map(&:str).join
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -105,6 +105,7 @@ module Analyzers
|
|
105
105
|
dict[result].tap do |match|
|
106
106
|
jot(match,debug: true,raw: true) unless match.nil?
|
107
107
|
if match.nil?
|
108
|
+
binding.pry
|
108
109
|
raise "Could not find dictonary entry for block #{block_id}, pos: #{pos}"
|
109
110
|
end
|
110
111
|
end
|
@@ -182,7 +183,7 @@ module Analyzers
|
|
182
183
|
total_length = oracle.encipher(@prefix_pad + (DUMMY * i) ).length
|
183
184
|
result = total_length - (@prefix_blocks * block_size )
|
184
185
|
if result > minimum_length
|
185
|
-
return minimum_length -
|
186
|
+
return minimum_length - i
|
186
187
|
end
|
187
188
|
end
|
188
189
|
end
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require 'crypto-toolbox/analyzers/padding_oracle/oracles/http_oracle.rb'
|
2
|
-
require 'crypto-toolbox/analyzers/padding_oracle/oracles/tcp_oracle.rb'
|
3
|
-
|
4
1
|
|
5
2
|
module Analyzers
|
6
3
|
module PaddingOracle
|
@@ -10,7 +7,7 @@ module Analyzers
|
|
10
7
|
attr_reader :result
|
11
8
|
include ::Utils::Reporting::Console
|
12
9
|
|
13
|
-
def initialize(oracle = ::
|
10
|
+
def initialize(oracle = CryptoToolbox::Oracles::PaddingOracle::TcpOracle.new)
|
14
11
|
@result = [ ]
|
15
12
|
@oracle = oracle
|
16
13
|
end
|
@@ -25,21 +22,21 @@ module Analyzers
|
|
25
22
|
def analyze(cipher)
|
26
23
|
blocks = CryptBuffer.from_hex(cipher).chunks_of(16)
|
27
24
|
|
28
|
-
#
|
25
|
+
# ranges cant be from high to low
|
29
26
|
(1..(blocks.length() -1)).reverse_each do |block_index|
|
30
27
|
result.unshift analyse_block(blocks,block_index)
|
31
28
|
end
|
32
|
-
|
33
|
-
report_result(result)
|
34
|
-
end
|
35
|
-
|
36
29
|
|
30
|
+
plaintext = CryptBuffer(result.flatten)
|
31
|
+
report_result(plaintext)
|
32
|
+
plaintext.strip_padding
|
33
|
+
end
|
37
34
|
|
38
35
|
private
|
39
36
|
|
40
37
|
def analyse_block(blocks,block_index)
|
41
38
|
block_result = []
|
42
|
-
|
39
|
+
|
43
40
|
# manipulate each byte of the 16 byte block
|
44
41
|
1.upto(blocks[block_index -1].length) do |pad_index|
|
45
42
|
with_oracle_connection do
|
@@ -52,9 +49,9 @@ module Analyzers
|
|
52
49
|
end
|
53
50
|
|
54
51
|
def report_result(result)
|
55
|
-
jot(
|
52
|
+
jot(result.chars.inspect,debug: true)
|
56
53
|
jot("stripping padding!",debug: true)
|
57
|
-
jot(
|
54
|
+
jot(result.strip_padding.str,debug: true)
|
58
55
|
end
|
59
56
|
|
60
57
|
def with_oracle_connection
|
@@ -83,15 +80,14 @@ module Analyzers
|
|
83
80
|
# and store the result in a buffer we will mess with
|
84
81
|
forge_buf = apply_found_bytes(blocks[block_index - 1],cur_result,pad_index)
|
85
82
|
|
86
|
-
1.upto
|
83
|
+
1.upto 255 do |guess|
|
87
84
|
input = assemble_oracle_input(forge_buf,blocks,block_index,pad_index,guess)
|
88
85
|
|
89
86
|
next if skip?(pad_index,block_index,guess,cur_result)
|
90
|
-
|
91
|
-
return guess if@oracle.valid_padding?(input,block_amount(block_index))
|
87
|
+
return guess if @oracle.valid_padding?(input,block_amount(block_index))
|
92
88
|
end
|
93
89
|
|
94
|
-
raise FailedAnalysis, "No padding found... this should
|
90
|
+
raise FailedAnalysis, "No padding found... this should never happen..."
|
95
91
|
end
|
96
92
|
private
|
97
93
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
module Ciphers
|
2
3
|
class Aes
|
3
4
|
|
@@ -8,32 +9,48 @@ module Ciphers
|
|
8
9
|
end
|
9
10
|
|
10
11
|
# NOTE convert ECB encryption to AES gem or both to openssl
|
11
|
-
def decipher_ecb(key,input)
|
12
|
-
decipher_ecb_blockwise(CryptBuffer(key),CryptBuffer(input).chunks_of(@block_size_bytes))
|
12
|
+
def decipher_ecb(key,input,strip_padding: true)
|
13
|
+
plain = decipher_ecb_blockwise(CryptBuffer(key),CryptBuffer(input).chunks_of(@block_size_bytes)).to_crypt_buffer
|
14
|
+
strip_padding ? plain.strip_padding : plain
|
13
15
|
end
|
14
16
|
|
15
17
|
def encipher_ecb(key,input)
|
16
|
-
encipher_ecb_blockwise(CryptBuffer(key),
|
18
|
+
encipher_ecb_blockwise(CryptBuffer(key),pad_message(input).chunks_of(@block_size_bytes))
|
17
19
|
end
|
18
20
|
|
19
21
|
def encipher_cbc(key_str,input_str,iv: nil)
|
20
|
-
unicipher_cbc(:encipher,key_str,input_str,iv)
|
22
|
+
unicipher_cbc(:encipher,key_str,pad_message(input_str),iv)
|
21
23
|
end
|
22
24
|
|
23
|
-
def decipher_cbc(key_str,input_str,iv: nil)
|
24
|
-
unicipher_cbc(:decipher,key_str,input_str,iv)
|
25
|
+
def decipher_cbc(key_str,input_str,iv: nil,strip_padding: true)
|
26
|
+
plain = unicipher_cbc(:decipher,key_str,CryptBuffer(input_str),iv).to_crypt_buffer
|
27
|
+
strip_padding ? plain.strip_padding : plain
|
25
28
|
end
|
26
29
|
|
27
30
|
|
28
31
|
private
|
29
32
|
|
33
|
+
def pad_message(input)
|
34
|
+
buffer=CryptBuffer(input)
|
35
|
+
final_block_size = buffer.length % @block_size_bytes
|
36
|
+
delta = @block_size_bytes - final_block_size
|
37
|
+
if delta > 0
|
38
|
+
buffer.pad(delta)
|
39
|
+
else
|
40
|
+
buffer
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def pad_block(block)
|
45
|
+
return block
|
46
|
+
end
|
47
|
+
|
30
48
|
def encipher_ecb_blockwise(key,blocks)
|
31
49
|
blocks.map{|block| encipher_ecb_block(key,block) }.join
|
32
50
|
end
|
33
51
|
|
34
52
|
def encipher_ecb_block(key,block)
|
35
|
-
|
36
|
-
_,out = AES.encrypt(block.str, key.hex, {:format => :plain,:padding => need_padding,:cipher => "AES-#{@key_size}-ECB"})
|
53
|
+
_,out = AES.encrypt(block.str, key.hex, {:format => :plain,:padding => false,:cipher => "AES-#{@key_size}-ECB"})
|
37
54
|
out
|
38
55
|
end
|
39
56
|
|
@@ -42,22 +59,23 @@ module Ciphers
|
|
42
59
|
end
|
43
60
|
|
44
61
|
def decipher_ecb_block(key,block)
|
45
|
-
need_padding = block.length < @block_size_bytes
|
62
|
+
need_padding = (block.length < @block_size_bytes)
|
46
63
|
AES.decrypt(["",block.str], key.hex, {:format => :plain,:padding => need_padding,:cipher => "AES-#{@key_size}-ECB"})
|
47
64
|
end
|
48
65
|
|
49
66
|
# this method is used for encipher and decipher since most of the code is identical
|
50
67
|
# only the value of the previous block and the internal ecb method differs
|
51
|
-
def unicipher_cbc(direction,key_str,
|
68
|
+
def unicipher_cbc(direction,key_str,input_buf,iv)
|
69
|
+
|
52
70
|
method="#{direction.to_s}_cbc_block"
|
53
|
-
blocks =
|
71
|
+
blocks = input_buf.chunks_of(@block_size_bytes)
|
54
72
|
iv ||= blocks.shift.str
|
55
73
|
key = CryptBuffer(key_str).hex
|
56
74
|
|
57
75
|
prev_block=iv.to_crypt_buffer
|
58
76
|
|
59
|
-
blocks.map do |block|
|
60
|
-
ctext_block = send(method,key,block,prev_block)
|
77
|
+
strings = blocks.map.with_index do |block,i|
|
78
|
+
ctext_block = send(method,key,block,prev_block)
|
61
79
|
if direction == :encipher
|
62
80
|
prev_block = ctext_block
|
63
81
|
else
|
@@ -65,22 +83,24 @@ module Ciphers
|
|
65
83
|
end
|
66
84
|
|
67
85
|
ctext_block.str
|
68
|
-
end
|
86
|
+
end
|
87
|
+
|
88
|
+
CryptBuffer(strings.join)
|
69
89
|
end
|
70
90
|
|
71
91
|
def encipher_cbc_block(key,block,prev_block)
|
72
92
|
xored = block ^ prev_block
|
73
|
-
|
74
|
-
|
75
|
-
_,out = AES.encrypt(xored.str, key, {:format => :plain,:padding => need_padding,:cipher => "AES-#{@key_size}-ECB",:iv => prev_block.str })
|
93
|
+
|
94
|
+
_,out = AES.encrypt(xored.str, key, {:format => :plain,:padding => false,:cipher => "AES-#{@key_size}-ECB",:iv => prev_block.str })
|
76
95
|
ecb_block = CryptBuffer(out)
|
77
96
|
end
|
97
|
+
|
78
98
|
def decipher_cbc_block(key,block,prev_block)
|
79
|
-
|
80
|
-
|
81
|
-
out = ::AES.decrypt([prev_block.str,block.str] , key, {:format => :plain,:padding => need_padding,:cipher => "AES-#{@key_size}-ECB",:iv => prev_block.str })
|
99
|
+
|
100
|
+
out = ::AES.decrypt([prev_block.str,block.str] , key, {:format => :plain,:padding => false,:cipher => "AES-#{@key_size}-ECB",:iv => prev_block.str })
|
82
101
|
ecb_block = CryptBuffer(out)
|
83
|
-
|
102
|
+
|
103
|
+
xored = ecb_block ^ prev_block
|
84
104
|
end
|
85
105
|
|
86
106
|
end
|
@@ -1,14 +1,17 @@
|
|
1
|
+
|
2
|
+
|
1
3
|
module CryptBufferConcern
|
4
|
+
# This module extends functionality the CryptBuffer to
|
5
|
+
# handle PKCS7 padding.
|
6
|
+
# It has the ability to detect, replace, add and strip a
|
7
|
+
# padding from a CryptBuffer to return a new one without
|
8
|
+
# mutating the existing buffer.
|
9
|
+
#
|
10
|
+
# The purpose is making crypto analysis of cbc and other
|
11
|
+
# cipher modes that use pkcs7 padding easier.
|
2
12
|
module Padding
|
3
|
-
|
4
|
-
|
5
|
-
# It has the ability to detect, replace, add and strip a
|
6
|
-
# padding from a CryptBuffer to return a new one without
|
7
|
-
# mutating the existing buffer.
|
8
|
-
#
|
9
|
-
# The purpose is making crypto analysis of cbc and other
|
10
|
-
# cipher modes that use pkcs7 padding easier.
|
11
|
-
|
13
|
+
class InvalidPkcs7Padding < RuntimeError; end
|
14
|
+
|
12
15
|
# Return any existing padding
|
13
16
|
def padding
|
14
17
|
last = bytes.last
|
@@ -32,7 +35,16 @@ module CryptBufferConcern
|
|
32
35
|
end
|
33
36
|
self.class.new(subset)
|
34
37
|
end
|
38
|
+
|
39
|
+
def strip_padding!
|
40
|
+
validate_padding!
|
41
|
+
strip_padding
|
42
|
+
end
|
35
43
|
|
44
|
+
def validate_padding!
|
45
|
+
raise InvalidPkcs7Padding, "No valid pkcs#7 padding present" unless padding?
|
46
|
+
true
|
47
|
+
end
|
36
48
|
|
37
49
|
def padding?
|
38
50
|
!padding.empty?
|
@@ -1,6 +1,8 @@
|
|
1
1
|
|
2
|
-
|
3
2
|
class CryptBufferInputConverter
|
3
|
+
class ImpossibleConversion < RuntimeError; end
|
4
|
+
class InvalidHexstring < RuntimeError; end
|
5
|
+
|
4
6
|
def convert(input)
|
5
7
|
bytes_from_any(input)
|
6
8
|
end
|
@@ -9,6 +11,7 @@ class CryptBufferInputConverter
|
|
9
11
|
# This is especially useful for unknown or uncertain inputs like
|
10
12
|
# strings with or without leading 0x
|
11
13
|
def from_hex(input)
|
14
|
+
raise InvalidHexstring, "input: #{input} is not a valid hexadicimal string" unless valid_hexstring?(input)
|
12
15
|
hexstr =""
|
13
16
|
unless input.nil?
|
14
17
|
hexstr = normalize_hex(input)
|
@@ -63,7 +66,11 @@ class CryptBufferInputConverter
|
|
63
66
|
tmp = pad_hex_char(str)
|
64
67
|
tmp.gsub(/(^0x|\s)/,"").upcase
|
65
68
|
end
|
66
|
-
|
69
|
+
private
|
70
|
+
|
71
|
+
def valid_hexstring?(input)
|
72
|
+
input =~ /^(0x)?[a-fA-F0-9]+$/
|
73
|
+
end
|
67
74
|
end
|
68
75
|
|
69
76
|
def CryptBuffer(input)
|
@@ -57,6 +57,15 @@ module Matasano
|
|
57
57
|
Analyzers::EcbStringAppender.new(oracle).analyze
|
58
58
|
end
|
59
59
|
|
60
|
+
def solve15(input)
|
61
|
+
CryptBuffer(input).strip_padding!.str
|
62
|
+
end
|
63
|
+
|
64
|
+
def solve16(oracle)
|
65
|
+
analyzer = CryptoToolbox::Analyzers::CbcMutatingEncryption.new(oracle)
|
66
|
+
analyzer.assemble_attack_message
|
67
|
+
end
|
68
|
+
|
60
69
|
end
|
61
70
|
end
|
62
71
|
end
|
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'crypto-toolbox/matasano/sets/set1.rb'
|
2
2
|
require 'crypto-toolbox/matasano/sets/set2.rb'
|
3
|
+
require 'crypto-toolbox/matasano/sets/set3.rb'
|
3
4
|
|
4
5
|
module Matasano
|
5
6
|
class Solver
|
6
7
|
include Matasano::Sets::Set1
|
7
8
|
include Matasano::Sets::Set2
|
9
|
+
include Matasano::Sets::Set3
|
8
10
|
end
|
9
11
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module CryptoToolbox
|
2
|
+
module Oracles
|
3
|
+
class CbcMutatingEncryptionOracle
|
4
|
+
attr_reader :prefix,:suffix
|
5
|
+
|
6
|
+
|
7
|
+
def initialize(key = SecureRandom.random_bytes(16) )
|
8
|
+
@key = key
|
9
|
+
@prefix = "comment1=cooking%20MCs;userdata="
|
10
|
+
@suffix = ";comment2=%20like%20a%20pound%20of%20bacon"
|
11
|
+
@iv = SecureRandom.random_bytes(16)
|
12
|
+
end
|
13
|
+
|
14
|
+
#make sure this attack is not possible
|
15
|
+
# fake_user="admin=true;admin=true;"
|
16
|
+
# ciphertext = oracle.encrypted_message_for(fake_user)
|
17
|
+
# oracle.is_admin?(ciphertext)
|
18
|
+
def message_for(user)
|
19
|
+
user.gsub!(/[;=]/,"") # sanitize meta chars
|
20
|
+
@prefix + user + @suffix
|
21
|
+
end
|
22
|
+
|
23
|
+
def parse_message(string)
|
24
|
+
string.split(";").each_with_object({}){|pair,hsh| k,v = pair.split("="); hsh[k.to_sym] = v }
|
25
|
+
end
|
26
|
+
|
27
|
+
def encrypted_message_for(user)
|
28
|
+
Ciphers::Aes.new.encipher_cbc(@key,message_for(user),iv: @iv)
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_admin?(ciphertext)
|
32
|
+
data = decrypt_message(ciphertext)
|
33
|
+
data.has_key?(:admin) && data[:admin] == "true"
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
def decrypt_message(ciphertext)
|
38
|
+
plaintext = Ciphers::Aes.new.decipher_cbc(@key,ciphertext,iv: @iv).to_crypt_buffer.strip_padding.str
|
39
|
+
parse_message(plaintext)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module CryptoToolbox
|
2
|
+
module Oracles
|
3
|
+
module PaddingOracle
|
4
|
+
|
5
|
+
class PlaintextSelection
|
6
|
+
PLAIN_TEXTS= %w(
|
7
|
+
MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=
|
8
|
+
MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic=
|
9
|
+
MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw==
|
10
|
+
MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg==
|
11
|
+
MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl
|
12
|
+
MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA==
|
13
|
+
MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw==
|
14
|
+
MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8=
|
15
|
+
MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g=
|
16
|
+
MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93
|
17
|
+
).freeze
|
18
|
+
def self.sample
|
19
|
+
samples.sample
|
20
|
+
end
|
21
|
+
def self.samples
|
22
|
+
PLAIN_TEXTS
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class MemoryOracle
|
27
|
+
attr_reader :secret_plaintext # for result validation only. I can trust myself
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
@key = SecureRandom.random_bytes(16)
|
31
|
+
@iv = SecureRandom.random_bytes(16)
|
32
|
+
@secret_plaintext = CryptBuffer.from_base64(PlaintextSelection::sample).str
|
33
|
+
end
|
34
|
+
|
35
|
+
def sample_ciphertext
|
36
|
+
@ciphertext ||= generate_ciphertext
|
37
|
+
end
|
38
|
+
|
39
|
+
def connect; end
|
40
|
+
def disconnect; end
|
41
|
+
|
42
|
+
def valid_padding?(input,custom_block_amount=nil)
|
43
|
+
# openssl will throw on invalid padding
|
44
|
+
begin
|
45
|
+
block = CryptBuffer(input)
|
46
|
+
result = CryptBuffer(decrypt(block))
|
47
|
+
result.validate_padding!
|
48
|
+
rescue CryptBufferConcern::Padding::InvalidPkcs7Padding => ex
|
49
|
+
false
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def generate_ciphertext
|
56
|
+
CryptBuffer(@iv + Ciphers::Aes.new.encipher_cbc(@key,@secret_plaintext,iv: @iv).str).hex
|
57
|
+
end
|
58
|
+
|
59
|
+
def decrypt(msg)
|
60
|
+
Ciphers::Aes.new.decipher_cbc(@key,msg,iv: @iv,strip_padding: false)
|
61
|
+
end
|
62
|
+
|
63
|
+
def check_padding(msg)
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/crypto-toolbox/{analyzers/padding_oracle/oracles → oracles/padding_oracle}/tcp_oracle.rb
RENAMED
@@ -1,15 +1,10 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
module Analyzers
|
6
|
-
module PaddingOracle
|
7
|
-
module Oracles
|
1
|
+
module CryptoToolbox
|
2
|
+
module Oracles
|
3
|
+
module PaddingOracle
|
8
4
|
|
9
5
|
class TcpOracle
|
10
6
|
def initialize
|
11
7
|
require "socket"
|
12
|
-
require_relative "./tcp_oracle.rb"
|
13
8
|
|
14
9
|
@hostname = '54.165.60.84'
|
15
10
|
@port = 80
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crypto-toolbox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dennis Sivia
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aes
|
@@ -57,11 +57,10 @@ files:
|
|
57
57
|
- lib/crypto-toolbox/analyzers/cbc_mac.rb
|
58
58
|
- lib/crypto-toolbox/analyzers/cbc_mac/variable_length/analyzer.rb
|
59
59
|
- lib/crypto-toolbox/analyzers/cbc_mac/variable_length/oracles/tcp.rb
|
60
|
+
- lib/crypto-toolbox/analyzers/cbc_mutating_encryption.rb
|
60
61
|
- lib/crypto-toolbox/analyzers/ecb_string_appender.rb
|
61
62
|
- lib/crypto-toolbox/analyzers/padding_oracle.rb
|
62
63
|
- lib/crypto-toolbox/analyzers/padding_oracle/analyzer.rb
|
63
|
-
- lib/crypto-toolbox/analyzers/padding_oracle/oracles/http_oracle.rb
|
64
|
-
- lib/crypto-toolbox/analyzers/padding_oracle/oracles/tcp_oracle.rb
|
65
64
|
- lib/crypto-toolbox/analyzers/utils/ascii_language_detector.rb
|
66
65
|
- lib/crypto-toolbox/analyzers/utils/human_language_detector.rb
|
67
66
|
- lib/crypto-toolbox/analyzers/utils/key_candidate_map.rb
|
@@ -86,7 +85,12 @@ files:
|
|
86
85
|
- lib/crypto-toolbox/forgers/stream_ciphers/forge_generator.rb
|
87
86
|
- lib/crypto-toolbox/matasano/sets/set1.rb
|
88
87
|
- lib/crypto-toolbox/matasano/sets/set2.rb
|
88
|
+
- lib/crypto-toolbox/matasano/sets/set3.rb
|
89
89
|
- lib/crypto-toolbox/matasano/solver.rb
|
90
|
+
- lib/crypto-toolbox/oracles/cbc_mutating_encryption_oracle.rb
|
91
|
+
- lib/crypto-toolbox/oracles/padding_oracle/http_oracle.rb
|
92
|
+
- lib/crypto-toolbox/oracles/padding_oracle/memory_oracle.rb
|
93
|
+
- lib/crypto-toolbox/oracles/padding_oracle/tcp_oracle.rb
|
90
94
|
- lib/crypto-toolbox/oracles/user_profile_encryption_oracle.rb
|
91
95
|
- lib/crypto-toolbox/utils/ecb_detector.rb
|
92
96
|
- lib/crypto-toolbox/utils/ecb_oracle.rb
|
@@ -112,7 +116,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
116
|
version: '0'
|
113
117
|
requirements: []
|
114
118
|
rubyforge_project:
|
115
|
-
rubygems_version: 2.4.
|
119
|
+
rubygems_version: 2.4.7
|
116
120
|
signing_key:
|
117
121
|
specification_version: 4
|
118
122
|
summary: Toolbox for crypto analysis
|