Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2018-01-21 05:37:52 +0000
committerEike Stepper2018-01-21 05:37:52 +0000
commitc19f86fdee29b58740bddcf25ebe77ce74978fae (patch)
tree4b40e7fe23b08335cdd45a7b95542eb05c30b4bb /plugins/org.eclipse.net4j.util
parent273adb8832a5f090ff65aa66d4896501fdd3e9d5 (diff)
downloadcdo-c19f86fdee29b58740bddcf25ebe77ce74978fae.tar.gz
cdo-c19f86fdee29b58740bddcf25ebe77ce74978fae.tar.xz
cdo-c19f86fdee29b58740bddcf25ebe77ce74978fae.zip
[530088] Authentication no longer works with Java 8 update 161
https://bugs.eclipse.org/bugs/show_bug.cgi?id=530088
Diffstat (limited to 'plugins/org.eclipse.net4j.util')
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java263
1 files changed, 210 insertions, 53 deletions
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java
index 222fd3c73b..e424310b47 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/security/DiffieHellman.java
@@ -16,9 +16,9 @@ import org.eclipse.net4j.util.io.IORuntimeException;
import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
-import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.math.BigInteger;
@@ -47,49 +47,93 @@ public class DiffieHellman
*/
public static class Server
{
+ /**
+ * @deprecated As of 3.8 the default secret algorithm is "AES".
+ */
+ @Deprecated
public static final String DEFAULT_SECRET_ALGORITHM = "DES";
+ /**
+ * @deprecated As of 3.8 the default cipher transformation is "AES/CBC/PKCS5Padding".
+ */
+ @Deprecated
public static final String DEFAULT_CYPHER_TRANSFORMATION = "DES/CBC/PKCS5Padding";
+ private static final int DIFFIE_HELLMAN_KEY_SIZE = 2048;
+
+ private static final int UNKNOWN_SECRET_ALGORITHM_KEY_LEN = -1;
+
+ private static final String SECRET_ALGORITHM = "AES";
+
+ private static final String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
+
private final String realm;
private final PrivateKey privateKey;
private final Challenge challenge;
- public Server(String realm, DHParameterSpec dhParamSpec, String secretAlgorithm, String cypherTransformation)
+ /**
+ * @since 3.8
+ */
+ public Server(String realm, KeyPairGenerator keyPairGenerator, int secretAlgorithmKeyLen, String secretAlgorithm, String cipherTransformation)
{
this.realm = realm;
- try
- {
- // Create DH key pair, using the passed DH parameters
- KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
- keyPairGenerator.initialize(dhParamSpec);
- KeyPair keyPair = keyPairGenerator.generateKeyPair();
+ // Create DH key pair, using the passed DH parameters.
+ KeyPair keyPair = keyPairGenerator.generateKeyPair();
- privateKey = keyPair.getPrivate();
+ privateKey = keyPair.getPrivate();
- // Encode public key
- byte[] pubKeyEnc = keyPair.getPublic().getEncoded();
+ // Create and remember Challenge object.
+ challenge = new Challenge(realm, secretAlgorithmKeyLen, secretAlgorithm, cipherTransformation, keyPair);
+ }
- // Create and remember Challenge object
- challenge = new Challenge(realm, secretAlgorithm, cypherTransformation, pubKeyEnc);
- }
- catch (GeneralSecurityException ex)
- {
- throw new SecurityException(ex);
- }
+ /**
+ * @since 3.8
+ */
+ public Server(String realm, int diffieHellmanKeySize, int secretAlgorithmKeyLen, String secretAlgorithm, String cipherTransformation)
+ {
+ this(realm, createKeyPairGenerator(diffieHellmanKeySize), secretAlgorithmKeyLen, secretAlgorithm, cipherTransformation);
}
- public Server(String realm, DHParameterSpec dhParamSpec)
+ /**
+ * @since 3.8
+ */
+ public Server(String realm, int diffieHellmanKeySize, String secretAlgorithm, String cipherTransformation)
{
- this(realm, dhParamSpec, DEFAULT_SECRET_ALGORITHM, DEFAULT_CYPHER_TRANSFORMATION);
+ this(realm, createKeyPairGenerator(diffieHellmanKeySize), UNKNOWN_SECRET_ALGORITHM_KEY_LEN, secretAlgorithm, cipherTransformation);
+ }
+
+ /**
+ * @since 3.8
+ */
+ public Server(String realm, int diffieHellmanKeySize)
+ {
+ this(realm, diffieHellmanKeySize, SECRET_ALGORITHM, CIPHER_TRANSFORMATION);
}
public Server(String realm)
{
- this(realm, SkipParameterSpec.INSTANCE);
+ this(realm, DIFFIE_HELLMAN_KEY_SIZE);
+ }
+
+ /**
+ * @since 3.8
+ */
+ public Server(String realm, DHParameterSpec dhParamSpec, int secretAlgorithmKeyLen, String secretAlgorithm, String cipherTransformation)
+ {
+ this(realm, createKeyPairGenerator(dhParamSpec), secretAlgorithmKeyLen, secretAlgorithm, cipherTransformation);
+ }
+
+ public Server(String realm, DHParameterSpec dhParamSpec, String secretAlgorithm, String cipherTransformation)
+ {
+ this(realm, createKeyPairGenerator(dhParamSpec), UNKNOWN_SECRET_ALGORITHM_KEY_LEN, secretAlgorithm, cipherTransformation);
+ }
+
+ public Server(String realm, DHParameterSpec dhParamSpec)
+ {
+ this(realm, dhParamSpec, SECRET_ALGORITHM, CIPHER_TRANSFORMATION);
}
public final String getRealm()
@@ -111,32 +155,34 @@ public class DiffieHellman
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(response.getClientPubKeyEnc());
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
- // Create and initialize DH KeyAgreement object
+ // Create and initialize DH KeyAgreement object.
KeyAgreement keyAgree = KeyAgreement.getInstance("DH");
keyAgree.init(privateKey);
// Use Client's public key for the first (and only) phase of her version of the DH protocol.
keyAgree.doPhase(pubKey, true);
- SecretKey sharedSecret = keyAgree.generateSecret(challenge.getSecretAlgorithm());
- // Prepare the cipher used to decrypt
- Cipher serverCipher = Cipher.getInstance(challenge.getCypherTransformation());
+ byte[] sharedSecret = keyAgree.generateSecret();
+ SecretKeySpec secretKeySpec = new SecretKeySpec(sharedSecret, 0, challenge.getSecretAlgorithmKeyLen(), challenge.getSecretAlgorithm());
+
+ // Prepare the cipher used to decrypt.
+ Cipher serverCipher = Cipher.getInstance(challenge.getCipherTransformation());
byte[] encodedParams = response.getParamsEnc();
if (encodedParams == null)
{
- serverCipher.init(Cipher.DECRYPT_MODE, sharedSecret);
+ serverCipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
}
else
{
- // Instantiate AlgorithmParameters object from parameter encoding obtained from client
+ // Instantiate AlgorithmParameters object from parameter encoding obtained from client.
AlgorithmParameters params = AlgorithmParameters.getInstance(challenge.getSecretAlgorithm());
params.init(encodedParams);
- serverCipher.init(Cipher.DECRYPT_MODE, sharedSecret, params);
+ serverCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, params);
}
- // Decrypt
+ // Decrypt.
return serverCipher.doFinal(response.getCipherText());
}
catch (GeneralSecurityException ex)
@@ -149,6 +195,70 @@ public class DiffieHellman
}
}
+ private static final KeyPairGenerator createKeyPairGenerator(int keySize)
+ {
+ try
+ {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
+ keyPairGenerator.initialize(keySize);
+ return keyPairGenerator;
+ }
+ catch (GeneralSecurityException ex)
+ {
+ throw new SecurityException(ex);
+ }
+ }
+
+ private static final KeyPairGenerator createKeyPairGenerator(DHParameterSpec dhParamSpec)
+ {
+ try
+ {
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
+ keyPairGenerator.initialize(dhParamSpec);
+ return keyPairGenerator;
+ }
+ catch (GeneralSecurityException ex)
+ {
+ throw new SecurityException(ex);
+ }
+ }
+
+ private static final int determineSecretAlgorithmKeyLen(String secretAlgorithm, String cipherTransformation, KeyPair keyPair)
+ {
+ byte[] secret;
+
+ try
+ {
+ KeyAgreement keyAgree = KeyAgreement.getInstance("DH");
+ keyAgree.init(keyPair.getPrivate());
+ keyAgree.doPhase(keyPair.getPublic(), true);
+
+ secret = keyAgree.generateSecret();
+ }
+ catch (GeneralSecurityException ex)
+ {
+ throw new SecurityException(ex);
+ }
+
+ for (int keyLen = secret.length; keyLen > 0; --keyLen)
+ {
+ SecretKeySpec secretKeySpec = new SecretKeySpec(secret, 0, keyLen, secretAlgorithm);
+
+ try
+ {
+ Cipher clientCipher = Cipher.getInstance(cipherTransformation);
+ clientCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
+ return keyLen;
+ }
+ catch (GeneralSecurityException ex)
+ {
+ //$FALL-THROUGH$
+ }
+ }
+
+ throw new SecurityException("Key length could not be determined for " + secretAlgorithm + " [" + cipherTransformation + "]");
+ }
+
/**
* @author Eike Stepper
*/
@@ -156,33 +266,56 @@ public class DiffieHellman
{
private final String serverRealm;
+ private final int secretAlgorithmKeyLen;
+
private final String secretAlgorithm;
- private final String cypherTransformation;
+ private final String cipherTransformation;
private final byte[] serverPubKeyEnc;
- public Challenge(String serverRealm, String secretAlgorithm, String cypherTransformation, byte[] serverPubKeyEnc)
+ private Challenge(String serverRealm, int secretAlgorithmKeyLen, String secretAlgorithm, String cipherTransformation, KeyPair keyPair)
{
this.serverRealm = serverRealm;
+
+ if (secretAlgorithmKeyLen == UNKNOWN_SECRET_ALGORITHM_KEY_LEN)
+ {
+ this.secretAlgorithmKeyLen = determineSecretAlgorithmKeyLen(secretAlgorithm, cipherTransformation, keyPair);
+ }
+ else
+ {
+ this.secretAlgorithmKeyLen = secretAlgorithmKeyLen;
+ }
+
this.secretAlgorithm = secretAlgorithm;
- this.cypherTransformation = cypherTransformation;
- this.serverPubKeyEnc = serverPubKeyEnc;
+ this.cipherTransformation = cipherTransformation;
+ serverPubKeyEnc = keyPair.getPublic().getEncoded();
+ }
+
+ /**
+ * @deprecated As of 3.8 public construction is no longer supported.
+ */
+ @Deprecated
+ public Challenge(String serverRealm, String secretAlgorithm, String cipherTransformation, byte[] serverPubKeyEnc)
+ {
+ throw new UnsupportedOperationException();
}
public Challenge(ExtendedDataInput in) throws IOException
{
serverRealm = in.readString();
+ secretAlgorithmKeyLen = in.readInt();
secretAlgorithm = in.readString();
- cypherTransformation = in.readString();
+ cipherTransformation = in.readString();
serverPubKeyEnc = in.readByteArray();
}
public void write(ExtendedDataOutput out) throws IOException
{
out.writeString(serverRealm);
+ out.writeInt(secretAlgorithmKeyLen);
out.writeString(secretAlgorithm);
- out.writeString(cypherTransformation);
+ out.writeString(cipherTransformation);
out.writeByteArray(serverPubKeyEnc);
}
@@ -191,14 +324,34 @@ public class DiffieHellman
return serverRealm;
}
+ /**
+ * @since 3.8
+ */
+ public int getSecretAlgorithmKeyLen()
+ {
+ return secretAlgorithmKeyLen;
+ }
+
public String getSecretAlgorithm()
{
return secretAlgorithm;
}
+ /**
+ * @since 3.8
+ */
+ public String getCipherTransformation()
+ {
+ return cipherTransformation;
+ }
+
+ /**
+ * @deprecated As of 3.8 use {@link #getCipherTransformation()}.
+ */
+ @Deprecated
public String getCypherTransformation()
{
- return cypherTransformation;
+ return cipherTransformation;
}
public byte[] getServerPubKeyEnc()
@@ -244,11 +397,15 @@ public class DiffieHellman
// Use server's public key for the first (and only) phase of his version of the DH protocol
clientKeyAgree.doPhase(pubKey, true);
- SecretKey sharedSecret = clientKeyAgree.generateSecret(challenge.getSecretAlgorithm());
+
+ // SecretKey sharedSecret = clientKeyAgree.generateSecret(challenge.getSecretAlgorithm());
+ byte[] sharedSecret = clientKeyAgree.generateSecret();
+
+ SecretKeySpec secretKeySpec = new SecretKeySpec(sharedSecret, 0, challenge.getSecretAlgorithmKeyLen(), challenge.getSecretAlgorithm());
// Encrypt
- Cipher clientCipher = Cipher.getInstance(challenge.getCypherTransformation());
- clientCipher.init(Cipher.ENCRYPT_MODE, sharedSecret);
+ Cipher clientCipher = Cipher.getInstance(challenge.getCipherTransformation());
+ clientCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] ciphertext = clientCipher.doFinal(clearText);
// Retrieve the parameter that was used, and transfer it to the server in encoded format
@@ -324,29 +481,29 @@ public class DiffieHellman
/**
* The 1024 bit Diffie-Hellman modulus values used by SKIP
*/
- private static final byte skip1024ModulusBytes[] = { (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58, (byte)0x4E, (byte)0x49, (byte)0xDB, (byte)0xCD,
- (byte)0x20, (byte)0xB4, (byte)0x9D, (byte)0xE4, (byte)0x91, (byte)0x07, (byte)0x36, (byte)0x6B, (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D,
- (byte)0x45, (byte)0x1D, (byte)0x0F, (byte)0x7C, (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C, (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6,
- (byte)0xF3, (byte)0xC9, (byte)0x23, (byte)0xC0, (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B, (byte)0x18, (byte)0x8D, (byte)0x8E, (byte)0xBB,
- (byte)0x55, (byte)0x8C, (byte)0xB8, (byte)0x5D, (byte)0x38, (byte)0xD3, (byte)0x34, (byte)0xFD, (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43,
- (byte)0xA3, (byte)0x1D, (byte)0x18, (byte)0x6C, (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C, (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C,
- (byte)0xE1, (byte)0xB1, (byte)0x29, (byte)0x40, (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C, (byte)0x84, (byte)0xA7, (byte)0x0A, (byte)0x72,
- (byte)0xD6, (byte)0x86, (byte)0xC4, (byte)0x03, (byte)0x19, (byte)0xC8, (byte)0x07, (byte)0x29, (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C,
- (byte)0xD9, (byte)0x96, (byte)0x9F, (byte)0xAB, (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B, (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08,
- (byte)0x3D, (byte)0x66, (byte)0xA4, (byte)0x5D, (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C, (byte)0xBD, (byte)0x89, (byte)0x4B, (byte)0x22,
- (byte)0x19, (byte)0x26, (byte)0xBA, (byte)0xAB, (byte)0xA2, (byte)0x5E, (byte)0xC3, (byte)0x55, (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7 };
+ private static final byte modulusBytes[] = { (byte)0xF4, (byte)0x88, (byte)0xFD, (byte)0x58, (byte)0x4E, (byte)0x49, (byte)0xDB, (byte)0xCD, (byte)0x20,
+ (byte)0xB4, (byte)0x9D, (byte)0xE4, (byte)0x91, (byte)0x07, (byte)0x36, (byte)0x6B, (byte)0x33, (byte)0x6C, (byte)0x38, (byte)0x0D, (byte)0x45,
+ (byte)0x1D, (byte)0x0F, (byte)0x7C, (byte)0x88, (byte)0xB3, (byte)0x1C, (byte)0x7C, (byte)0x5B, (byte)0x2D, (byte)0x8E, (byte)0xF6, (byte)0xF3,
+ (byte)0xC9, (byte)0x23, (byte)0xC0, (byte)0x43, (byte)0xF0, (byte)0xA5, (byte)0x5B, (byte)0x18, (byte)0x8D, (byte)0x8E, (byte)0xBB, (byte)0x55,
+ (byte)0x8C, (byte)0xB8, (byte)0x5D, (byte)0x38, (byte)0xD3, (byte)0x34, (byte)0xFD, (byte)0x7C, (byte)0x17, (byte)0x57, (byte)0x43, (byte)0xA3,
+ (byte)0x1D, (byte)0x18, (byte)0x6C, (byte)0xDE, (byte)0x33, (byte)0x21, (byte)0x2C, (byte)0xB5, (byte)0x2A, (byte)0xFF, (byte)0x3C, (byte)0xE1,
+ (byte)0xB1, (byte)0x29, (byte)0x40, (byte)0x18, (byte)0x11, (byte)0x8D, (byte)0x7C, (byte)0x84, (byte)0xA7, (byte)0x0A, (byte)0x72, (byte)0xD6,
+ (byte)0x86, (byte)0xC4, (byte)0x03, (byte)0x19, (byte)0xC8, (byte)0x07, (byte)0x29, (byte)0x7A, (byte)0xCA, (byte)0x95, (byte)0x0C, (byte)0xD9,
+ (byte)0x96, (byte)0x9F, (byte)0xAB, (byte)0xD0, (byte)0x0A, (byte)0x50, (byte)0x9B, (byte)0x02, (byte)0x46, (byte)0xD3, (byte)0x08, (byte)0x3D,
+ (byte)0x66, (byte)0xA4, (byte)0x5D, (byte)0x41, (byte)0x9F, (byte)0x9C, (byte)0x7C, (byte)0xBD, (byte)0x89, (byte)0x4B, (byte)0x22, (byte)0x19,
+ (byte)0x26, (byte)0xBA, (byte)0xAB, (byte)0xA2, (byte)0x5E, (byte)0xC3, (byte)0x55, (byte)0xE9, (byte)0x2F, (byte)0x78, (byte)0xC7 };
/**
* The SKIP 1024 bit modulus
*/
- private static final BigInteger skip1024Modulus = new BigInteger(1, skip1024ModulusBytes);
+ private static final BigInteger modulus = new BigInteger(1, modulusBytes);
/**
* The base used with the SKIP 1024 bit modulus
*/
- private static final BigInteger skip1024Base = BigInteger.valueOf(2);
+ private static final BigInteger base = BigInteger.valueOf(2);
- public static final DHParameterSpec INSTANCE = new DHParameterSpec(skip1024Modulus, skip1024Base);
+ public static final DHParameterSpec INSTANCE = new DHParameterSpec(modulus, base);
}
/**

Back to the top