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
Closed

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

drbrain opened this issue Jul 25, 2013 · 10 comments
Assignees
Milestone

Comments

@drbrain
Copy link

@drbrain 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
AES-256-CBC does not work for encrypting a key on JRuby, see jruby/jruby#919

Part of #606
@drbrain
Copy link
Author

@drbrain 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
Copy link
Contributor

@sluukkonen 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
Copy link
Member

@BanzaiMan BanzaiMan commented Sep 17, 2013

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

@BanzaiMan
Copy link
Member

@BanzaiMan 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
Copy link
Member

@headius 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
Copy link
Member

@BanzaiMan 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
Copy link
Member

@mkristian 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
Copy link
Member

@headius 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
Copy link
Member

@headius 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
Copy link
Member

@headius 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
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
6 participants