crypto_toolchain 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +51 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +3 -0
  6. data/Guardfile +15 -0
  7. data/LICENSE +21 -0
  8. data/README.md +95 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/crypto_toolchain.gemspec +33 -0
  13. data/exe/crypto +7 -0
  14. data/lib/crypto_toolchain/black_boxes/aes_ctr_editor.rb +25 -0
  15. data/lib/crypto_toolchain/black_boxes/cbc_bitflip_target.rb +33 -0
  16. data/lib/crypto_toolchain/black_boxes/cbc_iv_equals_key_target.rb +35 -0
  17. data/lib/crypto_toolchain/black_boxes/cbc_padding_oracle.rb +44 -0
  18. data/lib/crypto_toolchain/black_boxes/ctr_bitflip_target.rb +32 -0
  19. data/lib/crypto_toolchain/black_boxes/dsa_keypair.rb +50 -0
  20. data/lib/crypto_toolchain/black_boxes/ecb_cut_and_paste_target.rb +50 -0
  21. data/lib/crypto_toolchain/black_boxes/ecb_interpolate_chosen_plaintext_oracle.rb +28 -0
  22. data/lib/crypto_toolchain/black_boxes/ecb_or_cbc_encryptor.rb +47 -0
  23. data/lib/crypto_toolchain/black_boxes/ecb_prepend_chosen_plaintext_oracle.rb +23 -0
  24. data/lib/crypto_toolchain/black_boxes/md4_mac.rb +20 -0
  25. data/lib/crypto_toolchain/black_boxes/mt_19937_stream_cipher.rb +47 -0
  26. data/lib/crypto_toolchain/black_boxes/netcat_cbc_padding_oracle.rb +33 -0
  27. data/lib/crypto_toolchain/black_boxes/rsa_keypair.rb +83 -0
  28. data/lib/crypto_toolchain/black_boxes/rsa_parity_oracle.rb +14 -0
  29. data/lib/crypto_toolchain/black_boxes/rsa_unpadded_message_recovery_oracle.rb +24 -0
  30. data/lib/crypto_toolchain/black_boxes/sha1_mac.rb +20 -0
  31. data/lib/crypto_toolchain/black_boxes.rb +22 -0
  32. data/lib/crypto_toolchain/diffie_hellman/messages.rb +53 -0
  33. data/lib/crypto_toolchain/diffie_hellman/mitm.rb +52 -0
  34. data/lib/crypto_toolchain/diffie_hellman/peer.rb +130 -0
  35. data/lib/crypto_toolchain/diffie_hellman/peer_info.rb +43 -0
  36. data/lib/crypto_toolchain/diffie_hellman/received_message.rb +17 -0
  37. data/lib/crypto_toolchain/diffie_hellman.rb +10 -0
  38. data/lib/crypto_toolchain/extensions/integer_extensions.rb +90 -0
  39. data/lib/crypto_toolchain/extensions/object_extensions.rb +24 -0
  40. data/lib/crypto_toolchain/extensions/string_extensions.rb +263 -0
  41. data/lib/crypto_toolchain/extensions.rb +8 -0
  42. data/lib/crypto_toolchain/srp/client.rb +51 -0
  43. data/lib/crypto_toolchain/srp/framework.rb +55 -0
  44. data/lib/crypto_toolchain/srp/server.rb +38 -0
  45. data/lib/crypto_toolchain/srp/simple_client.rb +32 -0
  46. data/lib/crypto_toolchain/srp/simple_server.rb +68 -0
  47. data/lib/crypto_toolchain/srp.rb +14 -0
  48. data/lib/crypto_toolchain/tools/aes_ctr_recoverer.rb +30 -0
  49. data/lib/crypto_toolchain/tools/cbc_bitflip_attack.rb +30 -0
  50. data/lib/crypto_toolchain/tools/cbc_iv_equals_key_attack.rb +30 -0
  51. data/lib/crypto_toolchain/tools/cbc_padding_oracle_attack.rb +51 -0
  52. data/lib/crypto_toolchain/tools/ctr_bitflip_attack.rb +24 -0
  53. data/lib/crypto_toolchain/tools/determine_blocksize.rb +20 -0
  54. data/lib/crypto_toolchain/tools/dsa_recover_nonce_from_signatures.rb +53 -0
  55. data/lib/crypto_toolchain/tools/dsa_recover_private_key_from_nonce.rb +39 -0
  56. data/lib/crypto_toolchain/tools/ecb_cut_and_paste_attack.rb +47 -0
  57. data/lib/crypto_toolchain/tools/ecb_interpolate_chosen_plaintext_attack.rb +72 -0
  58. data/lib/crypto_toolchain/tools/ecb_prepend_chosen_plaintext_attack.rb +42 -0
  59. data/lib/crypto_toolchain/tools/interactive_xor.rb +51 -0
  60. data/lib/crypto_toolchain/tools/low_exponent_rsa_signature_forgery.rb +27 -0
  61. data/lib/crypto_toolchain/tools/md4_length_extension_attack.rb +30 -0
  62. data/lib/crypto_toolchain/tools/mt_19937_seed_recoverer.rb +27 -0
  63. data/lib/crypto_toolchain/tools/mt_19937_stream_cipher_seed_recoverer.rb +40 -0
  64. data/lib/crypto_toolchain/tools/rsa_broadcast_attack.rb +21 -0
  65. data/lib/crypto_toolchain/tools/rsa_parity_oracle_attack.rb +33 -0
  66. data/lib/crypto_toolchain/tools/rsa_unpadded_message_recovery_attack.rb +49 -0
  67. data/lib/crypto_toolchain/tools/sha1_length_extension_attack.rb +30 -0
  68. data/lib/crypto_toolchain/tools.rb +31 -0
  69. data/lib/crypto_toolchain/utilities/hmac.rb +73 -0
  70. data/lib/crypto_toolchain/utilities/md4.rb +106 -0
  71. data/lib/crypto_toolchain/utilities/mt_19937.rb +218 -0
  72. data/lib/crypto_toolchain/utilities/sha1.rb +95 -0
  73. data/lib/crypto_toolchain/utilities.rb +9 -0
  74. data/lib/crypto_toolchain/version.rb +3 -0
  75. data/lib/crypto_toolchain.rb +34 -0
  76. metadata +232 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5c925134cae022ff1f352dd99a514ed156af2b24
