Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JRuby cannot decrypt a private key using the AES-256-CBC cipher #919

Closed
drbrain opened this Issue Jul 25, 2013 · 10 comments

Comments

Projects
None yet
6 participants
@drbrain
Copy link

drbrain commented Jul 25, 2013

JRuby should be able to decrypt keys using the same ciphers as Ruby, but fails for several common ciphers including AES-256-CBC.

While this script does not have proper setup for some of the ciphers (notably ECB mode), in general it shows which cipher families do and do not work on JRuby:

require 'openssl'

# https://bugs.ruby-lang.org/issues/8690
exclude = %w[
  AES-128-CBC-HMAC-SHA1
  AES-256-CBC-HMAC-SHA1
  aes-128-cbc-hmac-sha1
  aes-256-cbc-hmac-sha1
]

key = OpenSSL::PKey::RSA.new 1024

OpenSSL::Cipher.ciphers.each do |cipher_name|
  begin
    next if exclude.include? cipher_name

    print cipher_name

    cipher = OpenSSL::Cipher.new cipher_name
    encryption_key = cipher.random_key

    encrypted = key.export cipher, encryption_key

    OpenSSL::PKey::RSA.new encrypted, encryption_key

    puts " PASS"
  rescue
    puts " FAIL: #{$!}"
  end
end

My results with jruby 1.7.4 (1.9.3p392) 2013-05-16 2390d3b on Java HotSpot(TM) 64-Bit Server VM 1.7.0_10-ea-b16 [darwin-x86_64] for the AES ciphers:

$ jruby test.rb | grep AES
Unable to find a $JAVA_HOME at "/usr", continuing with system-provided Java...
AES-128 PASS
AES-128-CBC PASS
AES-128-CFB PASS
AES-128-CFB1 PASS
AES-128-CFB8 FAIL: Neither PUB key nor PRIV key:
AES-128-ECB FAIL: exception using cipher: java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV
AES-128-OFB PASS
AES-192 FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-192-CBC FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-192-CFB FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-192-CFB1 FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-192-CFB8 FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-192-ECB FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-192-OFB FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-256 FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-256-CBC FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-256-CFB FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-256-CFB1 FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-256-CFB8 FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-256-ECB FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size
AES-256-OFB FAIL: exception using cipher: java.security.InvalidKeyException: Illegal key size

With ruby 2.0.0p247:

$ ruby test.rb | grep AES
AES-128-CBC PASS
AES-128-CFB PASS
AES-128-CFB1 PASS
AES-128-CFB8 PASS
AES-128-CTR PASS
AES-128-ECB FAIL: Neither PUB key nor PRIV key: nested asn1 error
AES-128-OFB PASS
AES-128-XTS PASS
AES-192-CBC PASS
AES-192-CFB PASS
AES-192-CFB1 PASS
AES-192-CFB8 PASS
AES-192-CTR PASS
AES-192-ECB FAIL: Neither PUB key nor PRIV key: nested asn1 error
AES-192-OFB PASS
AES-256-CBC PASS
AES-256-CFB PASS
AES-256-CFB1 PASS
AES-256-CFB8 PASS
AES-256-CTR PASS
AES-256-ECB FAIL: Neither PUB key nor PRIV key: nested asn1 error
AES-256-OFB PASS
AES-256-XTS PASS
AES128 PASS
AES192 PASS
AES256 PASS

drbrain added a commit to rubygems/rubygems that referenced this issue Jul 25, 2013

Encrypt test key with DES-CBC for JRuby
AES-256-CBC does not work for encrypting a key on JRuby, see jruby/jruby#919

Part of #606
@drbrain

This comment has been minimized.

Copy link
Author

drbrain commented Jul 25, 2013

Installing the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files I see the AES-192 and AES-256 ciphers pass except for CFB8.

Thanks to sluukkonen1 on #jruby for pointing me in this direction.

If the ciphers don't work without the altered policy files perhaps JRuby should remove them from the ciphers list?

