package org.bouncycastle.jce.provider;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.KeyAgreementSpi;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.agreement.ECDHBasicAgreement;
//import org.bouncycastle.crypto.agreement.ECDHCBasicAgreement;
import org.bouncycastle.jce.interfaces.ECPrivateKey;
import org.bouncycastle.jce.interfaces.ECPublicKey;
/**
* Diffie-Hellman key agreement using elliptic curve keys, ala IEEE P1363
* both the simple one, and the simple one with cofactors are supported.
*/
public class JCEECDHKeyAgreement
extends KeyAgreementSpi
{
private BigInteger result;
private CipherParameters privKey;
private BasicAgreement agreement;
protected JCEECDHKeyAgreement(
BasicAgreement agreement)
{
this.agreement = agreement;
}
public Key
doPhase(
Key key,
boolean lastPhase )
throws InvalidKeyException, IllegalStateException
{
return( engineDoPhase( key, lastPhase ));
}
protected Key engineDoPhase(
Key key,
boolean lastPhase)
throws InvalidKeyException, IllegalStateException
{
if (privKey == null)
{
throw new IllegalStateException("EC Diffie-Hellman not initialised.");
}
if (!lastPhase)
{
throw new IllegalStateException("EC Diffie-Hellman can only be between two parties.");
}
if (!(key instanceof ECPublicKey))
{
throw new InvalidKeyException("EC Key Agreement doPhase requires ECPublicKey");
}
CipherParameters pubKey = ECUtil.generatePublicKeyParameter((PublicKey)key);
result = agreement.calculateAgreement(pubKey);
return null;
}
public byte[]
generateSecret()
throws IllegalStateException
{
return( engineGenerateSecret());
}
protected byte[] engineGenerateSecret()
throws IllegalStateException
{
return result.toByteArray();
}
protected int engineGenerateSecret(
byte[] sharedSecret,
int offset)
throws IllegalStateException, ShortBufferException
{
byte[] secret = result.toByteArray();
if (sharedSecret.length - offset < secret.length)
{
throw new ShortBufferException("ECKeyAgreement - buffer too short");
}
System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
return secret.length;
}
protected SecretKey engineGenerateSecret(
String algorithm)
{
return new SecretKeySpec(result.toByteArray(), algorithm);
}
public void
init(
Key key )
throws InvalidKeyException, InvalidAlgorithmParameterException
{
engineInit( key, null );
}
protected void engineInit(
Key key,
AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidKeyException, InvalidAlgorithmParameterException
{
if (!(key instanceof ECPrivateKey))
{
throw new InvalidKeyException("ECKeyAgreement requires ECPrivateKey for initialisation");
}
privKey = ECUtil.generatePrivateKeyParameter((PrivateKey)key);
agreement.init(privKey);
}
protected void engineInit(
Key key,
SecureRandom random)
throws InvalidKeyException
{
if (!(key instanceof ECPrivateKey))
{
throw new InvalidKeyException("ECKeyAgreement requires ECPrivateKey");
}
privKey = ECUtil.generatePrivateKeyParameter((PrivateKey)key);
agreement.init(privKey);
}
public static class DH
extends JCEECDHKeyAgreement
{
public DH()
{
super(new ECDHBasicAgreement());
}
}
/*
public static class DHC
extends JCEECDHKeyAgreement
{
public DHC()
{
super(new ECDHCBasicAgreement());
}
}
*/
}