4
+ data.tar.gz: 6da3e5de58817cc75ea75cb0463ccb2230dee7b9
5
+ SHA512:
6
+ metadata.gz: 0dac92e2f29f7c800a15f0e8af6ef46581b9c23564fd73aa90fd80a90239ee67c59f21b8f94c2b588f8533ff9222ecd868e6b3b7ff3e34beab0b45d35044c274
7
+ data.tar.gz: ff82e12216383e5732637bc50fd93a34363972b119f2a9d3094a49076abd1737f025d0dfc48bfefba4941b2d88cd185f5a6fcaeff380a8c817221773aad60121
data/.gitignore ADDED
@@ -0,0 +1,51 @@
1
+ *.gem
2
+ *.rbc
3
+ /.config
4
+ /coverage/
5
+ /InstalledFiles
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /test/tmp/
10
+ /test/version_tmp/
11
+ /tmp/
12
+ Gemfile.lock
13
+
14
+ # Used by dotenv library to load environment variables.
15
+ # .env
16
+
17
+ ## Specific to RubyMotion:
18
+ .dat*
19
+ .repl_history
20
+ build/
21
+ *.bridgesupport
22
+ build-iPhoneOS/
23
+ build-iPhoneSimulator/
24
+
25
+ ## Specific to RubyMotion (use of CocoaPods):
26
+ #
27
+ # We recommend against adding the Pods directory to your .gitignore. However
28
+ # you should judge for yourself, the pros and cons are mentioned at:
29
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
30
+ #
31
+ # vendor/Pods/
32
+
33
+ ## Documentation cache and generated files:
34
+ /.yardoc/
35
+ /_yardoc/
36
+ /doc/
37
+ /rdoc/
38
+
39
+ ## Environment normalization:
40
+ /.bundle/
41
+ /vendor/bundle
42
+ /lib/bundler/man/
43
+
44
+ # for a library or gem, you might want to ignore these files since the code is
45
+ # intended to run in multiple environments; otherwise, check them in:
46
+ # Gemfile.lock
47
+ # .ruby-version
48
+ # .ruby-gemset
49
+
50
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
51
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.3
5
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,15 @@
1
+ guard :rspec, cmd: "bundle exec rspec" do
2
+ require "guard/rspec/dsl"
3
+ dsl = Guard::RSpec::Dsl.new(self)
4
+
5
+ # RSpec files
6
+ rspec = dsl.rspec
7
+ watch(rspec.spec_helper) { rspec.spec_dir }
8
+ watch(rspec.spec_support) { rspec.spec_dir }
9
+ watch(rspec.spec_files)
10
+
11
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
12
+
13
+ ruby = dsl.ruby
14
+ dsl.watch_spec_files_for(ruby.lib_files)
15
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Forrest Fleming
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # CryptoToolchain
2
+
3
+ This is a suite of tools for ruining the blue team's day with respect to crypto.
4
+
5
+ It is mostly based on the Matasano/Cryptopals challenges, because they lead you
6
+ by the hand down the garden path to breaking a good number of common
7
+ cryptographic vulnerabilities.
8
+
9
+ NB: These will probably never be finished
10
+
11
+ ## Cryptopals progress
12
+
13
+ ### Set 1: Basics
14
+ * [x] Convert hex to base64
15
+ * [x] Fixed XOR
16
+ * [x] Single-byte XOR cipher
17
+ * [x] Detect single-character XOR
18
+ * [x] Implement repeating-key XOR
19
+ * [x] Break repeating-key XOR
20
+ * [x] AES in ECB mode
21
+ * [x] Detect AES in ECB mode
22
+
23
+ ### Set 2: Block crypto
24
+ * [x] Implement PKCS#7 padding
25
+ * [x] Implement CBC mode
26
+ * [x] An ECB/CBC detection oracle
27
+ * [x] Byte-at-a-time ECB decryption (Simple)
28
+ * [x] ECB cut-and-paste
29
+ * [x] Byte-at-a-time ECB decryption (Harder)
30
+ * [x] PKCS#7 padding validation
31
+ * [x] CBC bitflipping attacks
32
+
33
+ ### Set 3: Block & stream crypto
34
+ * [x] The CBC padding oracle
35
+ * [x] Implement CTR, the stream cipher mode
36
+ * [x] Break fixed-nonce CTR mode using substitutions
37
+ * [x] Break fixed-nonce CTR statistically
38
+ * [x] Implement the MT19937 Mersenne Twister RNG
39
+ * [x] Crack an MT19937 seed
40
+ * [x] Clone an MT19937 RNG from its output
41
+ * [x] Create the MT19937 stream cipher and break it
42
+
43
+ ### Set 4: Stream crypto & randomness
44
+ * [x] Break "random access read/write" AES CTR
45
+ * [x] CTR bitflipping
46
+ * [x] Recover the key from CBC with IV=Key
47
+ * [x] Implement a SHA-1 keyed MAC
48
+ * [x] Break a SHA-1 keyed MAC using length extension
49
+ * [x] Break an MD4 keyed MAC using length extension
50
+ * [x] Implement and break HMAC-SHA1 with an artificial timing leak
51
+ * See [timing_attack](https://github.com/ffleming/timing_attack) for a timing attack tool
52
+ * See [camelflage](https://github.com/ffleming/camelflage) for the vulnerable server
53
+ * [x] Break HMAC-SHA1 with a slightly less artificial timing leak
54
+ * See [timing_attack](https://github.com/ffleming/timing_attack) for a timing attack tool
55
+ * See [camelflage](https://github.com/ffleming/camelflage) for the vulnerable server
56
+
57
+ ### Set 5: Diffie-Hellman & friends
58
+ * [x] Implement Diffie-Hellman
59
+ * [x] Implement a MITM key-fixing attack on Diffie-Hellman with parameter injection
60
+ * [x] Implement DH with negotiated groups, and break with malicious "g" parameters
61
+ * [x] Implement Secure Remote Password (SRP)
62
+ * [x] Break SRP with a zero key
63
+ * [x] Offline dictionary attack on simplified SRP
64
+ * [x] Implement RSA
65
+ * [x] Implement an E=3 RSA Broadcast attack
66
+
67
+ ### Set 6: RSA & DSA
68
+ * [x] Implement unpadded message recovery oracle
69
+ * [x] Bleichenbacher's e=3 RSA Attack
70
+ * [x] DSA key recovery from nonce
71
+ * [x] DSA nonce recovery from repeated nonce
72
+ * [x] DSA parameter tampering
73
+ * [x] RSA parity oracle
74
+ * [ ] Bleichenbacher's PKCS 1.5 Padding Oracle (Simple Case)
75
+ * [ ] Bleichenbacher's PKCS 1.5 Padding Oracle (Complete Case)
76
+
77
+ ### Set 7: Hashes
78
+ * [ ] CBC-MAC Message Forgery
79
+ * [ ] Hashing with CBC-MAC
80
+ * [ ] Compression Ratio Side-Channel Attacks
81
+ * [ ] Iterated Hash Function Multicollisions
82
+ * [ ] Kelsey and Schneier's Expandable Messages
83
+ * [ ] Kelsey and Kohno's Nostradamus Attack
84
+ * [ ] MD4 Collisions
85
+ * [ ] RC4 Single-Byte Biases
86
+
87
+ ### Set 8: Abstract Algebra
88
+ * [ ] Diffie-Hellman Revisited: Small Subgroup Confinement
89
+ * [ ] Pollard's Method for Catching Kangaroos
90
+ * [ ] Elliptic Curve Diffie-Hellman and Invalid-Curve Attacks
91
+ * [ ] Single-Coordinate Ladders and Insecure Twists
92
+ * [ ] Duplicate-Signature Key Selection in ECDSA (and RSA)
93
+ * [ ] Key-Recovery Attacks on ECDSA with Biased Nonces
94
+ * [ ] Key-Recovery Attacks on GCM with Repeated Nonces
95
+ * [ ] Key-Recovery Attacks on GCM with a Truncated MAC
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "crypto_toolchain"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ require "pry"
11
+ Pry.start
12
+
13
+ # require "irb"
14
+ # IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'crypto_toolchain/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "crypto_toolchain"
8
+ spec.version = CryptoToolchain::VERSION
9
+ spec.authors = ["Forrest Fleming"]
10
+ spec.email = ["ffleming@gmail.com"]
11
+
12
+ spec.summary = "Crypto toolchain for CTFs and so on"
13
+ spec.description = "A toolchain for manipulating data in a variety of cryptographic " <<
14
+ "and quasi-cryptographic ways."
15
+ spec.homepage = "https://github.com/ffleming/crypto_toolchain"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ spec.licenses = ["MIT"]
24
+
25
+ spec.add_runtime_dependency "pry-byebug", "3.4"
26
+ spec.add_runtime_dependency "openssl", "~> 2.0"
27
+ spec.add_runtime_dependency "bigdecimal", "~> 1.2"
28
+ spec.add_development_dependency "bundler", "~> 1.13"
29
+ spec.add_development_dependency "guard-rspec", "~> 4.7"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "rspec", "~> 3.0"
32
+ spec.add_development_dependency "simplecov", "~> 0.15"
33
+ end
data/exe/crypto ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "crypto_toolchain"
5
+
6
+ require "pry"
7
+ Pry.start
@@ -0,0 +1,25 @@
1
+ module CryptoToolchain
2
+ module BlackBoxes
3
+ class AesCtrEditor
4
+ def initialize(plaintext, key: Random.new.bytes(16), nonce: rand(0..0x0000FF))
5
+ @plaintext = plaintext
6
+ @key = key
7
+ @nonce = nonce
8
+ @ciphertext = plaintext.encrypt_ctr(key: key, nonce: nonce)
9
+ end
10
+
11
+ # Offset is in bytes
12
+ # Does not mutate @ciphetext or @plaintext
13
+ def edit(offset: ,with: )
14
+ previous = ciphertext[0...offset]
15
+ after = ciphertext[(offset + with.bytesize)..-1]
16
+ edited = with.encrypt_ctr(nonce: nonce,
17
+ key: key,
18
+ start_counter: offset)
19
+ previous + edited + after
20
+ end
21
+
22
+ attr_reader :plaintext, :key, :nonce, :ciphertext
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,33 @@
1
+ # encoding; ASCII-8BIT
2
+ module CryptoToolchain
3
+ module BlackBoxes
4
+ class CbcBitflipTarget
5
+ def initialize(key: Random.new.bytes(16), iv: Random.new.bytes(16))
6
+ @key = key
7
+ @iv = iv
8
+ end
9
+
10
+ def encrypt(input)
11
+ str = prefix + input.gsub(/;|=/, "") + suffix
12
+ str.encrypt_cbc(key: key, blocksize: 16, iv: iv)
13
+ end
14
+
15
+ def is_admin?(crypted)
16
+ dec = crypted.decrypt_cbc(key: key, blocksize: 16, iv: iv)
17
+ dec.include?(";admin=true;")
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :key, :iv
23
+
24
+ def prefix
25
+ "comment1=cooking%20MCs;userdata="
26
+ end
27
+
28
+ def suffix
29
+ ";comment2=%20like%20a%20pound%20of%20bacon"
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ # encoding; ASCII-8BIT
2
+ module CryptoToolchain
3
+ module BlackBoxes
4
+ class CbcIvEqualsKeyTarget
5
+ def initialize(key: Random.new.bytes(16))
6
+ @key = key
7
+ end
8
+
9
+ def encrypt(input)
10
+ str = prefix + input.gsub(/;|=/, "") + suffix
11
+ str.encrypt_cbc(key: key, blocksize: 16, iv: key)
12
+ end
13
+
14
+ def is_admin?(crypted)
15
+ dec = crypted.decrypt_cbc(key: key, blocksize: 16, iv: key)
16
+ dec.each_byte do |byte|
17
+ raise RuntimeError.new("Invalid byte in #{dec}") if byte > '~'.ord
18
+ end
19
+ dec.include?(";admin=true;")
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :key
25
+
26
+ def prefix
27
+ "comment1=cooking%20MCs;userdata="
28
+ end
29
+
30
+ def suffix
31
+ ";comment2=%20like%20a%20pound%20of%20bacon"
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ module CryptoToolchain
2
+ module BlackBoxes
3
+ class CbcPaddingOracle
4
+
5
+ attr_reader :ciphertext, :plaintext
6
+
7
+ def initialize(key: Random.new.bytes(16), iv: Random.new.bytes(16))
8
+ @key = key
9
+ @iv = iv
10
+ @ciphertext = text.encrypt_cbc(key: key, iv: iv, blocksize: 16)
11
+ @plaintext = text
12
+ end
13
+
14
+ def execute(str)
15
+ begin
16
+ !!str.
17
+ decrypt_cbc(key: key, iv: iv, blocksize: 16, strip_padding: false).
18
+ without_pkcs7_padding(16, raise_error: true)
19
+ rescue ArgumentError
20
+ false
21
+ end
22
+ end
23
+
24
+ private
25
+
26
+ attr_reader :key, :iv
27
+
28
+ def text
29
+ @text ||= %w(
30
+ MDAwMDAwTm93IHRoYXQgdGhlIHBhcnR5IGlzIGp1bXBpbmc=
31
+ MDAwMDAxV2l0aCB0aGUgYmFzcyBraWNrZWQgaW4gYW5kIHRoZSBWZWdhJ3MgYXJlIHB1bXBpbic=
32
+ MDAwMDAyUXVpY2sgdG8gdGhlIHBvaW50LCB0byB0aGUgcG9pbnQsIG5vIGZha2luZw==
33
+ MDAwMDAzQ29va2luZyBNQydzIGxpa2UgYSBwb3VuZCBvZiBiYWNvbg==
34
+ MDAwMDA0QnVybmluZyAnZW0sIGlmIHlvdSBhaW4ndCBxdWljayBhbmQgbmltYmxl
35
+ MDAwMDA1SSBnbyBjcmF6eSB3aGVuIEkgaGVhciBhIGN5bWJhbA==
36
+ MDAwMDA2QW5kIGEgaGlnaCBoYXQgd2l0aCBhIHNvdXBlZCB1cCB0ZW1wbw==
37
+ MDAwMDA3SSdtIG9uIGEgcm9sbCwgaXQncyB0aW1lIHRvIGdvIHNvbG8=
38
+ MDAwMDA4b2xsaW4nIGluIG15IGZpdmUgcG9pbnQgb2g=
39
+ MDAwMDA5aXRoIG15IHJhZy10b3AgZG93biBzbyBteSBoYWlyIGNhbiBibG93
40
+ ).map(&:from_base64).sample
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,32 @@
1
+ # encoding; ASCII-8BIT
2
+ module CryptoToolchain
3
+ module BlackBoxes
4
+ class CtrBitflipTarget
5
+ def initialize(key: Random.new.bytes(16), nonce: rand(0..0x0000FFFF))
6
+ @key = key
7
+ @nonce = nonce
8
+ end
9
+
10
+ def encrypt(input)
11
+ str = prefix + input.gsub(/;|=/, "") + suffix
12
+ str.encrypt_ctr(key: key, nonce: nonce)
13
+ end
14
+
15
+ def is_admin?(crypted)
16
+ crypted.decrypt_ctr(key: key, nonce: nonce).include?(";admin=true;")
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :key, :nonce
22
+
23
+ def prefix
24
+ "comment1=cooking%20MCs;userdata="
25
+ end
26
+
27
+ def suffix
28
+ ";comment2=%20like%20a%20pound%20of%20bacon"
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,50 @@
1
+ module CryptoToolchain
2
+ module BlackBoxes
3
+ class DSAKeypair
4
+ def initialize(p: DSA_P, q: DSA_Q, g: DSA_G, private_key: nil, dangerous: false)
5
+ @p = p
6
+ @q = q
7
+ @g = g
8
+ @private_key = numberize(private_key) unless private_key.nil?
9
+ @safe = !dangerous
10
+ end
11
+
12
+ attr_reader :p, :q, :g, :safe
13
+
14
+ def sign(m, k: nil)
15
+ r = s = 0
16
+ k ||= rand(2...q)
17
+ loop do
18
+ r = g.modpow(k, p) % q
19
+ next if safe && r == 0
20
+ digest = CryptoToolchain::Utilities::SHA1.digest(m).to_number
21
+ s = k.modinv(q) * ( digest + (private_key * r)) % q
22
+ next if safe && s == 0
23
+ return [r.to_bin_string, s.to_bin_string]
24
+ end
25
+ end
26
+
27
+ def verify(m, r: , s: , public_key: self.public_key)
28
+ s = s.to_number
29
+ r = r.to_number
30
+ if safe && !(0 < r && r < q) && (0 < s && s < q)
31
+ return false
32
+ end
33
+ w = s.invmod(q)
34
+ u_1 = (CryptoToolchain::Utilities::SHA1.digest(m).to_number * w) % q
35
+ u_2 = (r * w) % q
36
+ # a*b % n = [(a % n) * (b % n)] % m
37
+ v = ((g.modpow(u_1, p) * public_key.modpow(u_2, p)) % p) % q
38
+ v == r
39
+ end
40
+
41
+ def private_key
42
+ @private_key ||= rand(1..DSA_Q)
43
+ end
44
+
45
+ def public_key
46
+ @public_key ||= g.modpow(private_key, p)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: ASCII-8BIT
2
+ class Hash
3
+ def symbolize_keys
4
+ map do |k, v|
5
+ [k.to_sym, v]
6
+ end.to_h
7
+ end
8
+ end
9
+
10
+ module CryptoToolchain
11
+ module BlackBoxes
12
+ class EcbCutAndPasteTarget
13
+ def initialize(key: String.random_bytes(16))
14
+ @key = key
15
+ end
16
+
17
+ def cookie_for(email)
18
+ {
19
+ email: email.gsub(/&|=/, ""),
20
+ uid: 10,
21
+ role: "user"
22
+ }.each_with_object([]) do |(k, v), memo|
23
+ memo << "#{k}=#{v}"
24
+ end.join("&")
25
+ end
26
+ alias_method :profile_for, :cookie_for
27
+
28
+ def encrypted_profile_for(email)
29
+ profile_for(email).encrypt_ecb(key: key, blocksize: 16)
30
+ end
31
+ alias_method :encrypt, :encrypted_profile_for
32
+
33
+ def decrypt(enc)
34
+ enc.
35
+ decrypt_ecb(key: key, blocksize: 16).
36
+ split("&").
37
+ map do |str|
38
+ k, v = str.split("=")
39
+ [k, v || ""]
40
+ end.
41
+ to_h.
42
+ symbolize_keys
43
+ end
44
+
45
+ private
46
+
47
+ attr_reader :key
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,28 @@
1
+ # encoding: ASCII-8BIT
2
+ module CryptoToolchain
3
+ module BlackBoxes
4
+ class EcbInterpolateChosenPlaintextOracle
5
+ MYSTERY_TEXT = "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK"
6
+
7
+ def initialize(key: String.random_bytes(16))
8
+ @key = key
9
+ end
10
+
11
+ def encrypt(plaintext)
12
+ obfuscate(plaintext).encrypt_ecb(key: key, blocksize: 16)
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :key
18
+
19
+ def obfuscate(str)
20
+ "#{prefix}#{str}#{MYSTERY_TEXT.from_base64}"
21
+ end
22
+
23
+ def prefix
24
+ @prefix ||= String.random_bytes(rand(1..64))
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,47 @@
1
+ module CryptoToolchain
2
+ module BlackBoxes
3
+ class EcbOrCbcEncryptor
4
+ ENCRYPTION_ALGORITHMS = %i(ebc cbc).freeze
5
+ attr_reader :key, :plaintext
6
+
7
+ def initialize(plaintext, algorithm: random_algorithm)
8
+ raise ArgumentError.new("Unsupported algorithm #{algorithm}") unless ENCRYPTION_ALGORITHMS.include? algorithm
9
+ @plaintext = plaintext
10
+ @key = String.random_bytes(16)
11
+ @algorithm = algorithm
12
+ end
13
+
14
+ def encrypt(_algo = algorithm)
15
+ case _algo
16
+ when :ecb
17
+ encrypt_ecb
18
+ when :cbc
19
+ encrypt_cbc
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def obfuscate(text)
26
+ append_len = (rand(5..10))
27
+ prepend_len = (rand(5..10))
28
+ "#{String.random_bytes(append_len)}#{text}#{String.random_bytes(prepend_len)}"
29
+ end
30
+
31
+ def encrypt_ecb
32
+ obfuscate(plaintext).encrypt_ecb(key: key, blocksize: 16)
33
+ end
34
+
35
+ def encrypt_cbc
36
+ obfuscate(plaintext).encrypt_cbc(key: key,
37
+ iv: String.random_bytes(16),
38
+ blocksize: 16)
39
+ end
40
+
41
+ def random_algorithm
42
+ ENCRYPTION_ALGORITHMS[rand(2)]
43
+ end
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,23 @@
1
+ # encoding: ASCII-8BIT
2
+ module CryptoToolchain
3
+ module BlackBoxes
4
+ class EcbPrependChosenPlaintextOracle
5
+ MYSTERY_TEXT = "Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK"
6
+ def initialize(key: String.random_bytes(16))
7
+ @key = key
8
+ end
9
+
10
+ def encrypt(plaintext)
11
+ obfuscate(plaintext).encrypt_ecb(key: key, blocksize: 16)
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :key
17
+
18
+ def obfuscate(str)
19
+ "#{str}#{MYSTERY_TEXT.from_base64}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,20 @@
1
+ module CryptoToolchain
2
+ module BlackBoxes
3
+ class MD4Mac
4
+ attr_reader :key
5
+
6
+ def initialize(key: Random.new.bytes(16))
7
+ @key = key
8
+ end
9
+
10
+ def mac(str)
11
+ concat = key + str
12
+ CryptoToolchain::Utilities::MD4.hexdigest(concat)
13
+ end
14
+
15
+ def valid?(message: , mac: )
16
+ self.mac(message) == mac
17
+ end
18
+ end
19
+ end
20
+ end