crypto_toolchain 0.1.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.
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