1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage org.bouncycastle.crypto.agreement;
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.math.BigInteger;
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.SecureRandom;
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.CipherParameters;
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.DHParameters;
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.DHPublicKeyParameters;
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.DHPrivateKeyParameters;
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.AsymmetricKeyParameter;
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.bouncycastle.crypto.params.ParametersWithRandom;
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a Diffie-Hellman key exchange engine.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * note: This uses MTI/A0 key agreement in order to make the key agreement
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * secure against passive attacks. If you're doing Diffie-Hellman and both
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * parties have long term public keys you should look at using this. For
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * further information have a look at RFC 2631.
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p>
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's possible to extend this to more than two parties as well, for the moment
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * that is left as an exercise for the reader.
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DHAgreement
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private DHPrivateKeyParameters  key;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private DHParameters            dhParams;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private BigInteger              privateValue;
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private SecureRandom            random;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void init(
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        CipherParameters    param)
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        AsymmetricKeyParameter  kParam;
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (param instanceof ParametersWithRandom)
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ParametersWithRandom    rParam = (ParametersWithRandom)param;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.random = rParam.getRandom();
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kParam = (AsymmetricKeyParameter)rParam.getParameters();
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            this.random = new SecureRandom();
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kParam = (AsymmetricKeyParameter)param;
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!(kParam instanceof DHPrivateKeyParameters))
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters");
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.key = (DHPrivateKeyParameters)kParam;
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.dhParams = key.getParameters();
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * calculate our initial message.
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public BigInteger calculateMessage()
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        this.privateValue = new BigInteger(
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    dhParams.getP().bitLength() - 1, 0, random);
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return dhParams.getG().modPow(privateValue, dhParams.getP());
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * given a message from a given party and the coresponding public key
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * calculate the next message in the agreement sequence. In this case
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this will represent the shared secret.
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public BigInteger calculateAgreement(
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        DHPublicKeyParameters   pub,
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        BigInteger              message)
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (!pub.getParameters().equals(dhParams))
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        {
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters.");
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return message.modPow(key.getX(), dhParams.getP()).multiply(pub.getY().modPow(privateValue, dhParams.getP())).mod(dhParams.getP());
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
87