bcrypt_pbkdf 1.1.2-x86-mingw32 → 1.2.0.beta1-x86-mingw32

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 313a21f5f1d5f4802bc551f6a56fb10857fcf0d4e158ad298f8ba80f0701ca2c
4
- data.tar.gz: 79d24ad96046208c17435a4a1363d75c0b321c31fca90e570ace307eed61f9eb
3
+ metadata.gz: a7b555abee9e8aa847e4a3989e38a9e2cdfea6db49f92e1342ae7411bc43737c
4
+ data.tar.gz: 5ab435657574e742fb898c03e7e8a4fa552d73d6d998d57d72c2dfdd45a9544e
5
5
  SHA512:
6
- metadata.gz: bd0b06cf79e6b29af0febddd6f881e1966befaf0c4e75767ce900af7bc1317a2c5db94305ccd4a0bde8f5ebc901dc9e141beff0506201f577fa914b6ae2e562b
7
- data.tar.gz: 7edc64e7f41dde6a5e4c14488261aa5beb997c1ea5a7c0811507c194603d140561dc0a2f35a77ee0caa25b1ae3589ca35655c2a96e6fc2a58ae2a897c4ca2e83
6
+ metadata.gz: 43ea19f9b5836938c738bd44d4bd01a2cff96be03dc719a2ebba990e0a093fa1e4adc369f3ec83510a50ad743200720e994573387c71e61dcd21043369e45cd7
7
+ data.tar.gz: a9dffe7bb545038f7f1867e5ded5b070643a3ac06b0aa1f04066c7fe21ad07e003f200409b3e58f750a634ab32fe4aac29436c28ef70187427a0dc49f02adaf2
@@ -46,3 +46,30 @@ jobs:
46
46
  bundler-cache: true
47
47
  - run: bundle exec rake compile
48
48
  - run: bundle exec rake test
49
+
50
+ jruby:
51
+ name: ubuntu-latest ruby jruby
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - uses: actions/checkout@v4
55
+ - uses: ruby/setup-ruby@v1
56
+ with:
57
+ ruby-version: jruby
58
+ bundler-cache: true
59
+ - run: bundle exec rake compile:java
60
+ - run: bundle exec rake test
61
+
62
+ memcheck:
63
+ name: Memory leak check (valgrind)
64
+ runs-on: ubuntu-latest
65
+ env:
66
+ BUNDLE_GEMFILE: Gemfile.memcheck
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+ - uses: ruby/setup-ruby@v1
70
+ with:
71
+ ruby-version: '3.3'
72
+ bundler-cache: true
73
+ - run: sudo apt-get install -y valgrind
74
+ - run: bundle exec rake compile
75
+ - run: bundle exec rake memcheck
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
- lib/
1
+ lib/*.jar
2
+ lib/*.so
2
3
  pkg/
3
4
  tmp/
4
5
  Gemfile.lock
data/CHANGELOG.md CHANGED
@@ -1,3 +1,38 @@
1
- # 1.0.0.apha1
1
+ # 1.2.0.beta1
2
2
 
3
- initial version
3
+ * JRuby support: native Java extension (`-java` gem variant) [#30]
4
+ * Fix: missing salt size cap guard (`saltlen > 1<<20`) in Java implementation to match C behavior [#30]
5
+ * Fix: memory leak on error state in C extension [#34]
6
+ * Sync `bcrypt_pbkdf.c` (v1.13→v1.17) and `blowfish.c` (v1.19→v1.20) from OpenBSD [#36]
7
+ * Sync `blf.h` to OpenBSD v1.8, drop advertising clause [#38]
8
+ * Fix compatibility with minitest 6 [#28]
9
+
10
+ # 1.1.2
11
+
12
+ * Add Ruby 3.4 support [#26]
13
+
14
+ # 1.1.1
15
+
16
+ * Fix cross-compile and native gem publishing [#22]
17
+ * Fix compile on Windows (missing bzero)
18
+ * Replace Travis CI with GitHub Actions
19
+ * Minitest 5.19 compatibility [#21]
20
+
21
+ # 1.1.0
22
+
23
+ * Ruby 3.0 support
24
+ * Support rubies 2.0–2.7 in Windows cross-compile
25
+ * Fix inline static function declarations [#15]
26
+ * Add Linux on Power (ppc64) support [#11]
27
+ * Use size_t for xmalloc [#7]
28
+ * Fix gem summary typo [#9]
29
+
30
+ # 1.0.1
31
+
32
+ * Fix compile on Solarish platforms [#3]
33
+ * Drop rbnacl test dependency, use native OpenSSL instead [#6]
34
+ * Fix spelling in source [#2]
35
+
36
+ # 1.0.0
37
+
38
+ * Initial release
data/Gemfile.memcheck ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'ruby_memcheck'
data/README.md CHANGED
@@ -9,10 +9,19 @@ bcrypt_pbkdf is a ruby gem implementing bcrypt_pbkdf from OpenBSD. This is curre
9
9
  * The gut of the code is based on OpenBSD's bcrypt_pbkdf.c implementation
10
10
  * Some ideas/code were taken adopted bcrypt-ruby: https://github.com/codahale/bcrypt-ruby
11
11
 
12
+ ## Upstream sources
13
+
14
+ The C sources are synced from openssh-portable, which tracks OpenBSD CVS:
15
+
16
+ | File | OpenBSD version |
17
+ |------|----------------|
18
+ | `ext/mri/bcrypt_pbkdf.c` | [v1.17](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c?rev=1.17) |
19
+ | `ext/mri/blowfish.c` | [v1.20](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libcrypto/blowfish.c?rev=1.20) |
20
+ | `ext/mri/blf.h` | [v1.8](https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libcrypto/blf.h?rev=1.8) |
21
+
12
22
  ## Links
13
23
 
14
24
  * http://www.tedunangst.com/flak/post/bcrypt-pbkdf
15
- * http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/lib/libutil/bcrypt_pbkdf.c?rev=1.13&content-type=text/x-cvsweb-markup
16
25
 
17
26
  ## Building
18
27
 
data/Rakefile CHANGED
@@ -2,12 +2,26 @@ require 'rake/testtask'
2
2
  require 'rubygems/package_task'
3
3
  require 'bundler/gem_tasks'
4
4
  require 'rake/extensiontask'
5
+ begin
6
+ require 'rake/javaextensiontask'
7
+ rescue LoadError
8
+ end
5
9
  require 'rake/clean'
6
10
  require 'rdoc/task'
7
11
  require 'benchmark'
8
12
  require 'rake_compiler_dock'
9
13
 
14
+ begin
15
+ require 'ruby_memcheck'
16
+ RubyMemcheck::TestTask.new(memcheck: :compile) do |t|
17
+ t.libs << 'test'
18
+ t.test_files = FileList['test/**/*_test.rb']
19
+ end
20
+ rescue LoadError
21
+ end
22
+
10
23
  CLEAN.add("{ext,lib}/**/*.{o,so}", "pkg")
