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

EC keys seem to be unsupported #2454

Closed
adam-bishop opened this Issue Jul 5, 2016 · 6 comments

Comments

Projects
None yet
7 participants
@adam-bishop

adam-bishop commented Jul 5, 2016

I've defined a secure TCP input using the UI, and tried to use an ECDSA keypair. This fails due to the exception below.

I've had a quick look at the code (transports/util/KeyUtil.java).

From my reading of the code, it seems a keyspec is correctly created (IllegalArgumentException isn't thrown), but because the keyfactory has 'RSA' hard coded (and it's an ECDSA key) generatePrivate() fails.

I guess the fix would be to to replace the hardcoded 'RSA' with a section to detect the algorithm in use (getAlgName() like in createKeySpec()?)

Steps to reproduce the problem

  • Load an ECDSA keypair onto the system
  • Create an input with a secure TCP transport using these keys
  • Try to connect
  • Exceptions logged to console

Environment

  • Graylog Version: 2.0.3-1
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: Invalid RSA private key
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217) ~[?:1.8.0_91]
    at java.security.KeyFactory.generatePrivate(KeyFactory.java:372) ~[?:1.8.0_91]
    at org.graylog2.plugin.inputs.transports.util.KeyUtil.loadPrivateKey(KeyUtil.java:153) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.util.KeyUtil.initKeyStore(KeyUtil.java:111) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.AbstractTcpTransport$1.createSslEngine(AbstractTcpTransport.java:205) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.AbstractTcpTransport$1.call(AbstractTcpTransport.java:186) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.AbstractTcpTransport$1.call(AbstractTcpTransport.java:182) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.NettyTransport$1.getPipeline(NettyTransport.java:110) ~[graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.NioServerBoss.registerAcceptedChannel(NioServerBoss.java:134) [graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.NioServerBoss.process(NioServerBoss.java:104) [graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:337) [graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42) [graylog.jar:?]
    at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) [graylog.jar:?]
    at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) [graylog.jar:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_91]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_91]
    at java.lang.Thread.run(Thread.java:745) [?:1.8.0_91]
Caused by: java.security.InvalidKeyException: Invalid RSA private key
    at sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:206) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:342) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213) ~[?:1.8.0_91]
    ... 16 more
Caused by: java.io.IOException: Version must be 0
    at sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:192) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:342) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213) ~[?:1.8.0_91]
    ... 16 more
2016-07-05T14:19:59.466Z INFO  [connection] Opened connection [connectionId{localValue:9, serverValue:14466}] to localhost:27017
2016-07-05T14:20:33.164Z WARN  [AbstractNioSelector] Failed to initialize an accepted socket.
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: Invalid RSA private key
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:217) ~[?:1.8.0_91]
    at java.security.KeyFactory.generatePrivate(KeyFactory.java:372) ~[?:1.8.0_91]
    at org.graylog2.plugin.inputs.transports.util.KeyUtil.loadPrivateKey(KeyUtil.java:153) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.util.KeyUtil.initKeyStore(KeyUtil.java:111) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.AbstractTcpTransport$1.createSslEngine(AbstractTcpTransport.java:205) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.AbstractTcpTransport$1.call(AbstractTcpTransport.java:186) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.AbstractTcpTransport$1.call(AbstractTcpTransport.java:182) ~[graylog.jar:?]
    at org.graylog2.plugin.inputs.transports.NettyTransport$1.getPipeline(NettyTransport.java:110) ~[graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.NioServerBoss.registerAcceptedChannel(NioServerBoss.java:134) [graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.NioServerBoss.process(NioServerBoss.java:104) [graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:337) [graylog.jar:?]
    at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42) [graylog.jar:?]
    at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108) [graylog.jar:?]
    at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) [graylog.jar:?]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_91]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_91]
    at java.lang.Thread.run(Thread.java:745) [?:1.8.0_91]
Caused by: java.security.InvalidKeyException: Invalid RSA private key
    at sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:206) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:342) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213) ~[?:1.8.0_91]
    ... 16 more
Caused by: java.io.IOException: Version must be 0
    at sun.security.rsa.RSAPrivateCrtKeyImpl.parseKeyBits(RSAPrivateCrtKeyImpl.java:192) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:342) ~[?:1.8.0_91]
    at sun.security.pkcs.PKCS8Key.decode(PKCS8Key.java:356) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:91) ~[?:1.8.0_91]
    at sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:75) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:316) ~[?:1.8.0_91]
    at sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:213) ~[?:1.8.0_91]
    ... 16 more

@jalogisch jalogisch added this to the 2.1.0 milestone Jul 11, 2016

@mikkolehtisalo

This comment has been minimized.

Contributor

mikkolehtisalo commented Jul 19, 2016

Can reproduce this by creating dummy DSA keys:

openssl dsaparam -out dsaparam.pem 2048
openssl gendsa -out dsaprivkey.pem dsaparam.pem
openssl req -new -x509 -key dsaprivkey.pem -out dsacert.pem
openssl pkcs8 -topk8 -inform PEM -outform DER -in dsaprivkey.pem -out dsaprivkey.der -nocrypt

