Added all RFC Ciphers and some extended ones

This commit is contained in:
Jeroen van Erp
2015-11-11 22:10:16 +01:00
parent 51e1ff24e4
commit 2b6fedc939
16 changed files with 327 additions and 13 deletions

View File

@@ -59,7 +59,8 @@ In the `examples` directory, there is a separate Maven project that shows how th
Implementations / adapters for the following algorithms are included: Implementations / adapters for the following algorithms are included:
ciphers:: ciphers::
`aes{128,192,256}-{cbc,ctr}`, `blowfish-cbc`, `3des-cbc` `aes{128,192,256}-{cbc,ctr}`, `blowfish-{cbc,ctr}`, `3des-{cbc,ctr}`, `twofish{128,192,256}-{cbc,ctr}`, `twofish-cbc`, `serpent{128,192,256}-{cbc,ctr}`, `idea-{cbc,ctr}`, `cast128-{cbc,ctr}`, `arcfour`, `arcfour{128,256}`
SSHJ also supports the following extended (non official) ciphers: `camellia{128,192,256}-{cbc,ctr}`, `camellia{128,192,256}-{cbc,ctr}@openssh.org`
key exchange:: key exchange::
`diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`, `diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`, `diffie-hellman-group1-sha1`, `diffie-hellman-group14-sha1`, `diffie-hellman-group-exchange-sha1`, `diffie-hellman-group-exchange-sha256`,
@@ -79,6 +80,8 @@ private key files::
If you need something that is not included, it shouldn't be too hard to add (do contribute it!) If you need something that is not included, it shouldn't be too hard to add (do contribute it!)
== Comparing to other implementations
http://ssh-comparison.quendi.de/comparison.html[SSH Implementation Comparison]
== Dependencies == Dependencies
Java 6+. http://www.slf4j.org/download.html[slf4j] is required. http://www.bouncycastle.org/java.html[bouncycastle] is highly recommended and required for using some of the crypto algorithms. http://www.jcraft.com/jzlib/[jzlib] is required for using zlib compression. Java 6+. http://www.slf4j.org/download.html[slf4j] is required. http://www.bouncycastle.org/java.html[bouncycastle] is highly recommended and required for using some of the crypto algorithms. http://www.jcraft.com/jzlib/[jzlib] is required for using zlib compression.
@@ -93,6 +96,9 @@ Google Group: http://groups.google.com/group/sshj-users
Fork away! Fork away!
== Release history == Release history
SSHJ 0.15.0 (2015-??-??)::
* Added arcfour Stream Ciphers from RFC4253 and RFC4345
* Added all Block Ciphers from RFC4344 and RFC4253
SSHJ 0.14.0 (2015-11-04):: SSHJ 0.14.0 (2015-11-04)::
* Fixed https://github.com/hierynomus/sshj/issues/171[#171]: Added support for `curve25519-sha256@libssh.org` key exchange algorithm * Fixed https://github.com/hierynomus/sshj/issues/171[#171]: Added support for `curve25519-sha256@libssh.org` key exchange algorithm
* Added support for `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384` and `ecdh-sha2-nistp521` key exchange algorithms * Added support for `ecdh-sha2-nistp256`, `ecdh-sha2-nistp384` and `ecdh-sha2-nistp521` key exchange algorithms

View File

