crypto-toolbox 0.2.7 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|