where dsacert.pem will be the certificate, and dsaprivkey.der the private key.

Detecting key type requires parsing it. Easiest fix is to attempt DSA if RSA threw InvalidKeySpecException, the "proper" fix might be to rewrite the method by switching to Bouncy Castle's PEMParser which can read automatically about anything. I will offer the quick and dirty fix by pull request, sans tests.

I got DSA keys working:

# echo -n | openssl s_client -connect localhost:12206
CONNECTED(00000003)
depth=0 C = FI, ST = Some-State, O = Internet Widgits Pty Ltd, CN = graylog.local
verify error:num=18:self signed certificate
verify return:1
depth=0 C = FI, ST = Some-State, O = Internet Widgits Pty Ltd, CN = graylog.local
verify return:1
---
Certificate chain
 0 s:/C=FI/ST=Some-State/O=Internet Widgits Pty Ltd/CN=graylog.local
   i:/C=FI/ST=Some-State/O=Internet Widgits Pty Ltd/CN=graylog.local
---
Server certificate
-----BEGIN CERTIFICATE-----
blahblah
-----END CERTIFICATE-----
subject=/C=FI/ST=Some-State/O=Internet Widgits Pty Ltd/CN=graylog.local
issuer=/C=FI/ST=Some-State/O=Internet Widgits Pty Ltd/CN=graylog.local
---
No client certificate CA names sent
---
SSL handshake has read 1771 bytes and written 493 bytes
---
New, TLSv1/SSLv3, Cipher is EDH-DSS-DES-CBC3-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : EDH-DSS-DES-CBC3-SHA
    Session-ID: 578E908BA0E66F0447E653E48F1B8B72C3A969B7615B218BAB41C6A71D2814A6
    Session-ID-ctx: 
    Master-Key: 29CCE26A54066054C730210CDF6CD94543715AA8D69C417F0845D4C2291BE154C2E040E43D1D3782542915FCB74DB15F
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1468960907
    Timeout   : 300 (sec)
    Verify return code: 18 (self signed certificate)
---
DONE

However it should be noted that without enabling strong cryptography in JVM there are not many ciphers available - for example Chrome and Firefox throw SSL_ERROR_NO_CYPHER_OVERLAP. Getting DSA work in the real world with several clients might require something to be done about this.

  Supported Server Cipher(s):
Preferred TLSv1.2  168 bits  EDH-DSS-DES-CBC3-SHA         
Accepted  TLSv1.2  128 bits  DHE-DSS-AES128-GCM-SHA256    
Accepted  TLSv1.2  128 bits  DHE-DSS-AES128-SHA256        
Accepted  TLSv1.2  128 bits  DHE-DSS-AES128-SHA           
Preferred TLSv1.1  168 bits  EDH-DSS-DES-CBC3-SHA         
Accepted  TLSv1.1  128 bits  DHE-DSS-AES128-SHA           
Preferred TLSv1.0  168 bits  EDH-DSS-DES-CBC3-SHA         
Accepted  TLSv1.0  128 bits  DHE-DSS-AES128-SHA   

joschi added a commit that referenced this issue Jul 22, 2016

@joschi joschi self-assigned this Aug 9, 2016

joschi added a commit that referenced this issue Aug 9, 2016

@joschi joschi added improvement and removed bug to-verify labels Aug 9, 2016

@bernd bernd closed this in #2641 Aug 10, 2016

bernd added a commit that referenced this issue Aug 10, 2016

@bernd

This comment has been minimized.

Member

bernd commented Aug 10, 2016

This will be supported in the upcoming Graylog 2.1 release.

@adam-bishop

This comment has been minimized.

adam-bishop commented Aug 10, 2016

Many thanks for this!

@adam-bishop

This comment has been minimized.

adam-bishop commented Sep 2, 2016

For anyone looking at this ticket because they can't get ECDSA to work - it seems that openjdk on RHEL 7 has EC disabled by default, possibly due to issues integrating with NSS: https://bugzilla.redhat.com/show_bug.cgi?id=1167153

Proprietary Java works fine - check the list of disabled algorithms in java.security for confirmation.

@razvanphp

This comment has been minimized.

Contributor

razvanphp commented Jan 24, 2018

Maybe related for future reference, one can get this error if the key is in PKCS#5 format instead of PKCS#8:

2018-01-24T14:54:23.732Z ERROR [ServiceManager] Service JerseyService [FAILED] has failed in the STARTING state.
java.security.spec.InvalidKeySpecException: Neither RSA, DSA nor EC worked
	at org.graylog2.shared.security.tls.PemKeyStore.buildKeyStore(PemKeyStore.java:110) ~[graylog.jar:?]

The convert command:

openssl pkcs8 -in old.key -topk8 -v2 des3 -out p8enc.new.key -nocrypt
@nacastroc

This comment has been minimized.

nacastroc commented Mar 1, 2018

As razvanphp said

The convert command:

openssl pkcs8 -in old.key -topk8 -v2 des3 -out p8enc.new.key -nocrypt

Solved this for me in Elasticsearch with CentOS 7, which suffers from the same problem. Thanks a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment