package com.CryptoAlgorithms.DiffieHellman;
import com.exceptions.CreatingDHAgreementException;
import org.springframework.stereotype.Controller;
import javax.crypto.KeyAgreement;
import javax.crypto.spec.DHParameterSpec;
import java.math.BigInteger;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* Created by Steven Kok on 5/29/14.
*/
@Controller
public class DHAlgorithm {
public static final int SIZE = 512;
public static final String CREATING_DH_AGREEMENT_FAILED = "Creating DH agreement failed.";
/**
* Generates public values: prime 'p', primitive root 'g' and 'A'.
* And private value: 'a'
*
* @return DHAgreementModel
* @throws CreatingDHAgreementException
*/
public DHAgreementModel generateInitialNumbers() throws CreatingDHAgreementException {
try {
AlgorithmParameterGenerator algorithmParameterGenerator = AlgorithmParameterGenerator.getInstance("DH");
algorithmParameterGenerator.init(SIZE);
AlgorithmParameters algorithmParameters = algorithmParameterGenerator.generateParameters();
DHParameterSpec parameterSpec = algorithmParameters.getParameterSpec(DHParameterSpec.class);
KeyPair keyPair = createKeyPair(parameterSpec);
return new DHAgreementModel(parameterSpec.getP(), parameterSpec.getG(), keyPair.getPrivate().getEncoded(), keyPair.getPublic().getEncoded());
} catch (GeneralSecurityException e) {
throw new CreatingDHAgreementException(CREATING_DH_AGREEMENT_FAILED, e);
}
}
/**
* Generate values when prime 'p' and primitive root 'g' are already known.
*
* @param p
* @param g
* @return
*/
public DHAgreementModel generateInitialNumbers(BigInteger p, BigInteger g) throws CreatingDHAgreementException {
try {
KeyPair keyPair = createKeyPair(new DHParameterSpec(p, g));
return new DHAgreementModel(p, g, keyPair.getPrivate().getEncoded(), keyPair.getPublic().getEncoded());
} catch (GeneralSecurityException e) {
throw new CreatingDHAgreementException(CREATING_DH_AGREEMENT_FAILED, e);
}
}
private KeyPair createKeyPair(DHParameterSpec parameterSpec) throws NoSuchAlgorithmException, InvalidAlgorithmParameterException {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("DH");
keyPairGenerator.initialize(parameterSpec, new SecureRandom());
return keyPairGenerator.generateKeyPair();
}
/**
* Generates secret key from private 'a' and public 'B'.
*
* @param a
* @param B
*/
public byte[] generateSecret(byte[] a, byte[] B) throws CreatingDHAgreementException {
try {
// Get public B
KeyFactory keyFactory_B = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509EncodedKeySpec_B = new X509EncodedKeySpec(B);
PublicKey publicKey_B = keyFactory_B.generatePublic(x509EncodedKeySpec_B);
// Get private a
KeyFactory keyFactory_a = KeyFactory.getInstance("DH");
PKCS8EncodedKeySpec pkcs8EncodedKeySpec_a = new PKCS8EncodedKeySpec(a);
PrivateKey privateKey_a = keyFactory_a.generatePrivate(pkcs8EncodedKeySpec_a);
KeyAgreement keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(privateKey_a);
keyAgreement.doPhase(publicKey_B, true);
return keyAgreement.generateSecret();
} catch (GeneralSecurityException e) {
throw new CreatingDHAgreementException("Failed to generate secret.", e);
}
}
}