24
+ CLEAN.add("{ext,lib}/**/*.{jar,class}")
11
25
 
12
26
  cross_rubies = ["3.4.0", "3.3.0", "3.2.0", "3.1.0", "3.0.0", "2.7.0"]
13
27
  cross_platforms = [
@@ -41,11 +55,23 @@ RDoc::Task.new do |rdoc|
41
55
  rdoc.rdoc_files.include(*GEMSPEC.extra_rdoc_files)
42
56
  end
43
57
 
44
- Rake::ExtensionTask.new("bcrypt_pbkdf_ext", GEMSPEC) do |ext|
45
- ext.ext_dir = 'ext/mri'
46
- ext.cross_compile = true
47
- ext.cross_platform = cross_platforms
48
- ext.cross_config_options << "--enable-cross-build" # so extconf.rb knows we're cross-compiling
58
+ unless RUBY_PLATFORM == 'java'
59
+ Rake::ExtensionTask.new("bcrypt_pbkdf_ext", GEMSPEC) do |ext|
60
+ ext.ext_dir = 'ext/mri'
61
+ ext.cross_compile = true
62
+ ext.cross_platform = cross_platforms
63
+ ext.cross_config_options << "--enable-cross-build" # so extconf.rb knows we're cross-compiling
64
+ end
65
+ end
66
+
67
+ if defined?(Rake::JavaExtensionTask)
68
+ Rake::JavaExtensionTask.new("bcrypt_pbkdf_ext", GEMSPEC) do |ext|
69
+ ext.ext_dir = 'ext/jruby'
70
+ ext.source_pattern = '**/*.java'
71
+ ext.source_version = '8'
72
+ ext.target_version = '8'
73
+ ext.lint_option = '-options'
74
+ end
49
75
  end
50
76
 
51
77
  namespace "gem" do
@@ -73,11 +99,24 @@ namespace "gem" do
73
99
  end
74
100
  end
75
101
 
102
+ desc "build java gem for JRuby"
103
+ task "java" do
104
+ Rake::Task["java:#{GEMSPEC.name}"].invoke
105
+ Rake::Task["pkg/#{GEMSPEC.full_name}-java.gem"].invoke
106
+ end
107
+
108
+ namespace "java" do
109
+ task "release" do
110
+ sh "gem push pkg/#{GEMSPEC.full_name}-java.gem"
111
+ end
112
+ end
113
+
76
114
  desc "build native gem for all platforms"
77
115
  task "all" do
78
116
  cross_platforms.each do |platform|
79
117
  Rake::Task["gem:#{platform}"].invoke
80
118
  end
119
+ Rake::Task["gem:java"].invoke if defined?(Rake::JavaExtensionTask) && ENV['JRUBY_HOME']
81
120
  end
82
121
 
83
122
  desc "release native gem for all platforms"
@@ -85,6 +124,7 @@ namespace "gem" do
85
124
  cross_platforms.each do |platform|
86
125
  Rake::Task["gem:#{platform}:release"].invoke
87
126
  end
127
+ Rake::Task["gem:java:release"].invoke if File.exist?("pkg/#{GEMSPEC.full_name}-java.gem")
88
128
  end
89
129
  end
90
130
 
data/bcrypt_pbkdf.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'bcrypt_pbkdf'
3
- s.version = '1.1.2'
3
+ s.version = '1.2.0.beta1'
4
4
 
5
5
  s.summary = "OpenBSD's bcrypt_pbkdf (a variant of PBKDF2 with bcrypt-based PRF)"
6
6
  s.description = <<-EOF
@@ -0,0 +1,402 @@
1
+ package org.netssh.bcrypt_pbkdf;
2
+
3
+ import java.nio.charset.StandardCharsets;
4
+ import java.security.MessageDigest;
5
+ import java.security.NoSuchAlgorithmException;
6
+ import java.util.Arrays;
7
+
8
+ public final class BCryptPbkdf {
9
+ private static final int BLF_N = 16;
10
+ private static final int BCRYPT_WORDS = 8;
11
+ private static final int BCRYPT_HASHSIZE = BCRYPT_WORDS * 4;
12
+ private static final int SHA512_DIGEST_LENGTH = 64;
13
+ private static final int[] INITSTATE = new int[] {
14
+ 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96,
15
+ 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
16
+ 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658,
17
+ 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
18
+ 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e,
19
+ 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
20
+ 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6,
21
+ 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
22
+ 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c,
23
+ 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
24
+ 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1,
25
+ 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
26
+ 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a,
27
+ 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
28
+ 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176,
29
+ 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
30
+ 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706,
31
+ 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
32
+ 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b,
33
+ 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
34
+ 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c,
35
+ 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
36
+ 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a,
37
+ 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
38
+ 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760,
39
+ 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
40
+ 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8,
41
+ 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
42
+ 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33,
43
+ 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
44
+ 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0,
45
+ 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
46
+ 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777,
47
+ 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
48
+ 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705,
49
+ 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
50
+ 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e,
51
+ 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
52
+ 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9,
53
+ 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
54
+ 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f,
55
+ 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
56
+ 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, 0x4b7a70e9, 0xb5b32944,
57
+ 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
58
+ 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29,
59
+ 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
60
+ 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26,
61
+ 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
62
+ 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c,
63
+ 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
64
+ 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6,
65
+ 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
66
+ 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f,
67
+ 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
68
+ 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810,
69
+ 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
70
+ 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa,
71
+ 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
72
+ 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55,
73
+ 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
74
+ 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1,
75
+ 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
76
+ 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78,
77
+ 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
78
+ 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883,
79
+ 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
80
+ 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170,
81
+ 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
82
+ 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7,
83
+ 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
84
+ 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099,
85
+ 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
86
+ 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263,
87
+ 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
88
+ 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3,
89
+ 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
90
+ 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7,
91
+ 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
92
+ 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x095bbf00, 0xad19489d,
93
+ 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
94
+ 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460,
95
+ 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
96
+ 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484,
97
+ 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
98
+ 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a,
99
+ 0xe6e39f2b, 0xdb83adf7, 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
100
+ 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a,
101
+ 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
102
+ 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785,
103
+ 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
104
+ 0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900,
105
+ 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
106
+ 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9,
107
+ 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
108
+ 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397,
109
+ 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
110
+ 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9,
111
+ 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
112
+ 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f,
113
+ 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
114
+ 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e,
115
+ 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
116
+ 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd,
117
+ 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
118
+ 0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8,
119
+ 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
120
+ 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c,
121
+ 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
122
+ 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b,
123
+ 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
124
+ 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386,
125
+ 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
126
+ 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0,
127
+ 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
128
+ 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2,
129
+ 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
130
+ 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770,
131
+ 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
132
+ 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c,
133
+ 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
134
+ 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa,
135
+ 0xa002b5c4, 0x0de6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
136
+ 0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63,
137
+ 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
138
+ 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9,
139
+ 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
140
+ 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4,
141
+ 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
142
+ 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742,
143
+ 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
144
+ 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79,
145
+ 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
146
+ 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a,
147
+ 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
148
+ 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1,
149
+ 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
150
+ 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797,
151
+ 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
152
+ 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6,
153
+ 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
154
+ 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba,
155
+ 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
156
+ 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5,
157
+ 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
158
+ 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce,
159
+ 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
160
+ 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd,
161
+ 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
162
+ 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb,
163
+ 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
164
+ 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc,
165
+ 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
166
+ 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc,
167
+ 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
168
+ 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a,
169
+ 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
170
+ 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a,
171
+ 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
172
+ 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b,
173
+ 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
174
+ 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e,
175
+ 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
176
+ 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623,
177
+ 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
178
+ 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a,
179
+ 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
180
+ 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3,
181
+ 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
182
+ 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c,
183
+ 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
184
+ 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, 0x243f6a88, 0x85a308d3,
185
+ 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
186
+ 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd,
187
+ 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b
188
+ };
189
+
190
+ static byte[] cryptPbkdf(byte[] pass, byte[] salt, int keylen, int rounds) {
191
+ if (rounds < 1 || pass.length == 0 || salt.length == 0 || keylen == 0 || keylen > BCRYPT_HASHSIZE * BCRYPT_HASHSIZE || salt.length > (1 << 20)) {
192
+ return null;
193
+ }
194
+
195
+ byte[] key = new byte[keylen];
196
+ byte[] sha2pass = sha512(pass);
197
+ byte[] sha2salt;
198
+ byte[] out = new byte[BCRYPT_HASHSIZE];
199
+ byte[] tmpout;
200
+ byte[] countsalt = new byte[salt.length + 4];
201
+ System.arraycopy(salt, 0, countsalt, 0, salt.length);
202
+
203
+ int stride = (keylen + BCRYPT_HASHSIZE - 1) / BCRYPT_HASHSIZE;
204
+ int amt = (keylen + stride - 1) / stride;
205
+ int origkeylen = keylen;
206
+
207
+ for (int count = 1; keylen > 0; count++) {
208
+ countsalt[salt.length] = (byte) ((count >>> 24) & 0xff);
209
+ countsalt[salt.length + 1] = (byte) ((count >>> 16) & 0xff);
210
+ countsalt[salt.length + 2] = (byte) ((count >>> 8) & 0xff);
211
+ countsalt[salt.length + 3] = (byte) (count & 0xff);
212
+
213
+ sha2salt = sha512(countsalt);
214
+ tmpout = bcryptHash(sha2pass, sha2salt);
215
+ System.arraycopy(tmpout, 0, out, 0, out.length);
216
+
217
+ for (int i = 1; i < rounds; i++) {
218
+ sha2salt = sha512(tmpout);
219
+ tmpout = bcryptHash(sha2pass, sha2salt);
220
+ for (int j = 0; j < out.length; j++) {
221
+ out[j] ^= tmpout[j];
222
+ }
223
+ }
224
+
225
+ amt = Math.min(amt, keylen);
226
+ int i;
227
+ for (i = 0; i < amt; i++) {
228
+ int dest = i * stride + (count - 1);
229
+ if (dest >= origkeylen) {
230
+ break;
231
+ }
232
+ key[dest] = out[i];
233
+ }
234
+ keylen -= i;
235
+ }
236
+
237
+ Arrays.fill(sha2pass, (byte) 0);
238
+ Arrays.fill(out, (byte) 0);
239
+ return key;
240
+ }
241
+
242
+ static byte[] cryptHash(byte[] sha2pass, byte[] sha2salt) {
243
+ if (sha2pass.length != SHA512_DIGEST_LENGTH || sha2salt.length != SHA512_DIGEST_LENGTH) {
244
+ return null;
245
+ }
246
+ return bcryptHash(sha2pass, sha2salt);
247
+ }
248
+
249
+ private static byte[] bcryptHash(byte[] sha2pass, byte[] sha2salt) {
250
+ BlowfishContext state = new BlowfishContext();
251
+ byte[] ciphertext = "OxychromaticBlowfishSwatDynamite".getBytes(StandardCharsets.US_ASCII);
252
+ int[] cdata = new int[BCRYPT_WORDS];
253
+ byte[] out = new byte[BCRYPT_HASHSIZE];
254
+ int[] current = new int[] { 0 };
255
+
256
+ Blowfish_initstate(state);
257
+ Blowfish_expandstate(state, sha2salt, SHA512_DIGEST_LENGTH, sha2pass, SHA512_DIGEST_LENGTH);
258
+ for (int i = 0; i < 64; i++) {
259
+ Blowfish_expand0state(state, sha2salt, SHA512_DIGEST_LENGTH);
260
+ Blowfish_expand0state(state, sha2pass, SHA512_DIGEST_LENGTH);
261
+ }
262
+
263
+ for (int i = 0; i < BCRYPT_WORDS; i++) {
264
+ cdata[i] = Blowfish_stream2word(ciphertext, ciphertext.length, current);
265
+ }
266
+ for (int i = 0; i < 64; i++) {
267
+ blf_enc(state, cdata, cdata.length / 2);
268
+ }
269
+
270
+ for (int i = 0; i < BCRYPT_WORDS; i++) {
271
+ out[4 * i + 3] = (byte) ((cdata[i] >>> 24) & 0xff);
272
+ out[4 * i + 2] = (byte) ((cdata[i] >>> 16) & 0xff);
273
+ out[4 * i + 1] = (byte) ((cdata[i] >>> 8) & 0xff);
274
+ out[4 * i] = (byte) (cdata[i] & 0xff);
275
+ }
276
+
277
+ Arrays.fill(ciphertext, (byte) 0);
278
+ Arrays.fill(cdata, 0);
279
+ state.clear();
280
+ return out;
281
+ }
282
+
283
+ private static byte[] sha512(byte[] data) {
284
+ try {
285
+ return MessageDigest.getInstance("SHA-512").digest(data);
286
+ } catch (NoSuchAlgorithmException e) {
287
+ throw new IllegalStateException(e);
288
+ }
289
+ }
290
+
291
+ private static int F(int[][] s, int x) {
292
+ return ((s[0][(x >>> 24) & 0xff] + s[1][(x >>> 16) & 0xff]) ^ s[2][(x >>> 8) & 0xff]) + s[3][x & 0xff];
293
+ }
294
+
295
+ private static void Blowfish_encipher(BlowfishContext c, int[] data, int offset) {
296
+ int xl = data[offset];
297
+ int xr = data[offset + 1];
298
+ int[] p = c.P;
299
+
300
+ xl ^= p[0];
301
+ xr ^= F(c.S, xl) ^ p[1]; xl ^= F(c.S, xr) ^ p[2];
302
+ xr ^= F(c.S, xl) ^ p[3]; xl ^= F(c.S, xr) ^ p[4];
303
+ xr ^= F(c.S, xl) ^ p[5]; xl ^= F(c.S, xr) ^ p[6];
304
+ xr ^= F(c.S, xl) ^ p[7]; xl ^= F(c.S, xr) ^ p[8];
305
+ xr ^= F(c.S, xl) ^ p[9]; xl ^= F(c.S, xr) ^ p[10];
306
+ xr ^= F(c.S, xl) ^ p[11]; xl ^= F(c.S, xr) ^ p[12];
307
+ xr ^= F(c.S, xl) ^ p[13]; xl ^= F(c.S, xr) ^ p[14];
308
+ xr ^= F(c.S, xl) ^ p[15]; xl ^= F(c.S, xr) ^ p[16];
309
+
310
+ data[offset] = xr ^ p[17];
311
+ data[offset + 1] = xl;
312
+ }
313
+
314
+ private static void Blowfish_initstate(BlowfishContext c) {
315
+ int n = 0;
316
+ for (int i = 0; i < 4; i++) {
317
+ System.arraycopy(INITSTATE, n, c.S[i], 0, 256);
318
+ n += 256;
319
+ }
320
+ System.arraycopy(INITSTATE, n, c.P, 0, BLF_N + 2);
321
+ }
322
+
323
+ private static int Blowfish_stream2word(byte[] data, int databytes, int[] current) {
324
+ int temp = 0;
325
+ int j = current[0];
326
+ for (int i = 0; i < 4; i++, j++) {
327
+ if (j >= databytes) {
328
+ j = 0;
329
+ }
330
+ temp = (temp << 8) | (data[j] & 0xff);
331
+ }
332
+ current[0] = j;
333
+ return temp;
334
+ }
335
+
336
+ private static void Blowfish_expand0state(BlowfishContext c, byte[] key, int keybytes) {
337
+ int[] current = new int[] { 0 };
338
+ for (int i = 0; i < BLF_N + 2; i++) {
339
+ c.P[i] ^= Blowfish_stream2word(key, keybytes, current);
340
+ }
341
+
342
+ int[] data = new int[] { 0, 0 };
343
+ for (int i = 0; i < BLF_N + 2; i += 2) {
344
+ Blowfish_encipher(c, data, 0);
345
+ c.P[i] = data[0];
346
+ c.P[i + 1] = data[1];
347
+ }
348
+
349
+ for (int i = 0; i < 4; i++) {
350
+ for (int k = 0; k < 256; k += 2) {
351
+ Blowfish_encipher(c, data, 0);
352
+ c.S[i][k] = data[0];
353
+ c.S[i][k + 1] = data[1];
354
+ }
355
+ }
356
+ }
357
+
358
+ private static void Blowfish_expandstate(BlowfishContext c, byte[] dataBytes, int databytes, byte[] key, int keybytes) {
359
+ int[] current = new int[] { 0 };
360
+ for (int i = 0; i < BLF_N + 2; i++) {
361
+ c.P[i] ^= Blowfish_stream2word(key, keybytes, current);
362
+ }
363
+
364
+ current[0] = 0;
365
+ int[] data = new int[] { 0, 0 };
366
+ for (int i = 0; i < BLF_N + 2; i += 2) {
367
+ data[0] ^= Blowfish_stream2word(dataBytes, databytes, current);
368
+ data[1] ^= Blowfish_stream2word(dataBytes, databytes, current);
369
+ Blowfish_encipher(c, data, 0);
370
+ c.P[i] = data[0];
371
+ c.P[i + 1] = data[1];
372
+ }
373
+
374
+ for (int i = 0; i < 4; i++) {
375
+ for (int k = 0; k < 256; k += 2) {
376
+ data[0] ^= Blowfish_stream2word(dataBytes, databytes, current);
377
+ data[1] ^= Blowfish_stream2word(dataBytes, databytes, current);
378
+ Blowfish_encipher(c, data, 0);
379
+ c.S[i][k] = data[0];
380
+ c.S[i][k + 1] = data[1];
381
+ }
382
+ }
383
+ }
384
+
385
+ private static void blf_enc(BlowfishContext c, int[] data, int blocks) {
386
+ for (int i = 0, offset = 0; i < blocks; i++, offset += 2) {
387
+ Blowfish_encipher(c, data, offset);
388
+ }
389
+ }
390
+
391
+ private static class BlowfishContext {
392
+ final int[][] S = new int[4][256];
393
+ final int[] P = new int[BLF_N + 2];
394
+
395
+ void clear() {
396
+ for (int[] s : S) {
397
+ Arrays.fill(s, 0);
398
+ }
399
+ Arrays.fill(P, 0);
400
+ }
401
+ }
402
+ }
@@ -0,0 +1,47 @@
1
+ package org.netssh.bcrypt_pbkdf;
2
+
3
+ import org.jcodings.specific.ASCIIEncoding;
4
+ import org.jruby.Ruby;
5
+ import org.jruby.RubyClass;
6
+ import org.jruby.RubyModule;
7
+ import org.jruby.RubyNumeric;
8
+ import org.jruby.RubyString;
9
+ import org.jruby.anno.JRubyMethod;
10
+ import org.jruby.runtime.ThreadContext;
11
+ import org.jruby.runtime.builtin.IRubyObject;
12
+
13
+ public final class BCryptPbkdfExt {
14
+
15
+ public static void load(final Ruby runtime) {
16
+ RubyModule bcryptPbkdf = runtime.getOrCreateModule("BCryptPbkdf");
17
+ RubyClass engine = bcryptPbkdf.defineOrGetClassUnder("Engine", runtime.getObject());
18
+ engine.getSingletonClass().defineAnnotatedMethods(BCryptPbkdfExt.class);
19
+ }
20
+
21
+ @JRubyMethod(required = 4, rest = true)
22
+ public static IRubyObject __bc_crypt_pbkdf(ThreadContext context, IRubyObject self, IRubyObject[] args) {
23
+ byte[] key = BCryptPbkdf.cryptPbkdf(
24
+ stringToBytes(args[0]),
25
+ stringToBytes(args[1]),
26
+ RubyNumeric.num2int(args[2]),
27
+ RubyNumeric.num2int(args[3]));
28
+ if (key == null) return context.nil;
29
+ return newString(context.runtime, key);
30
+ }
31
+
32
+
33
+ @JRubyMethod(required = 2, rest = true)
34
+ public static IRubyObject __bc_crypt_hash(ThreadContext context, IRubyObject self, IRubyObject[] args) {
35
+ byte[] out = BCryptPbkdf.cryptHash(stringToBytes(args[0]), stringToBytes(args[1]));
36
+ if (out == null) return context.nil;
37
+ return newString(context.runtime, out);
38
+ }
39
+
40
+ private static byte[] stringToBytes(final IRubyObject value) {
41
+ return value.convertToString().getBytes();
42
+ }
43
+
44
+ private static RubyString newString(final Ruby runtime, final byte[] bytes) {
45
+ return RubyString.newString(runtime, bytes, 0, bytes.length, ASCIIEncoding.INSTANCE);
46
+ }
47
+ }
@@ -1,4 +1,4 @@
1
- /* $OpenBSD: bcrypt_pbkdf.c,v 1.13 2015/01/12 03:20:04 tedu Exp $ */
1
+ /* $OpenBSD: bcrypt_pbkdf.c,v 1.17 2022/12/27 17:10:08 jmc Exp $ */
2
2
  /*
3
3
  * Copyright (c) 2013 Ted Unangst <tedu@openbsd.org>
4
4
  *
@@ -15,14 +15,13 @@
15
15
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
16
  */
17
17
 
18
- #include <sys/types.h>
18
+ #include "includes.h"
19
+ #include "crypto_api.h"
19
20
 
20
- #include <stdint.h>
21
- #include <stdlib.h>
22
- #include "blf.h"
23
- #include "sha2.h"
24
- #include <string.h>
25
- #include "util.h"
21
+ #ifdef SHA512_DIGEST_LENGTH
22
+ # undef SHA512_DIGEST_LENGTH
23
+ #endif
24
+ #define SHA512_DIGEST_LENGTH crypto_hash_sha512_BYTES
26
25
 
27
26
  #define MINIMUM(a,b) (((a) < (b)) ? (a) : (b))
28
27
 
@@ -33,7 +32,7 @@
33
32
  * function with the following modifications:
34
33
  * 1. The input password and salt are preprocessed with SHA512.
35
34
  * 2. The output length is expanded to 256 bits.
36
- * 3. Subsequently the magic string to be encrypted is lengthened and modifed
35
+ * 3. Subsequently the magic string to be encrypted is lengthened and modified
37
36
  * to "OxychromaticBlowfishSwatDynamite"
38
37
  * 4. The hash function is defined to perform 64 rounds of initial state
39
38
  * expansion. (More rounds are performed by iterating the hash.)
@@ -50,14 +49,15 @@
50
49
  * wise caller could do; we just do it for you.
51
50
  */
52
51
 
53
- #define BCRYPT_WORDS 8
54
- #define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4)
55
-
56
52
  void
57
- bcrypt_hash(const uint8_t *sha2pass, const uint8_t *sha2salt, uint8_t *out)
53
+ bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out)
58
54
  {
59
55
  blf_ctx state;
56
+ #if defined(__has_attribute) && __has_attribute(__nonstring__)
57
+ uint8_t __attribute__ ((__nonstring__)) ciphertext[BCRYPT_HASHSIZE] =
58
+ #else
60
59
  uint8_t ciphertext[BCRYPT_HASHSIZE] =
60
+ #endif
61
61
  "OxychromaticBlowfishSwatDynamite";
62
62
  uint32_t cdata[BCRYPT_WORDS];
63
63
  int i;
@@ -78,7 +78,7 @@ bcrypt_hash(const uint8_t *sha2pass, const uint8_t *sha2salt, uint8_t *out)
78
78
  cdata[i] = Blowfish_stream2word(ciphertext, sizeof(ciphertext),
79
79
  &j);
80
80
  for (i = 0; i < 64; i++)
81
- blf_enc(&state, cdata, sizeof(cdata) / sizeof(uint64_t));
81
+ blf_enc(&state, cdata, BCRYPT_WORDS / 2);
82
82
 
83
83
  /* copy out */
84
84
  for (i = 0; i < BCRYPT_WORDS; i++) {
@@ -98,12 +98,11 @@ int
98
98
  bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen,
99
99
  uint8_t *key, size_t keylen, unsigned int rounds)
100
100
  {
101
- SHA2_CTX ctx;
102
101
  uint8_t sha2pass[SHA512_DIGEST_LENGTH];
103
102
  uint8_t sha2salt[SHA512_DIGEST_LENGTH];
104
103
  uint8_t out[BCRYPT_HASHSIZE];
105
104
  uint8_t tmpout[BCRYPT_HASHSIZE];
106
- uint8_t countsalt[4];
105
+ uint8_t *countsalt;
107
106
  size_t i, j, amt, stride;
108
107
  uint32_t count;
109
108
  size_t origkeylen = keylen;
@@ -112,37 +111,34 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltl
112
111
  if (rounds < 1)
113
112
  return -1;
114
113
  if (passlen == 0 || saltlen == 0 || keylen == 0 ||
115
- keylen > sizeof(out) * sizeof(out))
114
+ keylen > sizeof(out) * sizeof(out) || saltlen > 1<<20)
115
+ return -1;
116
+ if ((countsalt = calloc(1, saltlen + 4)) == NULL)
116
117
  return -1;
117
118
  stride = (keylen + sizeof(out) - 1) / sizeof(out);
118
119
  amt = (keylen + stride - 1) / stride;
119
120
 
120
- /* collapse password */
121
- SHA512Init(&ctx);
122
- SHA512Update(&ctx, pass, passlen);
123
- SHA512Final(sha2pass, &ctx);
121
+ memcpy(countsalt, salt, saltlen);
124
122
 
123
+ /* collapse password */
124
+ crypto_hash_sha512(sha2pass, (const uint8_t *)pass, passlen);
125
125
 
126
126
  /* generate key, sizeof(out) at a time */
127
127
  for (count = 1; keylen > 0; count++) {
128
- countsalt[0] = (count >> 24) & 0xff;
129
- countsalt[1] = (count >> 16) & 0xff;
130
- countsalt[2] = (count >> 8) & 0xff;
131
- countsalt[3] = count & 0xff;
128
+ countsalt[saltlen + 0] = (count >> 24) & 0xff;
129
+ countsalt[saltlen + 1] = (count >> 16) & 0xff;
130
+ countsalt[saltlen + 2] = (count >> 8) & 0xff;
131
+ countsalt[saltlen + 3] = count & 0xff;
132
132
 
133
133
  /* first round, salt is salt */
134
- SHA512Init(&ctx);
135
- SHA512Update(&ctx, salt, saltlen);
136
- SHA512Update(&ctx, countsalt, sizeof(countsalt));
137
- SHA512Final(sha2salt, &ctx);
134
+ crypto_hash_sha512(sha2salt, countsalt, saltlen + 4);
135
+
138
136
  bcrypt_hash(sha2pass, sha2salt, tmpout);
139
137
  memcpy(out, tmpout, sizeof(out));
140
138
 
141
139
  for (i = 1; i < rounds; i++) {
142
140
  /* subsequent rounds, salt is previous output */
143
- SHA512Init(&ctx);
144
- SHA512Update(&ctx, tmpout, sizeof(tmpout));
145
- SHA512Final(sha2salt, &ctx);
141
+ crypto_hash_sha512(sha2salt, tmpout, sizeof(tmpout));
146
142
  bcrypt_hash(sha2pass, sha2salt, tmpout);
147
143
  for (j = 0; j < sizeof(out); j++)
148
144
  out[j] ^= tmpout[j];
@@ -162,8 +158,10 @@ bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltl
162
158
  }
163
159
 
164
160
  /* zap */
165
- explicit_bzero(&ctx, sizeof(ctx));
161
+ explicit_bzero(countsalt, saltlen + 4);
162
+ free(countsalt);
166
163
  explicit_bzero(out, sizeof(out));
164
+ explicit_bzero(tmpout, sizeof(tmpout));
167
165
 
168
166
  return 0;
169
- }
167
+ }
@@ -8,6 +8,8 @@ static VALUE cBCryptPbkdfEngine;
8
8
  */
