-
Notifications
You must be signed in to change notification settings - Fork 87
FIPS
FIPS 140-3 variant of jruby-openssl.
Ships the unmodified BC-FJA module (NIST cert) and a FIPS-aware loader,
emulates the Ruby OpenSSL native library on top of BC-FIPS through JCE.
jruby-opensslvariant is not itself FIPS (140-3) validated, what carries FIPS compliance is the unmodified validated cryptographic module (bundled with the gem)
gem is not a full drop-in replacement, the
OpenSSLAPI surface is unchanged, in approved-only mode only FIPS-approved algorithms and parameters are exposed, code that reaches for a non-approved primitive raises instead of proceeding
gem install jruby-openssl-*.gemor preferably add it to your Gemfile e.g.
gem "jruby-openssl", source: "https://gem.coop/@jossl-fips"(J)Ruby's standard require 'openssl' than resolves to gem's loader, which:
- refuses to load if a non-FIPS BouncyCastle provider is already registered
- loads
bc-fips,bcutil-fips,bcpkix-fips,bctls-fipslibraries - delegates
OpenSSLcryptographic operations to the FIPS-variant provider
For NIST-validated operation, start the JVM with the BC-FIPS integrity self-test and approved-only mode, using the org.bouncycastle.fips.approved_only property:
JRUBY_OPTS='-J-Dorg.bouncycastle.fips.approved_only=true' ruby -ropenssl -e 'p OpenSSL.fips_mode'All the upstream jruby-openssl documentation
applies here as well — the OpenSSL API and the supported configuration knobs are the same.
This variant only swaps the regular Bouncy Castle backend for the FIPS-validated one, so the
rest of this README covers just the FIPS-specific parts.
| Property | Default | Effect |
|---|---|---|
org.bouncycastle.fips.approved_only |
unset by default; should be true in production FIPS use
|
BC-FIPS approved-only mode |
-
Legacy ciphers e.g.
OpenSSL::Cipher.new('des-cbc'),'bf-cbc'(Blowfish),'rc4','rc2-cbc','cast5-cbc','seed-cbc'are refused -
MD5 / MD4 as digests -
OpenSSL::Digest.new('MD5')and MD5-based key derivation (Cipher#pkcs5_keyivgen) are not approved -
Legacy encrypted PEM - MD5-based
DEK-Infoformat (olderOpenSSL::PKey.read(pem, pass)keys) cannot be read or written - Undersized keys / parameters e.g. RSA below 2048-bit and HMAC keys shorter than 112 bits
This gem ships the Bouncy Castle FIPS Java API (BC-FJA) along with its companion jars:
bc-fipsbcutil-fipsbcpkix-fipsbctls-fips
These are libraries Bouncy Castle publishes, shipped byte-for-byte as released: nothing is modified, repackaged or shaded - so the FIPS 140-3 HMAC-SHA2-256 integrity self-test built into the module is kept valid.
The BC-FIPS jars are Copyright (c) The Legion of the Bouncy Castle Inc. and are licensed under the Bouncy Castle Licence - see LICENSE.bouncycastle.
Further reading:
Bouncy Castle FIPS log via java.util.logging (JUL) JDK's built-in logging.
BC-JSSE (TLS implementation) is fairly chatty out of the box: it reports JDK-wide disabled-algorithm policy at first load and emits an INFO line per TLS handshake. Because JUL's default console handler prints INFO and above, these would show up on stderr in an otherwise quiet application.
By default, jruby-openssl adjusts the level on exactly those known-noisy loggers
(init-time reports to SEVERE and per-handshake logs to WARNING so genuine protocol
problems are still visible). This silencing is skipped when you have configured JUL
yourself e.g. using a java.util.logging.config.file and can also be turned off
explicitly with -Djruby.openssl.log.silence=false.
Any BC logger can then be tuned the usual JUL way, in your logging.properties:
org.bouncycastle.jsse.provider.ProvTlsClient.level = FINEjruby-openssl has its own small logger facade, that defaults to the process output
and is gated by setting OpenSSL.debug = true or -Djruby.openssl.debug=true.
This is convenient for quick debugging but isn't wired into any logging framework.
Since the FIPS module already logs through JUL, we recommend to switch jruby-openssl
logging to the JUL backend too, so both go to the same place with one configuration:
-Djruby.openssl.log.logger=jul
Messages are then emitted through java.util.logging under org.jruby.ext.openssl.*
logger names and are configured like any other JUL logger:
handlers = java.util.logging.ConsoleHandler
.level = INFO
# jruby-openssl internals
org.jruby.ext.openssl.level = FINE
java.util.logging.ConsoleHandler.level = FINEIt's the same OpenSSL API, only the cryptographic backend changes.
Regular jruby-openssl runs on the general-purpose Bouncy Castle (or the Java built-in)
provider, this variant runs on the FIPS-validated Bouncy Castle FIPS provider.
It ships as a separate gem, from a separate source, but under the same name
(jruby-openssl) so application code and require 'openssl' stay unchanged.
BC-FIPS is Bouncy Castle's FIPS 140-3 validated cryptographic module and Java API,
distinct from the regular BC provider jars.
The FIPS variant of the gem bundles the bc-fips, bcutil-fips, bcpkix-fips and
bctls-fips jars. Upstream releases live at downloads.bouncycastle.org/fips-java.
BC-FIPS is not the regular provider, it's a separate fork (branched from regular BC around 1.58), differences:
-
BouncyCastleFipsProvider("BC-FIPS") instead ofBouncyCastleProvider("BC"). -
No direct primitives - regular BC lets you instantiate engines/digests/signers from
org.bouncycastle.crypto.*, BC-FIPS replaces those with an approved-mode factory pattern where primitives can only be reached through approved services. - A validated module - "FIPS 140-3 validated" means an independent NIST-accredited lab tested the exact provider under NIST's CMVP: its algorithm implementations checked against NIST's known answer tests, key-management and self-test requirements, after which NIST issued certificate #4943.
- Divergent APIs (because of the fork and its requirement), e.g. ASN.1 and key classes differ in both names and types.
Standard (non-FIPS) jruby-openssl is built against regular BC, so it cannot simply load
the FIPS jars. This variant (and especially the parent) need to be aware of the subtle API
differences and potential illegal cryptographic operations and be adapted.
In approved-only mode BC-FIPS permits only FIPS-approved algorithms and parameters, so some
things (that work on regular jruby-openssl) are rejected:
- Legacy ciphers - DES/3DES-as-DES, Blowfish, CAST5/CAST6, RC2, RC4, SEED, and CFB-1 mode
-
MD5-based key derivation e.g.
Cipher#pkcs5_keyivgen(which defaults to MD5) - Undersized keys - RSA below 2048 bits for signing, HMAC keys shorter than 112 bits
An operation that BC-FIPS refuses surfaces as an OpenSSL error, not a silent downgrade — the
point of FIPS is that non-approved crypto fails closed.
No, jruby-openssl gem is not validated, the only validated artifact is the unmodified BC-FIPS module, responsible for all cryptographic operations. Using this gem in approved-only mode means your cryptography runs inside that validated module using approved algorithms: it does not certify your application, JVM, OS, or deployment. Overall FIPS claims remain your responsibility.
Gem is not published on rubygems.org, jruby-openssl name there belongs to the
non-FIPS artifact. The FIPS (open-source) variant is published to a separate source,
point your Gemfile at:
source 'https://rubygems.org'
gem 'jruby-openssl', source: 'https://gem.coop/@jossl-fips' # GPL-3.0 licensedThe commercial edition is distributed through a separate source, see COMMERCIAL.md for access and contact details.
Either way gem name stays jruby-openssl, it's a drop-in replacement for the default gem.
Packaging and maintaining the FIPS variant - a bundled validated module, a separate build,
a second artifact, and keeping all of it in step with the parent is a considerable amount
of ongoing work on top of jruby-openssl itself.
The dual GPL-3.0 + commercial model is how we are trying to gauge whether there is enough interest to sustain that work. Open-source and internal use are already covered by GPL-3.0 (see COMMERCIAL.md for what does and does not need a commercial license).
If the interest is not there, carrying FIPS support in the parent and shipping another
(separate) artifact may not be sustainable in the long run, and jruby-openssl as a whole
could eventually be retired in favor of a native C OpenSSL route on the JVM - with all the
packaging and deployment friction.
Commercial interest is a direct signal that jruby-openssl is worth continuing.
BC-FIPS can run in two states. In the default "general mode" it still exposes non-FIPS
approved algorithms and parameters, so you could unknowingly use non-compliant crypto.
Approved-only mode (-Dorg.bouncycastle.fips.approved_only=true) restricts the runtime
to the FIPS-approved algorithm set and key sizes (the actual FIPS operational state).
This gem assumes an approved-only default, see Approved-only mode for the flag.
For the FIPS variant to be a genuine drop-in, application code and transitive dependencies
must resolve the same gem name. RubyGems identifies a gem solely by name + version +
platform and neither platform nor a metadata field can act as a "variant" selector.
Thus the only way to be a true drop-in is to reuse the name jruby-openssl which is why
this is not published as a separate jruby-openssl-fips name, and why the gem comes
from a separate source.
With the name fixed there's extra metadata to be able to distinguish the gems installed locally, there's also a versioning convention. The FIPS gem mirrors the parent release it is built from and appends a fourth segment as its own version (revision) number:
Normal (jruby-openssl) |
FIPS (jruby-openssl) |
|---|---|
0.19.0 |
0.19.0.1, 0.19.0.2, … |
0.20.0 |
0.20.0.1, … |
The revision starts at 1 (a .0 would compare equal to the bare parent version).
This gem's customizations are (re-)licensed under GPL-3.0, see LICENSE. Commercial (non-GPL) licensing is available for organizations embedding this gem in proprietary or non-GPL products, see COMMERCIAL.md.
Generated from the jruby-openssl FIPS variant docs - edits made here will be overwritten.