@@ -0,0 +1,122 @@
package com.hierynomus.sshj.transport.cipher;
import net.schmizz.sshj.transport.cipher.BaseCipher;
import net.schmizz.sshj.transport.cipher.BlockCipher;
import net.schmizz.sshj.transport.cipher.Cipher;
/**
* All BlockCiphers supported by SSH according to the following RFCs
*
* - https://tools.ietf.org/html/rfc4344#section-3.1
* - https://tools.ietf.org/html/rfc4253#section-6.3
*
* TODO: https://tools.ietf.org/html/rfc5647
*
* Some of the Ciphers are still implemented in net.schmizz.sshj.transport.cipher.*. These are scheduled to be migrated to here.
*/
public class BlockCiphers {
public static final String COUNTER_MODE = "CTR";
public static final String CIPHER_BLOCK_CHAINING_MODE = "CBC";
public static Factory BlowfishCTR() {
return new Factory(8, 256, "blowfish-ctr", "Blowfish", COUNTER_MODE);
}
public static Factory Twofish128CTR() {
return new Factory(16, 128, "twofish128-ctr", "Twofish", COUNTER_MODE);
}
public static Factory Twofish192CTR() {
return new Factory(16, 192, "twofish192-ctr", "Twofish", COUNTER_MODE);
}
public static Factory Twofish256CTR() {
return new Factory(16, 256, "twofish256-ctr", "Twofish", COUNTER_MODE);
}
public static Factory Twofish128CBC() {
return new Factory(16, 128, "twofish128-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Twofish192CBC() {
return new Factory(16, 192, "twofish192-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Twofish256CBC() {
return new Factory(16, 256, "twofish256-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory TwofishCBC() {
return new Factory(16, 256, "twofish-cbc", "Twofish", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Serpent128CTR() {
return new Factory(16, 128, "serpent128-ctr", "Serpent", COUNTER_MODE);
}
public static Factory Serpent192CTR() {
return new Factory(16, 192, "serpent192-ctr", "Serpent", COUNTER_MODE);
}
public static Factory Serpent256CTR() {
return new Factory(16, 256, "serpent256-ctr", "Serpent", COUNTER_MODE);
}
public static Factory Serpent128CBC() {
return new Factory(16, 128, "serpent128-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Serpent192CBC() {
return new Factory(16, 192, "serpent192-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Serpent256CBC() {
return new Factory(16, 256, "serpent256-cbc", "Serpent", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory IDEACTR() {
return new Factory(8, 128, "idea-ctr", "IDEA", COUNTER_MODE);
}
public static Factory IDEACBC() {
return new Factory(8, 128, "idea-cbc", "IDEA", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory Cast128CTR() {
return new Factory(8, 128, "cast128-ctr", "CAST5", COUNTER_MODE);
}
public static Factory Cast128CBC() {
return new Factory(8, 128, "cast128-cbc", "CAST5", CIPHER_BLOCK_CHAINING_MODE);
}
public static Factory TripleDESCTR() {
return new Factory(8, 192, "3des-ctr", "DESede", COUNTER_MODE);
}
/** Named factory for BlockCipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
private int keysize;
private String cipher;
private String mode;
private String name;
private int ivsize;
/**
* @param ivsize
* @param keysize The keysize used in bits.
* @param name
* @param cipher
* @param mode
*/
public Factory(int ivsize, int keysize, String name, String cipher, String mode) {
this.name = name;
this.keysize = keysize;
this.cipher = cipher;
this.mode = mode;
this.ivsize = ivsize;
}
@Override
public Cipher create() {
return new BlockCipher(ivsize, keysize / 8, cipher, cipher + "/" + mode + "/NoPadding");
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
}

View File

@@ -0,0 +1,52 @@
package com.hierynomus.sshj.transport.cipher;
import static com.hierynomus.sshj.transport.cipher.BlockCiphers.CIPHER_BLOCK_CHAINING_MODE;
import static com.hierynomus.sshj.transport.cipher.BlockCiphers.COUNTER_MODE;
/**
* Set of Block Ciphers that are (not yet) part of any of the official RFCs for SSH, but
* that are either supported by other SSH implementations, or are being pushed for to be
* included in a new RFC.
*
* - http://tools.ietf.org/id/draft-kanno-secsh-camellia-01.txt
*/
public class ExtendedBlockCiphers {
public static BlockCiphers.Factory Camellia128CTR() {
return new BlockCiphers.Factory(16, 128, "camellia128-ctr", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia128CTROpenSSHOrg() {
return new BlockCiphers.Factory(16, 128, "camellia128-ctr@openssh.org", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia192CTR() {
return new BlockCiphers.Factory(16, 192, "camellia192-ctr", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia192CTROpenSSHOrg() {
return new BlockCiphers.Factory(16, 192, "camellia192-ctr@openssh.org", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia256CTR() {
return new BlockCiphers.Factory(16, 256, "camellia256-ctr", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia256CTROpenSSHOrg() {
return new BlockCiphers.Factory(16, 256, "camellia256-ctr@openssh.org", "Camellia", COUNTER_MODE);
}
public static BlockCiphers.Factory Camellia128CBC() {
return new BlockCiphers.Factory(16, 128, "camellia128-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia128CBCOpenSSHOrg() {
return new BlockCiphers.Factory(16, 128, "camellia128-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia192CBC() {
return new BlockCiphers.Factory(16, 192, "camellia192-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia192CBCOpenSSHOrg() {
return new BlockCiphers.Factory(16, 192, "camellia192-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia256CBC() {
return new BlockCiphers.Factory(16, 256, "camellia256-cbc", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
public static BlockCiphers.Factory Camellia256CBCOpenSSHOrg() {
return new BlockCiphers.Factory(16, 256, "camellia256-cbc@openssh.org", "Camellia", CIPHER_BLOCK_CHAINING_MODE);
}
}

View File

@@ -0,0 +1,19 @@
package com.hierynomus.sshj.transport.cipher;
import net.schmizz.sshj.transport.cipher.BaseCipher;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
public class StreamCipher extends BaseCipher {
public StreamCipher(int bsize, String algorithm, String transformation) {
super(0, bsize, algorithm, transformation);
}
@Override
protected void initCipher(javax.crypto.Cipher cipher, Mode mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException {
cipher.init(getMode(mode), getKeySpec(key), new SecureRandom());
}
}

View File

@@ -0,0 +1,61 @@
package com.hierynomus.sshj.transport.cipher;
import net.schmizz.sshj.transport.cipher.Cipher;
/**
* Implementations of the Stream Ciphers that are defined in the RFCs
*
* - https://tools.ietf.org/html/rfc4253#section-6.3
* - https://tools.ietf.org/html/rfc4345
*/
public class StreamCiphers {
public static Factory Arcfour() {
return new Factory(128, "arcfour", "ARCFOUR", "ECB");
}
public static Factory Arcfour128() {
return new Factory(128, "arcfour128", "RC4", "ECB");
}
public static Factory Arcfour256() {
return new Factory(256, "arcfour256", "RC4", "ECB");
}
/** Named factory for BlockCipher */
public static class Factory
implements net.schmizz.sshj.common.Factory.Named<Cipher> {
private int keysize;
private String cipher;
private String mode;
private String name;
/**
* @param keysize The keysize used in bits.
* @param name
* @param cipher
* @param mode
*/
public Factory(int keysize, String name, String cipher, String mode) {
this.name = name;
this.keysize = keysize;
this.cipher = cipher;
this.mode = mode;
}
@Override
public Cipher create() {
return new StreamCipher(keysize / 8, cipher, cipher + "/" + mode + "/NoPadding");
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return getName();
}
}
}

View File

@@ -15,6 +15,8 @@
*/ */
package net.schmizz.sshj; package net.schmizz.sshj;
import com.hierynomus.sshj.transport.cipher.BlockCiphers;
import com.hierynomus.sshj.transport.cipher.StreamCiphers;
import net.schmizz.keepalive.KeepAliveProvider; import net.schmizz.keepalive.KeepAliveProvider;
import net.schmizz.sshj.common.Factory; import net.schmizz.sshj.common.Factory;
import net.schmizz.sshj.common.SecurityUtils; import net.schmizz.sshj.common.SecurityUtils;
@@ -48,6 +50,7 @@ import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.awt.image.ByteLookupTable;
import java.util.Arrays; import java.util.Arrays;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
@@ -130,7 +133,29 @@ public class DefaultConfig
new AES192CBC.Factory(), new AES192CBC.Factory(),
new AES256CBC.Factory(), new AES256CBC.Factory(),
new TripleDESCBC.Factory(), new TripleDESCBC.Factory(),
new BlowfishCBC.Factory())); new BlowfishCBC.Factory(),
BlockCiphers.BlowfishCTR(),
BlockCiphers.Cast128CBC(),
BlockCiphers.Cast128CTR(),
BlockCiphers.IDEACBC(),
BlockCiphers.IDEACTR(),
BlockCiphers.Serpent128CBC(),
BlockCiphers.Serpent128CTR(),
BlockCiphers.Serpent192CBC(),
BlockCiphers.Serpent192CTR(),
BlockCiphers.Serpent256CBC(),
BlockCiphers.Serpent256CTR(),
BlockCiphers.TripleDESCTR(),
BlockCiphers.Twofish128CBC(),
BlockCiphers.Twofish128CTR(),
BlockCiphers.Twofish192CBC(),
BlockCiphers.Twofish192CTR(),
BlockCiphers.Twofish256CBC(),
BlockCiphers.Twofish256CTR(),
BlockCiphers.TwofishCBC(),
StreamCiphers.Arcfour(),
StreamCiphers.Arcfour128(),
StreamCiphers.Arcfour256()));
boolean warn = false; boolean warn = false;
// Ref. https://issues.apache.org/jira/browse/SSHD-24 // Ref. https://issues.apache.org/jira/browse/SSHD-24
@@ -144,6 +169,7 @@ public class DefaultConfig
c.init(Cipher.Mode.Encrypt, key, iv); c.init(Cipher.Mode.Encrypt, key, iv);
} catch (Exception e) { } catch (Exception e) {
warn = true; warn = true;
log.warn(e.getCause().getMessage());
i.remove(); i.remove();
} }
} }
@@ -151,6 +177,7 @@ public class DefaultConfig
log.warn("Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy"); log.warn("Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy");
setCipherFactories(avail); setCipherFactories(avail);
log.debug("Available cipher factories: {}", avail);
} }
protected void initSignatureFactories() { protected void initSignatureFactories() {

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code aes128-cbc} cipher */ /** {@code aes128-cbc} cipher */
public class AES128CBC public class AES128CBC
extends BaseCipher { extends BlockCipher {
/** Named factory for AES128CBC Cipher */ /** Named factory for AES128CBC Cipher */
public static class Factory public static class Factory

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code aes128-ctr} cipher */ /** {@code aes128-ctr} cipher */
public class AES128CTR public class AES128CTR
extends BaseCipher { extends BlockCipher {
/** Named factory for AES128CBC Cipher */ /** Named factory for AES128CBC Cipher */
public static class Factory public static class Factory

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code aes192-cbc} cipher */ /** {@code aes192-cbc} cipher */
public class AES192CBC public class AES192CBC
extends BaseCipher { extends BlockCipher {
/** Named factory for AES192CBC Cipher */ /** Named factory for AES192CBC Cipher */
public static class Factory public static class Factory

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code aes192-ctr} cipher */ /** {@code aes192-ctr} cipher */
public class AES192CTR public class AES192CTR
extends BaseCipher { extends BlockCipher {
/** Named factory for AES192CTR Cipher */ /** Named factory for AES192CTR Cipher */
public static class Factory public static class Factory

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code aes256-ctr} cipher */ /** {@code aes256-ctr} cipher */
public class AES256CBC public class AES256CBC
extends BaseCipher { extends BlockCipher {
/** Named factory for AES256CBC Cipher */ /** Named factory for AES256CBC Cipher */
public static class Factory public static class Factory

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code aes256-ctr} cipher */ /** {@code aes256-ctr} cipher */
public class AES256CTR public class AES256CTR
extends BaseCipher { extends BlockCipher {
/** Named factory for AES256CBC Cipher */ /** Named factory for AES256CBC Cipher */
public static class Factory public static class Factory

View File

@@ -22,9 +22,11 @@ import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
/** Base class for all Cipher implementations delegating to the JCE provider. */ /** Base class for all Cipher implementations delegating to the JCE provider. */
public class BaseCipher public abstract class BaseCipher
implements Cipher { implements Cipher {
private static byte[] resize(byte[] data, int size) { private static byte[] resize(byte[] data, int size) {
@@ -66,14 +68,22 @@ public class BaseCipher
iv = BaseCipher.resize(iv, ivsize); iv = BaseCipher.resize(iv, ivsize);
try { try {
cipher = SecurityUtils.getCipher(transformation); cipher = SecurityUtils.getCipher(transformation);
cipher.init((mode == Mode.Encrypt ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE), initCipher(cipher, mode, key, iv);
new SecretKeySpec(key, algorithm), new IvParameterSpec(iv));
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
cipher = null; cipher = null;
throw new SSHRuntimeException(e); throw new SSHRuntimeException(e);
} }
} }
protected abstract void initCipher(javax.crypto.Cipher cipher, Mode mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException;
protected SecretKeySpec getKeySpec(byte[] key) {
return new SecretKeySpec(key, algorithm);
}
protected int getMode(Mode mode) {
return mode == Mode.Encrypt ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE;
}
@Override @Override
public void update(byte[] input, int inputOffset, int inputLen) { public void update(byte[] input, int inputOffset, int inputLen) {
try { try {

View File

@@ -0,0 +1,17 @@
package net.schmizz.sshj.transport.cipher;
import javax.crypto.spec.IvParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
public class BlockCipher extends BaseCipher {
public BlockCipher(int ivsize, int bsize, String algorithm, String transformation) {
super(ivsize, bsize, algorithm, transformation);
}
protected void initCipher(javax.crypto.Cipher cipher, Mode mode, byte[] key, byte[] iv) throws InvalidKeyException, InvalidAlgorithmParameterException {
cipher.init(getMode(mode),
getKeySpec(key), new IvParameterSpec(iv));
}
}

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code blowfish-ctr} cipher */ /** {@code blowfish-ctr} cipher */
public class BlowfishCBC public class BlowfishCBC
extends BaseCipher { extends BlockCipher {
/** Named factory for BlowfishCBC Cipher */ /** Named factory for BlowfishCBC Cipher */
public static class Factory public static class Factory

View File

@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
/** {@code 3des-cbc} cipher */ /** {@code 3des-cbc} cipher */
public class TripleDESCBC public class TripleDESCBC
extends BaseCipher { extends BlockCipher {
/** Named factory for TripleDESCBC Cipher */ /** Named factory for TripleDESCBC Cipher */
public static class Factory public static class Factory