9
9
  static VALUE bc_crypt_pbkdf(VALUE self, VALUE pass, VALUE salt, VALUE keylen, VALUE rounds) {
10
10
  size_t okeylen = NUM2ULONG(keylen);
11
+ if (okeylen == 0 || okeylen > 1024)
12
+ return Qnil;
11
13
  u_int8_t* okey = xmalloc(okeylen);
12
14
  VALUE out;
13
15
 
@@ -16,8 +18,10 @@ static VALUE bc_crypt_pbkdf(VALUE self, VALUE pass, VALUE salt, VALUE keylen, VA
16
18
  (const u_int8_t*)StringValuePtr(salt), RSTRING_LEN(salt),
17
19
  okey, okeylen,
18
20
  NUM2ULONG(rounds));
19
- if (ret < 0)
21
+ if (ret < 0) {
22
+ xfree(okey);
20
23
  return Qnil;
24
+ }
21
25
  out = rb_str_new((const char*)okey, okeylen);
22
26
  xfree(okey);
23
27
  return out;
@@ -29,7 +33,7 @@ static VALUE bc_crypt_hash(VALUE self, VALUE pass, VALUE salt) {
29
33
  return Qnil;
30
34
  if (RSTRING_LEN(salt) != 64U)
31
35
  return Qnil;
32
- bcrypt_hash((const u_int8_t*)StringValuePtr(pass), (const u_int8_t*)StringValuePtr(salt), hash);
36
+ bcrypt_hash((u_int8_t*)StringValuePtr(pass), (u_int8_t*)StringValuePtr(salt), hash);
33
37
  return rb_str_new((const char*)hash, sizeof(hash));
34
38
  }
35
39
 
data/ext/mri/blf.h CHANGED
@@ -1,4 +1,4 @@
1
- /* $OpenBSD: blf.h,v 1.7 2007/03/14 17:59:41 grunk Exp $ */
1
+ /* $OpenBSD: blf.h,v 1.8 2021/11/29 01:04:45 djm Exp $ */
2
2
  /*
3
3
  * Blowfish - a fast block cipher designed by Bruce Schneier
4
4
  *
@@ -13,10 +13,7 @@
13
13
  * 2. Redistributions in binary form must reproduce the above copyright
14
14
  * notice, this list of conditions and the following disclaimer in the
15
15
  * documentation and/or other materials provided with the distribution.
16
- * 3. All advertising materials mentioning features or use of this software
17
- * must display the following acknowledgement:
18
- * This product includes software developed by Niels Provos.
19
- * 4. The name of the author may not be used to endorse or promote products
16
+ * 3. The name of the author may not be used to endorse or promote products
20
17
  * derived from this software without specific prior written permission.
21
18
  *
22
19
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
data/ext/mri/blowfish.c CHANGED
@@ -1,4 +1,4 @@
1
- /* $OpenBSD: blowfish.c,v 1.19 2015/09/11 09:18:27 guenther Exp $ */
1
+ /* $OpenBSD: blowfish.c,v 1.20 2021/11/29 01:04:45 djm Exp $ */
2
2
  /*
3
3
  * Blowfish block cipher for OpenBSD
4
4
  * Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
@@ -14,10 +14,7 @@
14
14
  * 2. Redistributions in binary form must reproduce the above copyright
15
15
  * notice, this list of conditions and the following disclaimer in the
16
16
  * documentation and/or other materials provided with the distribution.
17
- * 3. All advertising materials mentioning features or use of this software
18
- * must display the following acknowledgement:
19
- * This product includes software developed by Niels Provos.
20
- * 4. The name of the author may not be used to endorse or promote products
17
+ * 3. The name of the author may not be used to endorse or promote products
21
18
  * derived from this software without specific prior written permission.
22
19
  *
23
20
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
data/ext/mri/includes.h CHANGED
@@ -19,7 +19,7 @@ typedef uint32_t u_int32_t;
19
19
  void explicit_bzero(void *p, size_t n);
20
20
  int bcrypt_pbkdf(const char *pass, size_t passlen, const uint8_t *salt, size_t saltlen,
21
21
  uint8_t *key, size_t keylen, unsigned int rounds);
22
- void bcrypt_hash(const uint8_t *sha2pass, const uint8_t *sha2salt, uint8_t *out);
22
+ void bcrypt_hash(uint8_t *sha2pass, uint8_t *sha2salt, uint8_t *out);
23
23
 
24
24
  #define BCRYPT_WORDS 8
25
25
  #define BCRYPT_HASHSIZE (BCRYPT_WORDS * 4)
Binary file
Binary file
Binary file
Binary file
Binary file
data/lib/bcrypt_pbkdf.rb CHANGED
@@ -1,8 +1,13 @@
1
- begin
2
- RUBY_VERSION =~ /(\d+.\d+)/
3
- require "#{$1}/bcrypt_pbkdf_ext"
4
- rescue LoadError
5
- require "bcrypt_pbkdf_ext"
1
+ if RUBY_PLATFORM == 'java'
2
+ load File.expand_path('bcrypt_pbkdf_ext.jar', __dir__)
3
+ JRuby::Util.load_ext('org.netssh.bcrypt_pbkdf.BCryptPbkdfExt')
4
+ else
5
+ begin
6
+ RUBY_VERSION =~ /(\d+.\d+)/
7
+ require "#{$1}/bcrypt_pbkdf_ext"
8
+ rescue LoadError
9
+ require "bcrypt_pbkdf_ext"
10
+ end
6
11
  end
7
12
 
8
13
  module BCryptPbkdf
@@ -21,4 +26,3 @@ module BCryptPbkdf
21
26
  BCryptPbkdf::Engine::__bc_crypt_pbkdf(pass,salt,keylen,rounds)
22
27
  end
23
28
  end
24
-
@@ -1,5 +1,4 @@
1
1
  require 'minitest/autorun'
2
- require 'minitest/unit'
3
2
  require 'test_helper'
4
3
 
5
4
  # bcrypt_pbkdf in ruby
@@ -55,7 +54,7 @@ def bcrypt_pbkdf(password, salt, keylen, rounds)
55
54
  end
56
55
 
57
56
 
58
- class TestExt < Minitest::Unit::TestCase
57
+ class TestExt < Minitest::Test
59
58
  def test_table
60
59
  assert_equal table, table.map{ |p,s,l,r| [p,s,l,r,BCryptPbkdf::Engine::__bc_crypt_pbkdf(p,s,l,r).bytes] }
61
60
  end
@@ -66,12 +65,51 @@ class TestExt < Minitest::Unit::TestCase
66
65
  end
67
66
  end
68
67
 
68
+ def test_invalid_pbkdf_arguments_return_nil
69
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf('', 'salt', 14, 1)
70
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf('pass', '', 14, 1)
71
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf('pass', 'salt', 0, 1)
72
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf('pass', 'salt', 14, 0)
73
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf('pass', 'salt', 1025, 1)
74
+ end
75
+
76
+ def test_hash_argument_lengths
77
+ sha2pass = OpenSSL::Digest.digest('SHA512', 'pass')
78
+ sha2salt = OpenSSL::Digest.digest('SHA512', 'salt')
79
+
80
+ assert_equal BCRYPT_HASHSIZE, BCryptPbkdf::Engine.__bc_crypt_hash(sha2pass, sha2salt).bytesize
81
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_hash(sha2pass.byteslice(0, 63), sha2salt)
82
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_hash(sha2pass, sha2salt.byteslice(0, 63))
83
+ end
84
+
85
+ # Issue #31/33: xmalloc(okeylen) was called before the guards inside
86
+ # bcrypt_pbkdf(), so out-of-range keylen caused a heap allocation that was
87
+ # never freed when bcrypt_pbkdf() returned -1. `loop { key("p","s",2000,1) }`
88
+ # on unfixed code would exhaust memory.
89
+ def test_invalid_keylen_returns_nil
90
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf("pass", "salt", 0, 1)
91
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf("pass", "salt", 1025, 1)
92
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf("pass", "salt", 2000, 1)
93
+ assert_nil BCryptPbkdf::Engine.__bc_crypt_pbkdf("pass", "salt", 32, 0)
94
+ end
95
+
96
+ def test_invalid_keylen_does_not_leak_memory
97
+ 1000.times { BCryptPbkdf::Engine.__bc_crypt_pbkdf("pass", "salt", 2000, 1) }
98
+ end
69
99
 
70
100
  def table
71
101
  [
72
102
  ["pass2", "salt2", 12, 2, [214, 14, 48, 162, 131, 206, 121, 176, 50, 104, 231, 252]],
73
103
  ["\u0000\u0001foo", "\u0001\u0002fooo3", 14, 5, [46, 189, 32, 185, 94, 85, 232, 10, 84, 26, 44, 161, 49, 126]],
74
- ["doozoasd", "fooo$AS!", 14, 22, [57, 62, 50, 107, 70, 155, 65, 5, 129, 211, 189, 169, 188, 65]]
104
+ ["doozoasd", "fooo$AS!", 14, 22, [57, 62, 50, 107, 70, 155, 65, 5, 129, 211, 189, 169, 188, 65]],
105
+ # vectors from jBCrypt (https://github.com/kruton/jbcrypt) by Kenny Root
106
+ ["password", "salt", 32, 4, [0x5b, 0xbf, 0x0c, 0xc2, 0x93, 0x58, 0x7f, 0x1c, 0x36, 0x35, 0x55, 0x5c, 0x27, 0x79, 0x65, 0x98,
107
+ 0xd4, 0x7e, 0x57, 0x90, 0x71, 0xbf, 0x42, 0x7e, 0x9d, 0x8f, 0xbe, 0x84, 0x2a, 0xba, 0x34, 0xd9]],
108
+ ["password", "salt", 64, 8, [0xe1, 0x36, 0x7e, 0xc5, 0x15, 0x1a, 0x33, 0xfa, 0xac, 0x4c, 0xc1, 0xc1, 0x44, 0xcd, 0x23, 0xfa,
109
+ 0x15, 0xd5, 0x54, 0x84, 0x93, 0xec, 0xc9, 0x9b, 0x9b, 0x5d, 0x9c, 0x0d, 0x3b, 0x27, 0xbe, 0xc7,
110
+ 0x62, 0x27, 0xea, 0x66, 0x08, 0x8b, 0x84, 0x9b, 0x20, 0xab, 0x7a, 0xa4, 0x78, 0x01, 0x02, 0x46,
111
+ 0xe7, 0x4b, 0xba, 0x51, 0x72, 0x3f, 0xef, 0xa9, 0xf9, 0x47, 0x4d, 0x65, 0x08, 0x84, 0x5e, 0x8d]],
112
+ ["password", "salt", 16, 42, [0x83, 0x3c, 0xf0, 0xdc, 0xf5, 0x6d, 0xb6, 0x56, 0x08, 0xe8, 0xf0, 0xdc, 0x0c, 0xe8, 0x82, 0xbd]],
75
113
  ]
76
114
  end
77
115
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bcrypt_pbkdf
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0.beta1
5
5
  platform: x86-mingw32
6
6
  authors:
7
7
  - Miklos Fazekas
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-12-05 00:00:00.000000000 Z
11
+ date: 2026-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -110,9 +110,12 @@ files:
110
110
  - CHANGELOG.md
111
111
  - COPYING
112
112
  - Gemfile
113
+ - Gemfile.memcheck
113
114
  - README.md
114
115
  - Rakefile
115
116
  - bcrypt_pbkdf.gemspec
117
+ - ext/jruby/org/netssh/bcrypt_pbkdf/BCryptPbkdf.java
118
+ - ext/jruby/org/netssh/bcrypt_pbkdf/BCryptPbkdfExt.java
116
119
  - ext/mri/bcrypt_pbkdf.c
117
120
  - ext/mri/bcrypt_pbkdf_ext.c
118
121
  - ext/mri/blf.h
@@ -158,9 +161,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
161
  version: 3.4.dev
159
162
  required_rubygems_version: !ruby/object:Gem::Requirement
160
163
  requirements:
161
- - - ">="
164
+ - - ">"
162
165
  - !ruby/object:Gem::Version
163
- version: '0'
166
+ version: 1.3.1
164
167
  requirements: []
165
168
  rubygems_version: 3.3.26
166
169
  signing_key: