crypto_toolchain 0.1.1 → 0.2.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 +5 -5
- data/.gitignore +2 -0
- data/.travis.yml +1 -0
- data/README.md +6 -2
- data/lib/crypto_toolchain/black_boxes/rsa_keypair.rb +22 -9
- data/lib/crypto_toolchain/black_boxes/rsa_padding_oracle.rb +17 -0
- data/lib/crypto_toolchain/black_boxes.rb +1 -0
- data/lib/crypto_toolchain/extensions/integer_extensions.rb +9 -0
- data/lib/crypto_toolchain/extensions/string_extensions.rb +14 -3
- data/lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb +124 -0
- data/lib/crypto_toolchain/tools.rb +1 -0
- data/lib/crypto_toolchain/version.rb +1 -1
- data/lib/crypto_toolchain.rb +1 -0
- metadata +5 -4
- data/.rspec +0 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: abf3eb1ea6db35f164ee955e811d817ce4a54ce5f8dbfb7c26622662fe15b7ac
|
|
4
|
+
data.tar.gz: f65fe236e0594960033508c94570cb147fbda144db077570e946e0733282e062
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7db6ff7adb0b11efd29a5fd987f71e1517d6be8509007f4092bcef3e74076c907ef6f59a3b3f98b84b589563611a85882d89a12cee7ed4c30d972753c5457f5e
|
|
7
|
+
data.tar.gz: a1632d18cab50cc48228ce4394f3edefc923eb7e692ba213ad9acce2ab0d3a7a7d91127f9dcb7168ae3fc279ac6eba47c4798dd77bdd9a58fdc3f73a48871718
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](https://travis-ci.org/ffleming/crypto_toolchain)
|
|
2
|
+
|
|
1
3
|
# CryptoToolchain
|
|
2
4
|
|
|
3
5
|
This is a suite of tools for ruining the blue team's day with respect to crypto.
|
|
@@ -8,6 +10,8 @@ cryptographic vulnerabilities.
|
|
|
8
10
|
|
|
9
11
|
NB: These will probably never be finished
|
|
10
12
|
|
|
13
|
+
Add `--tag ~slow` to your `.rspec` file if you don't want to run slow tests.
|
|
14
|
+
|
|
11
15
|
## Cryptopals progress
|
|
12
16
|
|
|
13
17
|
### Set 1: Basics
|
|
@@ -71,8 +75,8 @@ NB: These will probably never be finished
|
|
|
71
75
|
* [x] DSA nonce recovery from repeated nonce
|
|
72
76
|
* [x] DSA parameter tampering
|
|
73
77
|
* [x] RSA parity oracle
|
|
74
|
-
* [
|
|
75
|
-
* [
|
|
78
|
+
* [x] Bleichenbacher's PKCS 1.5 Padding Oracle (Simple Case)
|
|
79
|
+
* [x] Bleichenbacher's PKCS 1.5 Padding Oracle (Complete Case)
|
|
76
80
|
|
|
77
81
|
### Set 7: Hashes
|
|
78
82
|
* [ ] CBC-MAC Message Forgery
|
|
@@ -5,17 +5,17 @@ module CryptoToolchain
|
|
|
5
5
|
PrivateKey = Struct.new(:d, :n)
|
|
6
6
|
PublicKey = Struct.new(:e, :n)
|
|
7
7
|
|
|
8
|
-
def initialize(bits: 1024)
|
|
8
|
+
def initialize(bits: 1024, p: nil, q: nil)
|
|
9
9
|
@bits = bits
|
|
10
|
-
@p = OpenSSL::BN::generate_prime(bits/2).to_i
|
|
11
|
-
@q = OpenSSL::BN::generate_prime(bits/2).to_i
|
|
10
|
+
@p = p || OpenSSL::BN::generate_prime(bits/2).to_i
|
|
11
|
+
@q = q || OpenSSL::BN::generate_prime(bits/2).to_i
|
|
12
12
|
@n = @p * @q
|
|
13
13
|
et = (@p-1) * (@q-1)
|
|
14
14
|
@e = 3
|
|
15
15
|
@d = @e.invmod(et)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
attr_reader :e, :bits
|
|
18
|
+
attr_reader :e, :bits, :p, :q
|
|
19
19
|
|
|
20
20
|
def encrypt(m, to: )
|
|
21
21
|
raise ArgumentError.new("Message should be a string") unless m.is_a?(String)
|
|
@@ -25,12 +25,17 @@ module CryptoToolchain
|
|
|
25
25
|
to_bin_string
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
-
def decrypt(m)
|
|
28
|
+
def decrypt(m, pad: false)
|
|
29
29
|
raise ArgumentError.new("Message should be a string") unless m.is_a?(String)
|
|
30
|
-
m.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
decrypted = m.
|
|
31
|
+
to_number.
|
|
32
|
+
modpow(private_key.d, private_key.n).
|
|
33
|
+
to_bin_string
|
|
34
|
+
if pad
|
|
35
|
+
pad_to_key_size(decrypted)
|
|
36
|
+
else
|
|
37
|
+
decrypted
|
|
38
|
+
end
|
|
34
39
|
end
|
|
35
40
|
|
|
36
41
|
def sign(plaintext)
|
|
@@ -78,6 +83,14 @@ module CryptoToolchain
|
|
|
78
83
|
sha512: "0Q0\r\x06\t`\x86H\x01e\x03\x04\x02\x03\x05\x00\x04@"
|
|
79
84
|
}.fetch(hash_type)
|
|
80
85
|
end
|
|
86
|
+
|
|
87
|
+
def pad_to_key_size(str)
|
|
88
|
+
padded = str.dup
|
|
89
|
+
while padded.bytesize < bits / 8
|
|
90
|
+
padded = "\x00#{padded}"
|
|
91
|
+
end
|
|
92
|
+
padded
|
|
93
|
+
end
|
|
81
94
|
end
|
|
82
95
|
end
|
|
83
96
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module CryptoToolchain
|
|
2
|
+
module BlackBoxes
|
|
3
|
+
class RSAPaddingOracle
|
|
4
|
+
def initialize(keypair: CryptoToolchain::BlackBoxes::RSAKeypair.new(bits: 256))
|
|
5
|
+
@keypair = keypair
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
attr_reader :keypair
|
|
9
|
+
|
|
10
|
+
def execute(str)
|
|
11
|
+
keypair.
|
|
12
|
+
decrypt(str, pad: true).
|
|
13
|
+
is_pkcs1_5_padded?(keypair.bits)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -15,6 +15,7 @@ require "crypto_toolchain/black_boxes/rsa_keypair"
|
|
|
15
15
|
require "crypto_toolchain/black_boxes/rsa_unpadded_message_recovery_oracle"
|
|
16
16
|
require "crypto_toolchain/black_boxes/rsa_parity_oracle"
|
|
17
17
|
require "crypto_toolchain/black_boxes/dsa_keypair"
|
|
18
|
+
require "crypto_toolchain/black_boxes/rsa_padding_oracle"
|
|
18
19
|
|
|
19
20
|
module CryptoToolchain
|
|
20
21
|
module BlackBoxes
|
|
@@ -123,10 +123,21 @@ class String
|
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
125
|
|
|
126
|
+
def pad_pkcs1_5(bits)
|
|
127
|
+
len = bits / 8
|
|
128
|
+
if self.bytesize > len - 11
|
|
129
|
+
raise ArgumentError.new("String #{self.inspect} is too long to pad with PKCS#1v1.5, length: #{self.bytesize}")
|
|
130
|
+
end
|
|
131
|
+
padstring = (len - 3 - self.bytesize).times.with_object("") { |_, memo| memo << rand(1..255).chr }
|
|
132
|
+
"\x00\x02#{padstring}\x00#{self}"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def is_pkcs1_5_padded?(bits)
|
|
136
|
+
self[0..1] == "\x00\x02"
|
|
137
|
+
end
|
|
138
|
+
|
|
126
139
|
def is_pkcs7_padded?(blocksize = CryptoToolchain::AES_BLOCK_SIZE)
|
|
127
|
-
|
|
128
|
-
return in_blocks(blocksize).last.is_block_pkcs7_padded?(blocksize)
|
|
129
|
-
# end
|
|
140
|
+
return in_blocks(blocksize).last.is_block_pkcs7_padded?(blocksize)
|
|
130
141
|
end
|
|
131
142
|
|
|
132
143
|
def without_pkcs7_padding(blocksize = CryptoToolchain::AES_BLOCK_SIZE, raise_error: false)
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# encoding: ASCII-8BIT
|
|
2
|
+
module CryptoToolchain
|
|
3
|
+
module Tools
|
|
4
|
+
class RSAPaddingOracleAttack
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
class CryptoToolchain::Tools::RSAPaddingOracleAttack
|
|
10
|
+
def initialize(oracle: BlackBoxes::RSAPaddingOracle.new, n: , e: 3)
|
|
11
|
+
@oracle = oracle
|
|
12
|
+
@n = n
|
|
13
|
+
@e = e
|
|
14
|
+
end
|
|
15
|
+
attr_reader :n, :oracle, :e
|
|
16
|
+
|
|
17
|
+
def check(int)
|
|
18
|
+
oracle.execute(str_for(int))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def str_for(int)
|
|
22
|
+
str = int.to_bin_string
|
|
23
|
+
pad = "\x00" * (n.bit_length.updiv(8) - str.bytesize)
|
|
24
|
+
"#{pad}#{str}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def execute(ciphertext)
|
|
28
|
+
s = 1
|
|
29
|
+
@c0 = ciphertext.to_number
|
|
30
|
+
intervals = [ [ (2*big_b), (3*big_b ) ] ]
|
|
31
|
+
i = 1
|
|
32
|
+
loop do
|
|
33
|
+
if i == 1
|
|
34
|
+
#2a
|
|
35
|
+
s = start_search()
|
|
36
|
+
elsif intervals.length > 1
|
|
37
|
+
#2b
|
|
38
|
+
s += 1
|
|
39
|
+
s += 1 until check((@c0 * s.modpow(e, n)) % n)
|
|
40
|
+
elsif intervals.length == 1
|
|
41
|
+
#2c
|
|
42
|
+
a, b = intervals.first
|
|
43
|
+
|
|
44
|
+
if a == b
|
|
45
|
+
return str_for(a)
|
|
46
|
+
end
|
|
47
|
+
s = search_with_single_interval(a, b, s)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# 3
|
|
51
|
+
intervals = calculate_intervals(intervals, s)
|
|
52
|
+
i += 1
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def calculate_intervals(intervals, s)
|
|
58
|
+
new_intervals = []
|
|
59
|
+
intervals.each do |a, b|
|
|
60
|
+
min_r = (a * s - 3 * big_b + 1).updiv(n)
|
|
61
|
+
max_r = (b * s - 2 * big_b) / n
|
|
62
|
+
(min_r..max_r).each do |r|
|
|
63
|
+
aa = [a, (2 * big_b + r * n).updiv(s)].max
|
|
64
|
+
bb = [b, ((3 * big_b - 1 + r * n) / s)].min
|
|
65
|
+
|
|
66
|
+
new_intervals = add_interval(new_intervals, aa, bb)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
new_intervals
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def add_interval(intervals, lower, upper)
|
|
73
|
+
matched = false
|
|
74
|
+
new_intervals = intervals.map do |a, b|
|
|
75
|
+
if b < lower || a > upper
|
|
76
|
+
# interval to be added does not overlap an existing interval - persist the existing interval
|
|
77
|
+
# if we never overlap an interval, we'll add the [lower, upper] interval later
|
|
78
|
+
[a, b]
|
|
79
|
+
else
|
|
80
|
+
# interval to be added overlaps - extend that interval according to [lower, upper]
|
|
81
|
+
matched = true
|
|
82
|
+
[
|
|
83
|
+
[lower, a].min,
|
|
84
|
+
[upper, b].max
|
|
85
|
+
]
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
if matched
|
|
89
|
+
new_intervals
|
|
90
|
+
else
|
|
91
|
+
new_intervals.push([lower, upper])
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def start_search
|
|
96
|
+
s1 = n.updiv(3 * big_b)
|
|
97
|
+
loop do
|
|
98
|
+
c = (@c0 * s1.modpow(e, n)) % n
|
|
99
|
+
if check(c)
|
|
100
|
+
return s1
|
|
101
|
+
end
|
|
102
|
+
s1 += 1
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def search_with_single_interval(a, b, s)
|
|
107
|
+
r = (2 * (b * s - 2 * big_b)) / (n)
|
|
108
|
+
s = (2 * big_b + r * n) / (b)
|
|
109
|
+
|
|
110
|
+
until check((@c0 * s.modpow(e,n)) % n)
|
|
111
|
+
s += 1
|
|
112
|
+
if s > (3 * big_b + r * n) / a
|
|
113
|
+
r += 1
|
|
114
|
+
s = (2 * big_b + r * n) / b
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
s
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def big_b
|
|
121
|
+
k = oracle.keypair.bits / 8
|
|
122
|
+
2**(8 * (k - 2))
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -18,6 +18,7 @@ require "crypto_toolchain/tools/low_exponent_rsa_signature_forgery"
|
|
|
18
18
|
require "crypto_toolchain/tools/dsa_recover_private_key_from_nonce"
|
|
19
19
|
require "crypto_toolchain/tools/dsa_recover_nonce_from_signatures"
|
|
20
20
|
require "crypto_toolchain/tools/rsa_parity_oracle_attack"
|
|
21
|
+
require "crypto_toolchain/tools/rsa_padding_oracle_attack"
|
|
21
22
|
|
|
22
23
|
module CryptoToolchain
|
|
23
24
|
module Tools
|
data/lib/crypto_toolchain.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: crypto_toolchain
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Forrest Fleming
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2018-06-16 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: pry-byebug
|
|
@@ -132,7 +132,6 @@ extensions: []
|
|
|
132
132
|
extra_rdoc_files: []
|
|
133
133
|
files:
|
|
134
134
|
- ".gitignore"
|
|
135
|
-
- ".rspec"
|
|
136
135
|
- ".travis.yml"
|
|
137
136
|
- Gemfile
|
|
138
137
|
- Guardfile
|
|
@@ -159,6 +158,7 @@ files:
|
|
|
159
158
|
- lib/crypto_toolchain/black_boxes/mt_19937_stream_cipher.rb
|
|
160
159
|
- lib/crypto_toolchain/black_boxes/netcat_cbc_padding_oracle.rb
|
|
161
160
|
- lib/crypto_toolchain/black_boxes/rsa_keypair.rb
|
|
161
|
+
- lib/crypto_toolchain/black_boxes/rsa_padding_oracle.rb
|
|
162
162
|
- lib/crypto_toolchain/black_boxes/rsa_parity_oracle.rb
|
|
163
163
|
- lib/crypto_toolchain/black_boxes/rsa_unpadded_message_recovery_oracle.rb
|
|
164
164
|
- lib/crypto_toolchain/black_boxes/sha1_mac.rb
|
|
@@ -196,6 +196,7 @@ files:
|
|
|
196
196
|
- lib/crypto_toolchain/tools/mt_19937_seed_recoverer.rb
|
|
197
197
|
- lib/crypto_toolchain/tools/mt_19937_stream_cipher_seed_recoverer.rb
|
|
198
198
|
- lib/crypto_toolchain/tools/rsa_broadcast_attack.rb
|
|
199
|
+
- lib/crypto_toolchain/tools/rsa_padding_oracle_attack.rb
|
|
199
200
|
- lib/crypto_toolchain/tools/rsa_parity_oracle_attack.rb
|
|
200
201
|
- lib/crypto_toolchain/tools/rsa_unpadded_message_recovery_attack.rb
|
|
201
202
|
- lib/crypto_toolchain/tools/sha1_length_extension_attack.rb
|
|
@@ -225,7 +226,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
225
226
|
version: '0'
|
|
226
227
|
requirements: []
|
|
227
228
|
rubyforge_project:
|
|
228
|
-
rubygems_version: 2.6
|
|
229
|
+
rubygems_version: 2.7.6
|
|
229
230
|
signing_key:
|
|
230
231
|
specification_version: 4
|
|
231
232
|
summary: Crypto toolchain for CTFs and so on
|
data/.rspec
DELETED