
|
If you were logged in you would be able to see more operations.
|
|
|
JRuby
Created: 09/Dec/07 07:24 AM
Updated: 14/Aug/08 04:51 AM
|
|
| Component/s: |
OpenSSL
|
| Affects Version/s: |
None
|
| Fix Version/s: |
None
|
|
|
File Attachments:
|
1.
sst.rb (3 kb)
|
|
Environment:
|
jopenssl trunk, JRuby trunk, WinXP, Java 1.6, bcprov-jdk15-137.jar, Net::SSH 1.1.2; server sshd is OpenSSH 4.7 (cygwin)
|
|
jopenssl support for Net::SSH is nearly working (the new BN and DH classes used for key exchange appear to work), but I'm getting a failure that appears to be caused by a bug in cipher code (org.jruby.ext.openssl.Cipher.java).
Here's what happens, in brief (I've attached the debug output below, and have attached some code to repro):
- the client and server negotiate algorithms and exchange keys
- Net::SSH creates two ciphers, one for encrypt, one for decrypt
- Net::SSH uses encrypt cipher to encrypt and send message "ssh-userauth" (plus some header fields)
- Net::SSH uses decrypt cipher to decrypt the response, which also has the value "ssh-userauth" (plus headers)
So far, so good – we've encrypted and sent a message, and received and decrypted a valid response. Now:
- Net::SSH uses encrypt cipher to encrypt and send a "ssh-connection" message, with username, password, and other info. We don't know if this worked, because:
- Net::SSH uses decrypt cipher to decrypt response. This actually takes place in a couple of steps; first, a block is read and decrypted (packet header), and the message length is extracted. This length is then used to determine how much more data to read. However, the length returned is garbage. Typically very large or very small garbage: the RubyIO module attempts to allocate a ByteList, and either fails with a NegativeIndex exception, or dies with an OutOfMemory error (because the size was so large).
So it appears that the cipher doesn't work for more than one message. I've gone through the code and can't spot the bug; Cipher#final is being called between messages, and I've walked through the code (jopenssl and BC) and confirmed that BufferBlockCipher#doFinal is called, which appears to call #reset on the underlying Cipher; in the DES code at least, it appears that this correctly copies the original IV back to the buffer.
SO... I'm not sure why this is failing. On the other hand, there seems to be a fair amount of uncertainty in the Cipher implementation (I fixed a couple of glaring issues), so I wouldn't be surprised if there were some sort of misunderstanding of the BC interfaces (not so well documented) or the MRI-OpenSSL interface we're emulating (not documented at all), or the process in general. I'm certainly out of my depth here, though I've been doing a lot of research (Applied Cryptography is sorely out-of-date; the newer Practical Cryptography lacks details; Wikipedia has some pretty good info and pointers, like this one on modes: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf ).
I've included a listing of a debug session below. The attached script will reproduce this, though you'll have to plug in your username and password first (and possibly hostname if you don't have sshd on your local machine – I've got OpenSSH running under cygwin on my WinXP box).
Try running the script under MRI-IRB to see what the results should look like. Getting pretty darned close, considering where things stood a few weeks ago.
|
|
Description
|
jopenssl support for Net::SSH is nearly working (the new BN and DH classes used for key exchange appear to work), but I'm getting a failure that appears to be caused by a bug in cipher code (org.jruby.ext.openssl.Cipher.java).
Here's what happens, in brief (I've attached the debug output below, and have attached some code to repro):
- the client and server negotiate algorithms and exchange keys
- Net::SSH creates two ciphers, one for encrypt, one for decrypt
- Net::SSH uses encrypt cipher to encrypt and send message "ssh-userauth" (plus some header fields)
- Net::SSH uses decrypt cipher to decrypt the response, which also has the value "ssh-userauth" (plus headers)
So far, so good – we've encrypted and sent a message, and received and decrypted a valid response. Now:
- Net::SSH uses encrypt cipher to encrypt and send a "ssh-connection" message, with username, password, and other info. We don't know if this worked, because:
- Net::SSH uses decrypt cipher to decrypt response. This actually takes place in a couple of steps; first, a block is read and decrypted (packet header), and the message length is extracted. This length is then used to determine how much more data to read. However, the length returned is garbage. Typically very large or very small garbage: the RubyIO module attempts to allocate a ByteList, and either fails with a NegativeIndex exception, or dies with an OutOfMemory error (because the size was so large).
So it appears that the cipher doesn't work for more than one message. I've gone through the code and can't spot the bug; Cipher#final is being called between messages, and I've walked through the code (jopenssl and BC) and confirmed that BufferBlockCipher#doFinal is called, which appears to call #reset on the underlying Cipher; in the DES code at least, it appears that this correctly copies the original IV back to the buffer.
SO... I'm not sure why this is failing. On the other hand, there seems to be a fair amount of uncertainty in the Cipher implementation (I fixed a couple of glaring issues), so I wouldn't be surprised if there were some sort of misunderstanding of the BC interfaces (not so well documented) or the MRI-OpenSSL interface we're emulating (not documented at all), or the process in general. I'm certainly out of my depth here, though I've been doing a lot of research (Applied Cryptography is sorely out-of-date; the newer Practical Cryptography lacks details; Wikipedia has some pretty good info and pointers, like this one on modes: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf ).
I've included a listing of a debug session below. The attached script will reproduce this, though you'll have to plug in your username and password first (and possibly hostname if you don't have sshd on your local machine – I've got OpenSSH running under cygwin on my WinXP box).
Try running the script under MRI-IRB to see what the results should look like. Getting pretty darned close, considering where things stood a few weeks ago.
|
Show » |
|