mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-08 00:00:54 +03:00
Added all RFC Ciphers and some extended ones
This commit is contained in:
@@ -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:
|
||||
|
||||
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::
|
||||
`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!)
|
||||
|
||||
== Comparing to other implementations
|
||||
http://ssh-comparison.quendi.de/comparison.html[SSH Implementation Comparison]
|
||||
|
||||
== 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.
|
||||
@@ -93,6 +96,9 @@ Google Group: http://groups.google.com/group/sshj-users
|
||||
Fork away!
|
||||
|
||||
== 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)::
|
||||
* 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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
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.sshj.common.Factory;
|
||||
import net.schmizz.sshj.common.SecurityUtils;
|
||||
@@ -48,6 +50,7 @@ import net.schmizz.sshj.userauth.keyprovider.PuTTYKeyFile;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.image.ByteLookupTable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@@ -130,7 +133,29 @@ public class DefaultConfig
|
||||
new AES192CBC.Factory(),
|
||||
new AES256CBC.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;
|
||||
// Ref. https://issues.apache.org/jira/browse/SSHD-24
|
||||
@@ -144,6 +169,7 @@ public class DefaultConfig
|
||||
c.init(Cipher.Mode.Encrypt, key, iv);
|
||||
} catch (Exception e) {
|
||||
warn = true;
|
||||
log.warn(e.getCause().getMessage());
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
@@ -151,6 +177,7 @@ public class DefaultConfig
|
||||
log.warn("Disabling high-strength ciphers: cipher strengths apparently limited by JCE policy");
|
||||
|
||||
setCipherFactories(avail);
|
||||
log.debug("Available cipher factories: {}", avail);
|
||||
}
|
||||
|
||||
protected void initSignatureFactories() {
|
||||
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code aes128-cbc} cipher */
|
||||
public class AES128CBC
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for AES128CBC Cipher */
|
||||
public static class Factory
|
||||
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code aes128-ctr} cipher */
|
||||
public class AES128CTR
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for AES128CBC Cipher */
|
||||
public static class Factory
|
||||
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code aes192-cbc} cipher */
|
||||
public class AES192CBC
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for AES192CBC Cipher */
|
||||
public static class Factory
|
||||
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code aes192-ctr} cipher */
|
||||
public class AES192CTR
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for AES192CTR Cipher */
|
||||
public static class Factory
|
||||
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code aes256-ctr} cipher */
|
||||
public class AES256CBC
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for AES256CBC Cipher */
|
||||
public static class Factory
|
||||
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code aes256-ctr} cipher */
|
||||
public class AES256CTR
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for AES256CBC Cipher */
|
||||
public static class Factory
|
||||
|
||||
@@ -22,9 +22,11 @@ import javax.crypto.ShortBufferException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
/** Base class for all Cipher implementations delegating to the JCE provider. */
|
||||
public class BaseCipher
|
||||
public abstract class BaseCipher
|
||||
implements Cipher {
|
||||
|
||||
private static byte[] resize(byte[] data, int size) {
|
||||
@@ -66,14 +68,22 @@ public class BaseCipher
|
||||
iv = BaseCipher.resize(iv, ivsize);
|
||||
try {
|
||||
cipher = SecurityUtils.getCipher(transformation);
|
||||
cipher.init((mode == Mode.Encrypt ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE),
|
||||
new SecretKeySpec(key, algorithm), new IvParameterSpec(iv));
|
||||
initCipher(cipher, mode, key, iv);
|
||||
} catch (GeneralSecurityException e) {
|
||||
cipher = null;
|
||||
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
|
||||
public void update(byte[] input, int inputOffset, int inputLen) {
|
||||
try {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code blowfish-ctr} cipher */
|
||||
public class BlowfishCBC
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for BlowfishCBC Cipher */
|
||||
public static class Factory
|
||||
|
||||
@@ -17,7 +17,7 @@ package net.schmizz.sshj.transport.cipher;
|
||||
|
||||
/** {@code 3des-cbc} cipher */
|
||||
public class TripleDESCBC
|
||||
extends BaseCipher {
|
||||
extends BlockCipher {
|
||||
|
||||
/** Named factory for TripleDESCBC Cipher */
|
||||
public static class Factory
|
||||
|
||||
Reference in New Issue
Block a user