/**

* 安全的密钥交互类。

* 这个交互工具可以校验双方的身份,并对发送的DH公钥进行签名,防止中间者***。

* @author atlas
* @date 2012-9-6
*/
public class SecureKeyExchanger extends DHKeyExchanger {
/**
* 签名算法
*/
private static String signAlgorithm = "SHA1withRSA";
/**
* 此方的私钥
*/
private PrivateKey privateKey;
/**
* 此方的证书
*/
private Certificate certificate;
/**
* 用于校验彼方公钥的CA证书,此证书来自此方的CA或者此方可信任的CA
*/
private Certificate caCertificate;
/**
* 彼方的证书,在DH公钥交换之前进行交互获取的
*/
private Certificate peerCert;
/**
*
* @param out
* @param in
* @param privateKey 此方的私钥
* @param certificate 此方的证书
* @param caCertificate 用于校验彼方公钥的CA证书,此证书来自此方的CA或者此方可信任的CA
*/
public SecureKeyExchanger(Pipe pipe,
PrivateKey privateKey, Certificate certificate,
Certificate caCertificate) {
super(pipe);
this.privateKey = privateKey;
this.certificate = certificate;
this.caCertificate = caCertificate;
}
// Send the public key.
public void sendPublicKey() throws IOException,
CertificateEncodingException {
byte[] keyBytes = certificate.getEncoded();
write(keyBytes);
}
public void receivePublicKey() throws IOException, SkipException {
byte[] keyBytes =read();
try {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
peerCert = cf
.generateCertificate(new ByteArrayInputStream(keyBytes));
peerCert.verify(caCertificate.getPublicKey());
} catch (CertificateException e) {
throw new SkipException("Unsupported certificate type X.509", e);
} catch (InvalidKeyException e) {
throw new SkipException(
"Peer's certificate was not invlaid or not signed by current CA.",
e);
} catch (NoSuchAlgorithmException e) {
throw new SkipException("Signature algorithm not supported.", e);
} catch (NoSuchProviderException e) {
throw new SkipException("No signature Provider.", e);
} catch (SignatureException e) {
throw new SkipException(
"Peer's certificate was not invlaid or not signed by current CA.",
e);
}
}
@Override
public void receiveDHPublicKey() throws IOException, SkipException {
// receiver public key
receivePublicKey();
// receive dh public key
byte[] publicKeyBytes = read();
// receive signature of dh public key
byte[] sign = read();
KeyFactory kf;
try {
// verify signature using peer certificate
Signature sig = Signature.getInstance(signAlgorithm);
sig.initVerify(peerCert);
sig.verify(sign);
kf = KeyFactory.getInstance("DH");
X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(publicKeyBytes);
peerDHPublicKey = kf.generatePublic(x509Spec);
} catch (NoSuchAlgorithmException e) {
throw new SkipException("Signature algorithm " + signAlgorithm
+ " not supported.", e);
} catch (InvalidKeySpecException e) {
throw new SkipException("Peer's public key invalid.", e);
} catch (InvalidKeyException e) {
throw new SkipException("Peer's public key invalid.", e);
} catch (SignatureException e) {
throw new SkipException("Invalid signature.", e);
}
}
@Override
public void sendDHPublicKey() throws IOException, SkipException {
try {
// send public key
sendPublicKey();
// send dh public key
byte[] keyBytes = dhKeyPair.getPublic().getEncoded();
write(keyBytes);
// sign dh public key using my private key and send the signature
Signature sig;
sig = Signature.getInstance(signAlgorithm);
sig.initSign(privateKey);
sig.update(keyBytes);
byte[] sign = sig.sign();
write(sign);
} catch (NoSuchAlgorithmException e) {
throw new SkipException("Signature algorithm " + signAlgorithm
+ " not supported.", e);
} catch (InvalidKeyException e) {
throw new SkipException("My private key invalid.", e);
} catch (SignatureException e) {
throw new SkipException(
"Signature exception when sending dh public key.", e);
} catch (CertificateEncodingException e) {
throw new SkipException("error when sending dh public key.", e);
}
}
}