jruby-openssl 0.16.1-java → 0.19.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.md +109 -0
- data/Mavenfile +180 -93
- data/README.md +101 -28
- data/Rakefile +77 -26
- data/lib/jopenssl/load.rb +13 -57
- data/lib/jopenssl/version.rb +3 -8
- data/lib/jopenssl.jar +0 -0
- data/lib/openssl/config.rb +13 -5
- data/lib/openssl/ssl.rb +21 -11
- data/lib/openssl.rb +43 -0
- data/pom.xml +657 -109
- data/{lib/org/bouncycastle/bcpkix-jdk18on/1.84/bcpkix-jdk18on-1.84.jar → vendor/org/bouncycastle/bcpkix-jdk18on/1.85/bcpkix-jdk18on-1.85.jar} +0 -0
- data/{lib/org/bouncycastle/bcprov-jdk18on/1.84/bcprov-jdk18on-1.84.jar → vendor/org/bouncycastle/bcprov-jdk18on/1.85/bcprov-jdk18on-1.85.jar} +0 -0
- data/{lib/org/bouncycastle/bctls-jdk18on/1.84/bctls-jdk18on-1.84.jar → vendor/org/bouncycastle/bctls-jdk18on/1.85/bctls-jdk18on-1.85.jar} +0 -0
- data/{lib/org/bouncycastle/bcutil-jdk18on/1.84/bcutil-jdk18on-1.84.jar → vendor/org/bouncycastle/bcutil-jdk18on/1.85/bcutil-jdk18on-1.85.jar} +0 -0
- metadata +20 -21
- data/lib/openssl/pkcs12.rb +0 -101
data/README.md
CHANGED
|
@@ -1,35 +1,34 @@
|
|
|
1
1
|
# JRuby-OpenSSL
|
|
2
2
|
|
|
3
|
-
[JRuby-OpenSSL](https://github.com/jruby/jruby-openssl) is an
|
|
4
|
-
[JRuby](https://www.jruby.org/) that emulates the Ruby OpenSSL native library.
|
|
3
|
+
[JRuby-OpenSSL](https://github.com/jruby/jruby-openssl) is an extension gem for
|
|
4
|
+
[JRuby](https://www.jruby.org/) that emulates the Ruby `OpenSSL` native library.
|
|
5
5
|
|
|
6
6
|
Under the hood it uses the [Bouncy Castle Crypto APIs](https://www.bouncycastle.org/java.html).
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
PKIX/CMS/EAC/PKCS/OCSP/TSP/OPENSSL jars), usually the latest available version.
|
|
8
|
+
All jruby-openssl gem releases include the Bouncy Castle library (BC Provider, BC JSSE
|
|
9
|
+
and PKIX/CMS/EAC/PKCS/OCSP/TSP/OPENSSL jars), usually the latest available version.
|
|
10
10
|
|
|
11
11
|
Please report bugs and incompatibilities (preferably with test-cases) to either
|
|
12
12
|
the JRuby [mailing list][1] or the [bug tracker][2].
|
|
13
13
|
|
|
14
14
|
## Compatibility
|
|
15
15
|
|
|
16
|
+
Check latest jruby-openssl gem spec's `jar` *requirements* for compatibility.
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
require 'openssl'
|
|
20
|
+
JOpenSSL::VERSION
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
For older versions of the gem compatibility wasn't reported:
|
|
24
|
+
|
|
16
25
|
| JRuby-OpenSSL | JRuby compat | JVM compat | supported BC |
|
|
17
26
|
|---------------|:------------:|-----------:|-------------:|
|
|
18
|
-
| 0.9.6 | 1.6.8-9.0.2 | Java 6-8 | 1.47-1.50 |
|
|
19
|
-
| 0.9.12 | 1.6.8-9.0.5 | Java 6-8 | 1.47-1.52 |
|
|
20
|
-
| 0.9.13 | 1.6.8-9.1.2 | Java 6-8 | 1.49-1.52 |
|
|
21
|
-
| 0.9.14 | 1.6.8-9.1.5 | Java 6-8 | 1.49-1.54 |
|
|
22
|
-
| 0.9.17 | 1.6.8-9.1.5 | Java 6-8 | 1.50-1.54 |
|
|
23
|
-
| ~>0.9.18 | 1.6.8-9.1.x | Java 6-8 | 1.50-1.55 |
|
|
24
|
-
| 0.10.0 | 1.7.20-9.2.x | Java 7-10 | 1.55-1.59 |
|
|
25
|
-
| 0.10.3 | 1.7.20-9.2.x | Java 7-11 | 1.56-1.62 |
|
|
26
|
-
| ~>0.10.5 | 1.7.20-9.3.x | Java 7-11 | 1.60-1.68 |
|
|
27
|
-
| ~>0.11.x | 9.0.x-9.3.x | Java 7-11 | 1.62-1.68 |
|
|
28
27
|
| ~>0.12.x | 9.1.x-9.3.x | Java 8-15 | 1.65-1.68 |
|
|
29
28
|
| ~>0.13.x | 9.1.x-9.4.x | Java 8-17 | 1.68-1.69 |
|
|
30
29
|
| ~>0.14.x | 9.1.x-9.4.x | Java 8-21 | 1.71-1.74 |
|
|
31
30
|
| ~>0.15.x | 9.2.x-10.0.x | Java 8-25 | 1.78-1.83 |
|
|
32
|
-
| ~>0.16.x | 9.3.x-10.0.x | Java 8-25 | 1.83-1.
|
|
31
|
+
| ~>0.16.x | 9.3.x-10.0.x | Java 8-25 | 1.83-1.85 |
|
|
33
32
|
|
|
34
33
|
## Security
|
|
35
34
|
|
|
@@ -39,30 +38,103 @@ JRuby-OpenSSL is an essential part of [JRuby](https://www.jruby.org/), please re
|
|
|
39
38
|
Please note that most OpenSSL vulnerabilities do not affect JRuby since it's not using
|
|
40
39
|
any of OpenSSL's C code, only Ruby parts (*.rb) are the same as in MRI's OpenSSL library.
|
|
41
40
|
|
|
42
|
-
##
|
|
41
|
+
## Supported configuration
|
|
42
|
+
|
|
43
|
+
Most runtime knobs are Java system properties.
|
|
44
|
+
Under JRuby you pass them as `-J-D...` flags, e.g. `JRUBY_OPTS='-J-Djruby.openssl.debug=true'`.
|
|
45
|
+
|
|
46
|
+
### Runtime / JVM properties
|
|
47
|
+
|
|
48
|
+
| Property | Default | Effect |
|
|
49
|
+
|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
50
|
+
| `jruby.openssl.load.jars` | `true` | If set to `false`, `lib/jopenssl/load.rb` skips auto-loading the bundled BouncyCastle jars - handy when the BC jars are on the JVM classpath. |
|
|
51
|
+
| `jruby.openssl.debug` | `false` | Turns on internal debug logging and stack traces from the Java extension, has the same effect as setting `OpenSSL.debug = true` at runtime. |
|
|
52
|
+
| `jruby.openssl.warn` | follows JRuby's warning mode (`runtime.warningsEnabled()`) | Enables or disables warnings from the extension, set `false` to stay quiet regardless of `-w`. |
|
|
53
|
+
| `jruby.openssl.log.logger` | default stdout/stderr logger | Selects the internal logger implementation, set to `JUL` to route logs through `java.util.logging`. |
|
|
54
|
+
| `jruby.openssl.log.silence` | `true` | Silences a few noisy BC / BC-JSSE loggers by default, set `false` to leave their levels untouched. |
|
|
55
|
+
| `jruby.openssl.provider.ssl` | `BCJSSE` | Selects the SSL provider. `BCJSSE`, `BC`, or `true` all mean BC-JSSE, an empty string or `false` falls back to the platform JSSE provider. |
|
|
56
|
+
| `jruby.openssl.ssl.error_wait_nonblock.backtrace` | falls back to `jruby.errno.backtrace` (which defaults to `false`) | Whether `SSLErrorWaitReadable` / `SSLErrorWaitWritable` carry backtraces. |
|
|
57
|
+
| `jruby.openssl.x509.lookup.cache` | disabled | Caching for X.509 lookup results. `true` turns on a soft cache; an integer such as `8` gives a bounded strong/soft cache of that size, unset or `false` disables it. |
|
|
58
|
+
|
|
59
|
+
### Environment variables
|
|
60
|
+
|
|
61
|
+
| Variable | Default | Effect |
|
|
62
|
+
|----------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
63
|
+
| `SSL_CERT_FILE` | platform / packaged default CA file | Overrides the default certificate bundle used for X.509 default-path loading, `.crt`, `.cer`, or `.pem` are read as a PEM bundle, otherwise treated as a Java CA store path. |
|
|
64
|
+
| `SSL_CERT_DIR` | platform / packaged default CA directory | Overrides the default certificate directory list for X.509 default-path loading, separate multiple directories with the platform path separator. |
|
|
65
|
+
| `OPENSSL_ALLOW_PROXY_CERTS` | unset / disabled | When set to anything other than `false`, proxy certificates are allowed during certificate chain validation. |
|
|
66
|
+
|
|
67
|
+
### Other supported customizations
|
|
68
|
+
|
|
69
|
+
- `OpenSSL.debug = true` gives you the same internal debug logging as `-Djruby.openssl.debug=true`
|
|
70
|
+
- when `jruby.openssl.warn` is unset, JRuby's own warning mode (`ruby -w`) decides whether warnings show
|
|
71
|
+
- `OpenSSL::Config` can look up variables from the process environment through the `ENV` section, matching the upstream Ruby OpenSSL config parser
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
## Differences from OpenSSL
|
|
75
|
+
|
|
76
|
+
JRuby-OpenSSL aims to be a source-compatible drop-in for MRI's `openssl` - same Ruby API and
|
|
77
|
+
same `require 'openssl'`. But there are limitations on the JVM (with JCE and JSSE) as well as
|
|
78
|
+
Bouncy Castle libraries, so some entry points are unavailable, behave differently, or are no-ops.
|
|
79
|
+
|
|
80
|
+
**Engine**
|
|
81
|
+
- `OpenSSL::Engine` is not implemented - there is no hardware/engine layer, `OpenSSL::Engine.*`
|
|
82
|
+
raises `NameError` (uninitialized constant)
|
|
83
|
+
|
|
84
|
+
**SSL / TLS** (backed by JSSE)
|
|
85
|
+
- `SSLSocket#state` and NPN (`#npn_protocol`) are unimplemented and return `nil` - use ALPN instead
|
|
86
|
+
- Forced session resumption (`SSLSocket#session=`) is best-effort and only fully works with the
|
|
87
|
+
BouncyCastle JSSE provider; `session_reused?` may return `nil` ("can't decide")
|
|
88
|
+
- `SSL::Session#id=` / `#time=` are no-ops; `SSL::Session.new` on a non-socket raises `NotImplementedError`
|
|
89
|
+
- Hostname / `subjectAltName` matching runs over Java's certificate parsing and can differ from
|
|
90
|
+
MRI's `GeneralName` handling in edge cases
|
|
91
|
+
|
|
92
|
+
**Cipher** (JCE / Bouncy Castle)
|
|
93
|
+
- The available cipher set is provider-dependent (what JCE/BC offer on your JVM), not the fixed
|
|
94
|
+
libcrypto list (some OpenSSL ciphers may be missing or vary by JDK)
|
|
95
|
+
- CFB1 mode (`*-cfb1`) is excluded (doesn't match OpenSSL under BC)
|
|
96
|
+
- AEAD is limited to what JCE exposes; `iv_len=` on a non-AEAD cipher raises
|
|
43
97
|
|
|
44
|
-
|
|
45
|
-
|
|
98
|
+
**PKey** (EC / DH / EdDSA)
|
|
99
|
+
- EC is limited to prime curves (`:GFp`); binary-field curves (`:GF2m`) fail
|
|
100
|
+
- `EC::Point#mul` with array arguments, `:hybrid` point compression, and encrypted EC private-key
|
|
101
|
+
export are not implemented
|
|
102
|
+
- `DH#set_pqg` accepts but silently ignores the `q` parameter
|
|
103
|
+
- EdDSA (`Ed25519` / `Ed448`) rejects digest arguments
|
|
46
104
|
|
|
47
|
-
|
|
48
|
-
|
|
105
|
+
**X509**
|
|
106
|
+
- multi-valued RDNs (the `+` separator in a DN string) are not supported and raise `X509::NameError`.
|
|
107
|
+
- few `authorityKeyIdentifier` extension configurations are unsupported
|
|
49
108
|
|
|
50
|
-
|
|
109
|
+
**Random**
|
|
110
|
+
- randomness comes from the JVM's `SecureRandom`; the EGD and seed-file APIs (`Random.egd`,
|
|
111
|
+
`egd_bytes`, `load_random_file`, `write_random_file`) are no-ops
|
|
51
112
|
|
|
52
|
-
|
|
53
|
-
|
|
113
|
+
**Other**
|
|
114
|
+
- `OpenSSL.fips_mode = true` raises `NotImplementedError` unless the separate [FIPS variant](#fips)
|
|
115
|
+
gem is installed
|
|
116
|
+
- some rarely-used entry points are no-ops (`OpenSSL.check_func`, `deprecated_warning_flag`) and
|
|
117
|
+
`OPENSSL_NO_SOCK` is `nil` rather than a boolean
|
|
118
|
+
- a few PKCS7 content types can't be reconstructed purely from ASN.1 (may surface when parsing
|
|
119
|
+
some S/MIME structures)
|
|
54
120
|
|
|
55
|
-
|
|
121
|
+
Hitting something not listed here that MRI's OpenSSL supports?
|
|
122
|
+
Please report it on the [bug tracker][2], ideally with a test case.
|
|
56
123
|
|
|
57
|
-
|
|
124
|
+
## FIPS
|
|
58
125
|
|
|
59
|
-
|
|
126
|
+
A FIPS 140-3 build of jruby-openssl is available as a separate gem.
|
|
127
|
+
It's the very same library but uses the NIST-validated BC FIPS module (BC-FJA) instead of
|
|
128
|
+
regular Bouncy Castle, for deployments that need a validated cryptographic module.
|
|
129
|
+
Ships separately under GPL 3.0, with commercial licensing available - see the
|
|
130
|
+
[FIPS variant][6] wiki page for details.
|
|
60
131
|
|
|
61
|
-
NOTE:
|
|
132
|
+
NOTE: unlike C OpenSSL, `OpenSSL.fips_mode` cannot be changed at runtime, the flag reports
|
|
133
|
+
which gem variant is activated (`true` under the FIPS gem, `false` otherwise).
|
|
62
134
|
|
|
63
135
|
## License
|
|
64
136
|
|
|
65
|
-
(c) 2009-2026 JRuby distributed under EPL 1.0/GPL 2.0/LGPL 2.1
|
|
137
|
+
(c) 2009-2026 JRuby distributed under EPL 1.0 / GPL 2.0 / LGPL 2.1
|
|
66
138
|
|
|
67
139
|
[0]: https://github.com/jruby/jruby-openssl/security
|
|
68
140
|
[1]: https://github.com/jruby/jruby/wiki/MailingLists
|
|
@@ -70,3 +142,4 @@ NOTE: you can pick any JRuby version which is on [Maven Central][4] or on [ci.jr
|
|
|
70
142
|
[3]: https://github.com/jruby/jruby-openssl/tree/master/integration
|
|
71
143
|
[4]: https://repo1.maven.org/maven2/org/jruby/
|
|
72
144
|
[5]: https://www.jruby.org/nightly
|
|
145
|
+
[6]: https://github.com/jruby/jruby-openssl/wiki/FIPS
|
data/Rakefile
CHANGED
|
@@ -1,57 +1,108 @@
|
|
|
1
|
-
|
|
1
|
+
require 'rake/testtask'
|
|
2
|
+
|
|
3
|
+
mvnw = File.expand_path('./mvnw', File.dirname(__FILE__))
|
|
4
|
+
|
|
5
|
+
# reproducible build: SOURCE_DATE_EPOCH shared by jopenssl.jar and gem
|
|
6
|
+
# read from env by RubyGems; pass via -D so dev builds don't churn pom.xml
|
|
7
|
+
def source_date_epoch!
|
|
8
|
+
ENV['SOURCE_DATE_EPOCH'] ||= `git log -1 --pretty=%ct`.strip
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def _build_output_timestamp
|
|
12
|
+
"-Dproject.build.outputTimestamp=#{ENV['SOURCE_DATE_EPOCH']}" if ENV['SOURCE_DATE_EPOCH']
|
|
13
|
+
end
|
|
2
14
|
|
|
3
|
-
#Rake::Task[:jar].clear rescue nil
|
|
4
15
|
desc "Package jopenssl.jar with the compiled classes"
|
|
5
16
|
task :jar do
|
|
6
|
-
sh(
|
|
17
|
+
sh("#{mvnw} prepare-package -Dmaven.test.skip=true")
|
|
7
18
|
end
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
sh( './mvnw package -Dmaven.test.skip=true' )
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
task :test_prepare do
|
|
15
|
-
sh( './mvnw prepare-package -Dmaven.test.skip=true' )
|
|
16
|
-
sh( './mvnw test-compile' ) # separate step due -Dmaven.test.skip=true
|
|
19
|
+
|
|
20
|
+
task :test_prepare => :jar do
|
|
21
|
+
sh("#{mvnw} test-compile") # separate due -Dmaven.test.skip=true
|
|
17
22
|
end
|
|
18
23
|
|
|
19
24
|
task :clean do
|
|
20
|
-
sh(
|
|
25
|
+
sh("#{mvnw} clean")
|
|
21
26
|
end
|
|
22
27
|
|
|
23
28
|
task :build do
|
|
24
|
-
|
|
29
|
+
source_date_epoch!
|
|
30
|
+
sh("#{mvnw} -Prelease -DupdateReleaseInfo=true #{_build_output_timestamp} clean package")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc "Sanity-check the tree/version, then build a reproducible release gem"
|
|
34
|
+
task :release => :release_check do
|
|
35
|
+
source_date_epoch! # pin to the release commit so the gem + jar use the same
|
|
36
|
+
puts "SOURCE_DATE_EPOCH=#{ENV['SOURCE_DATE_EPOCH']} (#{Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).utc})"
|
|
37
|
+
Rake::Task[:build].invoke
|
|
38
|
+
gem = Dir['target/*.gem', 'pkg/*.gem'].max_by { |f| File.mtime(f) }
|
|
39
|
+
abort "release aborted - no .gem produced" unless gem
|
|
40
|
+
puts "built #{gem}"
|
|
41
|
+
# gem push #{gem} (or: #{File.basename(mvnw)} deploy -Pjar-release for the jar artifact)"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
task :release_check do
|
|
45
|
+
dirty = `git status --porcelain`.strip
|
|
46
|
+
abort "release aborted - working tree is not clean:\n#{dirty}" unless dirty.empty?
|
|
47
|
+
|
|
48
|
+
load File.expand_path('lib/jopenssl/version.rb', File.dirname(__FILE__))
|
|
49
|
+
version = JOpenSSL::VERSION
|
|
50
|
+
|
|
51
|
+
if Gem::Version.new(version).prerelease? && ENV['PRERELEASE'] != 'true'
|
|
52
|
+
abort "release aborted - #{version} is a prerelease"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
branch = `git rev-parse --abbrev-ref HEAD`.strip
|
|
56
|
+
warn "WARNING: releasing from '#{branch}' (not 'master')" unless branch == 'master'
|
|
57
|
+
|
|
58
|
+
tag = `git tag --points-at HEAD`.split("\n").find { |t| t =~ /#{Regexp.escape(version)}/ }
|
|
59
|
+
warn "WARNING: no git tag matching #{version} points at HEAD" unless tag
|
|
60
|
+
|
|
61
|
+
puts "release checks passed for #{version}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
desc "Build the self-contained jar-release artifacts (-Pjar-release)"
|
|
65
|
+
task :jar_release => :release_check do
|
|
66
|
+
source_date_epoch!
|
|
67
|
+
puts "SOURCE_DATE_EPOCH=#{ENV['SOURCE_DATE_EPOCH']} (#{Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).utc})"
|
|
68
|
+
sh("#{mvnw} package -Pjar-release -Dmaven.test.skip=true #{_build_output_timestamp}")
|
|
69
|
+
# deploy (gpg-sign + push): #{File.basename(mvnw)} deploy -Prelease,jar-release -D...
|
|
25
70
|
end
|
|
26
71
|
|
|
27
72
|
task :default => :build
|
|
28
73
|
|
|
29
|
-
file('lib/jopenssl.jar') { Rake::Task[
|
|
74
|
+
file('lib/jopenssl.jar') { Rake::Task[:jar].invoke }
|
|
75
|
+
|
|
76
|
+
file('pkg/test-classes/org/jruby/ext/openssl/SecurityHelperTest.class') do
|
|
77
|
+
Rake::Task[:test_prepare].invoke
|
|
78
|
+
end
|
|
30
79
|
|
|
31
|
-
require 'rake/testtask'
|
|
32
80
|
Rake::TestTask.new do |task|
|
|
33
|
-
task.libs << File.expand_path('
|
|
34
|
-
test_files = FileList['
|
|
35
|
-
task.test_files = test_files.map { |path| path.sub('
|
|
81
|
+
task.libs << File.expand_path('test', File.dirname(__FILE__))
|
|
82
|
+
test_files = FileList['test/**/test*.rb'].to_a
|
|
83
|
+
task.test_files = test_files.map { |path| path.sub('test/', '') }
|
|
36
84
|
task.verbose = false # using -v directly instead due issues with rake
|
|
37
85
|
task.loader = :direct
|
|
38
|
-
task.ruby_opts = [ '-v', '-
|
|
86
|
+
task.ruby_opts = [ '-v', '-rbundler/setup' ]
|
|
39
87
|
end
|
|
40
|
-
task :test => 'lib/jopenssl.jar'
|
|
88
|
+
task :test => ['lib/jopenssl.jar', 'pkg/test-classes/org/jruby/ext/openssl/SecurityHelperTest.class']
|
|
89
|
+
|
|
90
|
+
require_relative 'tasks/vendor_tests'
|
|
91
|
+
define_vendor_test_tasks # root + jopenssl_lib default to this tree
|
|
41
92
|
|
|
42
93
|
namespace :integration do
|
|
43
|
-
it_path = File.expand_path('
|
|
94
|
+
it_path = File.expand_path('integration', File.dirname(__FILE__))
|
|
44
95
|
task :install do
|
|
45
96
|
ruby "-C #{it_path} -S bundle install"
|
|
46
97
|
end
|
|
47
|
-
|
|
98
|
+
desc "Run tests via invoker (bc-compat)"
|
|
48
99
|
task :test => 'lib/jopenssl.jar' do
|
|
49
100
|
unless File.exist?(File.join(it_path, 'Gemfile.lock'))
|
|
50
|
-
|
|
101
|
+
fail "bundle not installed, run `rake integration:install'"
|
|
51
102
|
end
|
|
52
103
|
loader = "ARGV.each { |file| require(file) }"
|
|
53
104
|
lib = [ File.expand_path('../lib', __FILE__), it_path ]
|
|
54
|
-
test_files = FileList['
|
|
55
|
-
ruby "-I#{lib.join(':')} -C
|
|
105
|
+
test_files = FileList['integration/*_test.rb'].map { |path| path.sub('integration/', '') }
|
|
106
|
+
ruby "-I#{lib.join(':')} -C integration -e \"#{loader}\" #{test_files.map { |f| "\"#{f}\"" }.join(' ')}"
|
|
56
107
|
end
|
|
57
108
|
end
|
data/lib/jopenssl/load.rb
CHANGED
|
@@ -1,71 +1,27 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative 'version'
|
|
2
2
|
|
|
3
|
-
# NOTE: assuming user does pull in BC .jars from somewhere else on the
|
|
4
|
-
|
|
3
|
+
# NOTE: assuming user does pull in BC .jars from somewhere else on the class-path
|
|
4
|
+
if ENV_JAVA['jruby.openssl.load.jars'] != 'false' &&
|
|
5
|
+
java.security.Security.getProvider('BC').nil?
|
|
5
6
|
version = JOpenSSL::BOUNCY_CASTLE_VERSION
|
|
6
|
-
begin
|
|
7
|
-
require '
|
|
8
|
-
# if we have jar-dependencies we let it track the jars
|
|
7
|
+
bc_jars = begin
|
|
8
|
+
require 'jar_dependencies' unless respond_to?(:require_jar, true)
|
|
9
9
|
require_jar 'org.bouncycastle', 'bcprov-jdk18on', version
|
|
10
10
|
require_jar 'org.bouncycastle', 'bcpkix-jdk18on', version
|
|
11
11
|
require_jar 'org.bouncycastle', 'bcutil-jdk18on', version
|
|
12
12
|
require_jar 'org.bouncycastle', 'bctls-jdk18on', version
|
|
13
|
-
|
|
13
|
+
true
|
|
14
14
|
rescue LoadError, RuntimeError
|
|
15
|
-
|
|
15
|
+
false
|
|
16
16
|
end
|
|
17
17
|
unless bc_jars
|
|
18
|
-
|
|
19
|
-
load "org/bouncycastle/
|
|
20
|
-
load "org/bouncycastle/
|
|
21
|
-
load "org/bouncycastle/
|
|
18
|
+
vendor = File.expand_path('../../vendor', __dir__)
|
|
19
|
+
load "#{vendor}/org/bouncycastle/bcprov-jdk18on/#{version}/bcprov-jdk18on-#{version}.jar"
|
|
20
|
+
load "#{vendor}/org/bouncycastle/bcpkix-jdk18on/#{version}/bcpkix-jdk18on-#{version}.jar"
|
|
21
|
+
load "#{vendor}/org/bouncycastle/bcutil-jdk18on/#{version}/bcutil-jdk18on-#{version}.jar"
|
|
22
|
+
load "#{vendor}/org/bouncycastle/bctls-jdk18on/#{version}/bctls-jdk18on-#{version}.jar"
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
|
|
25
26
|
require 'jopenssl.jar'
|
|
26
27
|
JRuby::Util.load_ext('org.jruby.ext.openssl.OpenSSL')
|
|
27
|
-
|
|
28
|
-
# NOTE: content bellow should live in *lib/openssl.rb* but due RubyGems/Bundler
|
|
29
|
-
# `autoload :OpenSSL` this will cause issues if an older version (0.11) is the
|
|
30
|
-
# default gem under JRuby 9.2 (which on auto-load does not trigger a dynamic
|
|
31
|
-
# require - this is only fixed in JRuby 9.3)
|
|
32
|
-
|
|
33
|
-
module OpenSSL
|
|
34
|
-
autoload :Config, 'openssl/config' unless const_defined?(:Config, false)
|
|
35
|
-
autoload :ConfigError, 'openssl/config' unless const_defined?(:ConfigError, false)
|
|
36
|
-
autoload :PKCS12, 'openssl/pkcs12'
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
=begin
|
|
40
|
-
= Info
|
|
41
|
-
'OpenSSL for Ruby 2' project
|
|
42
|
-
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
|
43
|
-
All rights reserved.
|
|
44
|
-
|
|
45
|
-
= Licence
|
|
46
|
-
This program is licensed under the same licence as Ruby.
|
|
47
|
-
(See the file 'LICENCE'.)
|
|
48
|
-
=end
|
|
49
|
-
|
|
50
|
-
require 'openssl/bn'
|
|
51
|
-
require 'openssl/pkey'
|
|
52
|
-
require 'openssl/cipher'
|
|
53
|
-
require 'openssl/digest'
|
|
54
|
-
require 'openssl/hmac'
|
|
55
|
-
require 'openssl/x509'
|
|
56
|
-
require 'openssl/ssl'
|
|
57
|
-
require 'openssl/pkcs5'
|
|
58
|
-
|
|
59
|
-
module OpenSSL
|
|
60
|
-
# call-seq:
|
|
61
|
-
# OpenSSL.secure_compare(string, string) -> boolean
|
|
62
|
-
#
|
|
63
|
-
# Constant time memory comparison. Inputs are hashed using SHA-256 to mask
|
|
64
|
-
# the length of the secret. Returns +true+ if the strings are identical,
|
|
65
|
-
# +false+ otherwise.
|
|
66
|
-
def self.secure_compare(a, b)
|
|
67
|
-
hashed_a = OpenSSL::Digest.digest('SHA256', a)
|
|
68
|
-
hashed_b = OpenSSL::Digest.digest('SHA256', b)
|
|
69
|
-
OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
|
|
70
|
-
end
|
|
71
|
-
end
|
data/lib/jopenssl/version.rb
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module JOpenSSL
|
|
2
|
-
VERSION = '0.
|
|
3
|
-
BOUNCY_CASTLE_VERSION = '1.
|
|
4
|
-
end
|
|
5
|
-
|
|
6
|
-
Object.class_eval do
|
|
7
|
-
Jopenssl = JOpenSSL
|
|
8
|
-
private_constant :Jopenssl if respond_to?(:private_constant)
|
|
9
|
-
deprecate_constant :Jopenssl if respond_to?(:deprecate_constant)
|
|
3
|
+
VERSION = '0.19.0'
|
|
4
|
+
BOUNCY_CASTLE_VERSION = '1.85'
|
|
10
5
|
end
|
data/lib/jopenssl.jar
CHANGED
|
Binary file
|
data/lib/openssl/config.rb
CHANGED
|
@@ -80,7 +80,9 @@ module OpenSSL
|
|
|
80
80
|
section = 'default'
|
|
81
81
|
data = {section => {}}
|
|
82
82
|
io_stack = [io]
|
|
83
|
-
|
|
83
|
+
# absolute paths of the currently-open .include chain, to break include cycles
|
|
84
|
+
included = [nil]
|
|
85
|
+
while definition = get_definition(io_stack, included)
|
|
84
86
|
definition = clear_comments(definition)
|
|
85
87
|
next if definition.empty?
|
|
86
88
|
case definition
|
|
@@ -100,11 +102,16 @@ module OpenSSL
|
|
|
100
102
|
end
|
|
101
103
|
|
|
102
104
|
files.each do |filename|
|
|
105
|
+
real = File.expand_path(filename)
|
|
106
|
+
if included.include?(real)
|
|
107
|
+
raise ConfigError, "include cycle detected: '%s'" % filename
|
|
108
|
+
end
|
|
103
109
|
begin
|
|
104
110
|
io_stack << StringIO.new(File.read(filename))
|
|
105
111
|
rescue
|
|
106
112
|
raise ConfigError, "could not include file '%s'" % filename
|
|
107
113
|
end
|
|
114
|
+
included << real
|
|
108
115
|
end
|
|
109
116
|
when /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/
|
|
110
117
|
if $2
|
|
@@ -229,10 +236,10 @@ module OpenSSL
|
|
|
229
236
|
scanned.join
|
|
230
237
|
end
|
|
231
238
|
|
|
232
|
-
def get_definition(io_stack)
|
|
233
|
-
if line = get_line(io_stack)
|
|
239
|
+
def get_definition(io_stack, included = nil)
|
|
240
|
+
if line = get_line(io_stack, included)
|
|
234
241
|
while /[^\\]\\\z/ =~ line
|
|
235
|
-
if extra = get_line(io_stack)
|
|
242
|
+
if extra = get_line(io_stack, included)
|
|
236
243
|
line += extra
|
|
237
244
|
else
|
|
238
245
|
break
|
|
@@ -242,12 +249,13 @@ module OpenSSL
|
|
|
242
249
|
end
|
|
243
250
|
end
|
|
244
251
|
|
|
245
|
-
def get_line(io_stack)
|
|
252
|
+
def get_line(io_stack, included = nil)
|
|
246
253
|
while io = io_stack.last
|
|
247
254
|
if line = io.gets
|
|
248
255
|
return line.gsub(/[\r\n]*/, '')
|
|
249
256
|
end
|
|
250
257
|
io_stack.pop
|
|
258
|
+
included.pop if included
|
|
251
259
|
end
|
|
252
260
|
end
|
|
253
261
|
end
|
data/lib/openssl/ssl.rb
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
|
|
13
13
|
require "openssl/buffering"
|
|
14
14
|
require "io/nonblock"
|
|
15
|
+
require "ipaddr"
|
|
15
16
|
require "socket"
|
|
16
17
|
|
|
17
18
|
module OpenSSL
|
|
@@ -84,7 +85,6 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
|
|
|
84
85
|
|
|
85
86
|
DEFAULT_CERT_STORE = OpenSSL::X509::Store.new # :nodoc:
|
|
86
87
|
DEFAULT_CERT_STORE.set_default_paths
|
|
87
|
-
DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL
|
|
88
88
|
|
|
89
89
|
# A callback invoked when DH parameters are required for ephemeral DH key
|
|
90
90
|
# exchange.
|
|
@@ -137,7 +137,7 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
|
|
|
137
137
|
# used.
|
|
138
138
|
def set_params(params={})
|
|
139
139
|
params = DEFAULT_PARAMS.merge(params)
|
|
140
|
-
self.options
|
|
140
|
+
self.options |= params.delete(:options) # set before min_version/max_version
|
|
141
141
|
params.each{ |name, value| self.__send__("#{name}=", value) }
|
|
142
142
|
if self.verify_mode != OpenSSL::SSL::VERIFY_NONE
|
|
143
143
|
unless self.ca_file or self.ca_path or self.cert_store
|
|
@@ -319,15 +319,10 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
|
|
|
319
319
|
#when 7 # iPAddress in GeneralName (RFC5280)
|
|
320
320
|
elsif /\AIP(?: Address)?:(.*)/ =~ general_name
|
|
321
321
|
should_verify_common_name = false
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
# begin
|
|
327
|
-
# return true if $1 == IPAddr.new(hostname).to_s
|
|
328
|
-
# rescue IPAddr::InvalidAddressError
|
|
329
|
-
# end
|
|
330
|
-
# end
|
|
322
|
+
begin
|
|
323
|
+
return true if IPAddr.new($1) == IPAddr.new(hostname)
|
|
324
|
+
rescue IPAddr::InvalidAddressError
|
|
325
|
+
end
|
|
331
326
|
end
|
|
332
327
|
}
|
|
333
328
|
}
|
|
@@ -431,6 +426,13 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
|
|
|
431
426
|
# This method MUST be called after calling #connect to ensure that the
|
|
432
427
|
# hostname of a remote peer has been verified.
|
|
433
428
|
def post_connection_check(hostname)
|
|
429
|
+
# if connect already verified this hostname (via verify_hostname), skip;
|
|
430
|
+
# avoids double-verification in libraries that call post_connection_check
|
|
431
|
+
if defined?(@verified_hostname) && @verified_hostname == hostname
|
|
432
|
+
@verified_hostname = nil
|
|
433
|
+
return true
|
|
434
|
+
end
|
|
435
|
+
|
|
434
436
|
if peer_cert.nil?
|
|
435
437
|
msg = "Peer verification enabled, but no certificate received."
|
|
436
438
|
if using_anon_cipher?
|
|
@@ -446,6 +448,14 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
|
|
|
446
448
|
return true
|
|
447
449
|
end
|
|
448
450
|
|
|
451
|
+
# @private JRuby due having to call this outside of post_connection_check
|
|
452
|
+
def verify_certificate_identity_internal(hostname)
|
|
453
|
+
peer_cert = self.peer_cert
|
|
454
|
+
return nil if peer_cert.nil?
|
|
455
|
+
OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname)
|
|
456
|
+
end
|
|
457
|
+
private :verify_certificate_identity_internal
|
|
458
|
+
|
|
449
459
|
# call-seq:
|
|
450
460
|
# ssl.session -> aSession
|
|
451
461
|
#
|
data/lib/openssl.rb
CHANGED
|
@@ -1,3 +1,46 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'jopenssl/load'
|
|
4
|
+
|
|
5
|
+
module OpenSSL
|
|
6
|
+
autoload :Config, 'openssl/config' unless const_defined?(:Config, false)
|
|
7
|
+
autoload :ConfigError, 'openssl/config' unless const_defined?(:ConfigError, false)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
=begin
|
|
11
|
+
= Info
|
|
12
|
+
'OpenSSL for Ruby 2' project
|
|
13
|
+
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
|
14
|
+
All rights reserved.
|
|
15
|
+
|
|
16
|
+
= Licence
|
|
17
|
+
This program is licensed under the same licence as Ruby.
|
|
18
|
+
(See the file 'COPYING'.)
|
|
19
|
+
=end
|
|
20
|
+
|
|
21
|
+
require 'openssl/bn'
|
|
22
|
+
require 'openssl/cipher'
|
|
23
|
+
require 'openssl/digest'
|
|
24
|
+
require 'openssl/hmac'
|
|
25
|
+
require 'openssl/pkcs5'
|
|
26
|
+
require 'openssl/pkey'
|
|
27
|
+
require 'openssl/ssl'
|
|
28
|
+
require 'openssl/x509'
|
|
29
|
+
|
|
30
|
+
module OpenSSL
|
|
31
|
+
# :call-seq:
|
|
32
|
+
# OpenSSL.secure_compare(string, string) -> true or false
|
|
33
|
+
#
|
|
34
|
+
# Constant time memory comparison. Inputs are hashed using SHA-256 to mask
|
|
35
|
+
# the length of the secret. Returns +true+ if the strings are identical,
|
|
36
|
+
# +false+ otherwise.
|
|
37
|
+
#
|
|
38
|
+
# This method is expensive due to the SHA-256 hashing. In most cases, where
|
|
39
|
+
# the input lengths are known to be equal or are not sensitive,
|
|
40
|
+
# OpenSSL.fixed_length_secure_compare should be used instead.
|
|
41
|
+
def self.secure_compare(a, b)
|
|
42
|
+
hashed_a = OpenSSL::Digest.digest('SHA256', a)
|
|
43
|
+
hashed_b = OpenSSL::Digest.digest('SHA256', b)
|
|
44
|
+
OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
|
|
45
|
+
end
|
|
46
|
+
end
|