116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropackage org.bouncycastle.crypto.agreement;
216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport java.math.BigInteger;
416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.BasicAgreement;
616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.CipherParameters;
716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.AsymmetricKeyParameter;
816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHParameters;
916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHPrivateKeyParameters;
1016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.DHPublicKeyParameters;
1116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giroimport org.bouncycastle.crypto.params.ParametersWithRandom;
1216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
1316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro/**
1416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * a Diffie-Hellman key agreement class.
1516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * <p>
1616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * note: This is only the basic algorithm, it doesn't take advantage of
1716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * long term public keys if they are available. See the DHAgreement class
1816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro * for a "better" implementation.
1916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro */
2016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giropublic class DHBasicAgreement
2116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    implements BasicAgreement
2216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro{
234caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro    private static final BigInteger ONE = BigInteger.valueOf(1);
244caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
2516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private DHPrivateKeyParameters  key;
2616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    private DHParameters            dhParams;
2716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
2816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public void init(
2916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        CipherParameters    param)
3016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
3116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        AsymmetricKeyParameter  kParam;
3216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
3316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (param instanceof ParametersWithRandom)
3416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
3516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            ParametersWithRandom rParam = (ParametersWithRandom)param;
3616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            kParam = (AsymmetricKeyParameter)rParam.getParameters();
3716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
3816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        else
3916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
4016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            kParam = (AsymmetricKeyParameter)param;
4116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
4216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (!(kParam instanceof DHPrivateKeyParameters))
4416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
4516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
4616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
4716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
4816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.key = (DHPrivateKeyParameters)kParam;
4916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        this.dhParams = key.getParameters();
5016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
5116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
5216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public int getFieldSize()
5316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
5416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        return (key.getParameters().getP().bitLength() + 7) / 8;
5516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
5616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
5716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    /**
5816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * given a short term public key from a given party calculate the next
5916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     * message in the agreement sequence.
6016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro     */
6116f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    public BigInteger calculateAgreement(
6216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        CipherParameters   pubKey)
6316f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    {
6416f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        DHPublicKeyParameters   pub = (DHPublicKeyParameters)pubKey;
6516f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
6616f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        if (!pub.getParameters().equals(dhParams))
6716f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        {
6816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro            throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
6916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro        }
7016f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro
714caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        BigInteger result = pub.getY().modPow(key.getX(), dhParams.getP());
724caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        if (result.compareTo(ONE) == 0)
734caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        {
744caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro            throw new IllegalStateException("Shared key can't be 1");
754caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        }
764caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro
774caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro        return result;
7816f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro    }
7916f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro}
80