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

@@ -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;
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() {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 {

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 */
public class BlowfishCBC
extends BaseCipher {
extends BlockCipher {
/** Named factory for BlowfishCBC Cipher */
public static class Factory

View File

@@ -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