/*
* (c) Copyright 2008 by Michael Beck (Debianguru@gmx.de), Edgar Kalkowski
* (eMail@edgar-kalkowski.de)
*
* This file is part of the ErkiTalk Chat Server.
*
* The ErkiTalk Chat Server is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
package erki.talk;
import java.io.IOException;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
public class DHKeyExchange {
private KeyAgreement keyAgreement;
public String getPublicKey() {
try {
AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator
.getInstance("DH");
paramGen.init(512);
AlgorithmParameters params = paramGen.generateParameters();
DHParameterSpec parameterSpec = params
.getParameterSpec(DHParameterSpec.class);
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DH");
keyPairGen.initialize(parameterSpec);
KeyPair keyPair = keyPairGen.generateKeyPair();
keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(keyPair.getPrivate());
KeyFactory keyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyPair
.getPublic().getEncoded());
return toHexString(keyFactory.generatePublic(keySpec).getEncoded());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.exit(-1);
} catch (InvalidParameterSpecException e) {
e.printStackTrace();
System.exit(-1);
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
System.exit(-1);
} catch (InvalidKeyException e) {
e.printStackTrace();
System.exit(-1);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
System.exit(-1);
}
return null;
}
public static String toString(byte[] bytes) throws IOException {
return new String(bytes, "UTF-8");
}
public static String toHexString(byte[] bytes) {
StringBuffer buffer = new StringBuffer();
int len = bytes.length;
for (int i = 0; i < len; i++) {
byte2hex(bytes[i], buffer);
}
return buffer.toString();
}
private static void byte2hex(byte b, StringBuffer buffer) {
char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };
int high = ((b & 0xf0) >> 4);
int low = (b & 0x0f);
buffer.append(hexChars[high]);
buffer.append(hexChars[low]);
}
public static byte[] toBytes(String hex) {
byte[] bytes = new byte[hex.length() / 2];
for (int i = 0; i < hex.length() / 2; i++) {
bytes[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2),
16);
}
return bytes;
}
public void injectPublicKey(String pubKey) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(toBytes(pubKey));
PublicKey publicKey = keyFactory.generatePublic(keySpec);
keyAgreement.doPhase(publicKey, true);
} catch (InvalidKeyException e) {
e.printStackTrace();
System.exit(-1);
} catch (IllegalStateException e) {
e.printStackTrace();
System.exit(-1);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.exit(-1);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
System.exit(-1);
}
}
public SecretKey getSecretKey() {
try {
return keyAgreement.generateSecret("DES");
} catch (InvalidKeyException e) {
e.printStackTrace();
System.exit(-1);
} catch (IllegalStateException e) {
e.printStackTrace();
System.exit(-1);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
System.exit(-1);
}
return null;
}
public String getPublicKey(String pubKey) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("DH");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(toBytes(pubKey));
PublicKey publicKey = keyFactory.generatePublic(keySpec);
DHParameterSpec dhParamSpec = ((DHPublicKey) keyFactory
.generatePublic(keySpec)).getParams();
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("DH");
keyPairGen.initialize(dhParamSpec);
KeyPair keyPair = keyPairGen.generateKeyPair();
keyAgreement = KeyAgreement.getInstance("DH");
keyAgreement.init(keyPair.getPrivate());
keyAgreement.doPhase(publicKey, true);
keyFactory = KeyFactory.getInstance("DH");
keySpec = new X509EncodedKeySpec(keyPair.getPublic().getEncoded());
return toHexString(keyFactory.generatePublic(keySpec).getEncoded());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
e.printStackTrace();
return null;
} catch (InvalidKeySpecException e) {
e.printStackTrace();
return null;
}
}
}