@sluukkonen

This comment has been minimized.

Copy link
Contributor

sluukkonen commented Jul 25, 2013

Alternatively, JRuby could at least print a warning message telling the user to install the JCE Unlimited files.

@ghost ghost assigned nahi Jul 26, 2013

@BanzaiMan

This comment has been minimized.

Copy link
Member

BanzaiMan commented Sep 17, 2013

See also http://jira.codehaus.org/browse/JRUBY-7093. This directly impacts usefulness of Rails 4.

@BanzaiMan

This comment has been minimized.

Copy link
Member

BanzaiMan commented Sep 17, 2013

http://www.bouncycastle.org/wiki/display/JA1/Frequently+Asked+Questions leads me to believe that this is a limitation imposed by JVM which we probably cannot overcome.

@headius

This comment has been minimized.

Copy link
Member

headius commented Sep 17, 2013

So I investigated this nonsense and it turns out to be even stupider than I thought. The "unlimited strength jurisdiction policy files" you download from Oracle contain nothing more than security policies enabling the use of higher-strength crypto.

Specifically, they replace the default_local.policy file from $JAVA_HOME/jre/lib/security/local_policy.jar:

// Some countries have import limits on crypto strength. This policy file
// is worldwide importable.

grant {
    permission javax.crypto.CryptoPermission "DES", 64;
    permission javax.crypto.CryptoPermission "DESede", *;
    permission javax.crypto.CryptoPermission "RC2", 128, 
                                     "javax.crypto.spec.RC2ParameterSpec", 128;
    permission javax.crypto.CryptoPermission "RC4", 128;
    permission javax.crypto.CryptoPermission "RC5", 128, 
          "javax.crypto.spec.RC5ParameterSpec", *, 12, *;
    permission javax.crypto.CryptoPermission "RSA", *;
    permission javax.crypto.CryptoPermission *, 128;
};

With one that looks the same as the already existing default_US_export.policy from from US_export_policy.jar in the same dir:

// Manufacturing policy file.
grant {
    // There is no restriction to any algorithms.
    permission javax.crypto.CryptoAllPermission; 
};

So it's actually possible, via a couple trivial commands, to "upgrade" a local JDK to support unlimited-strength crypto without doing the download.

Now here's where it gets slippery. Would we violate some stupid crypto export law by simply providing a gem you can install that rewrites the crypto policy jars? The fact that the limitation is imposed solely by configuration is pretty stupid.

@BanzaiMan

This comment has been minimized.

Copy link
Member

BanzaiMan commented Sep 17, 2013

@headius I agree in principle that this is an arbitrary legal restriction rather than a technical one. At the same time, I argue that it is not in our best interest to do anything from our end. In the eyes of the law, I suspect that the end user taking a deliberate action to remove the restriction goes a long way.

As for printing a warning, unless we can precisely determine when to issue them, I don't think it is feasible to do it.

@mkristian

This comment has been minimized.

Copy link
Member

mkristian commented Sep 17, 2013

can I as German living in the UK publish such a gem ? personally I see no
reason why not.

@headius

This comment has been minimized.

Copy link
Member

headius commented Sep 17, 2013

mkristian: Yes, probably can. See discussion on #jruby today or http://wiki.jruby.org/UnlimitedStrengthCrypto for a Ruby one-liner that disables the restriction.

headius added a commit that referenced this issue Sep 17, 2013

@headius

This comment has been minimized.

Copy link
Member

headius commented Sep 17, 2013

@sluukkonen The commit above attempts to improve the error message to point at a new wiki page describing the fix: http://wiki.jruby.org/UnlimitedStrengthCrypto. Thanks for the idea.

@headius

This comment has been minimized.

Copy link
Member

headius commented Sep 17, 2013

JRuby 1.7.5 will have a better error message providing instructions on fixing this with either the JCE files or with a Java integration hack, and Rails should hopefully work around this in rails/rails#12256. Closing this for now.

@headius headius closed this Sep 17, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.