diff options
Diffstat (limited to 'core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java')
-rw-r--r-- | core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java b/core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java new file mode 100644 index 00000000..9dd5d040 --- /dev/null +++ b/core/src/main/java/org/spongycastle/crypto/agreement/DHAgreement.java @@ -0,0 +1,94 @@ +package org.spongycastle.crypto.agreement; + +import java.math.BigInteger; +import java.security.SecureRandom; + +import org.spongycastle.crypto.AsymmetricCipherKeyPair; +import org.spongycastle.crypto.CipherParameters; +import org.spongycastle.crypto.generators.DHKeyPairGenerator; +import org.spongycastle.crypto.params.DHKeyGenerationParameters; +import org.spongycastle.crypto.params.DHParameters; +import org.spongycastle.crypto.params.DHPublicKeyParameters; +import org.spongycastle.crypto.params.DHPrivateKeyParameters; +import org.spongycastle.crypto.params.AsymmetricKeyParameter; +import org.spongycastle.crypto.params.ParametersWithRandom; + +/** + * a Diffie-Hellman key exchange engine. + * <p> + * note: This uses MTI/A0 key agreement in order to make the key agreement + * secure against passive attacks. If you're doing Diffie-Hellman and both + * parties have long term public keys you should look at using this. For + * further information have a look at RFC 2631. + * <p> + * It's possible to extend this to more than two parties as well, for the moment + * that is left as an exercise for the reader. + */ +public class DHAgreement +{ + private DHPrivateKeyParameters key; + private DHParameters dhParams; + private BigInteger privateValue; + private SecureRandom random; + + public void init( + CipherParameters param) + { + AsymmetricKeyParameter kParam; + + if (param instanceof ParametersWithRandom) + { + ParametersWithRandom rParam = (ParametersWithRandom)param; + + this.random = rParam.getRandom(); + kParam = (AsymmetricKeyParameter)rParam.getParameters(); + } + else + { + this.random = new SecureRandom(); + kParam = (AsymmetricKeyParameter)param; + } + + + if (!(kParam instanceof DHPrivateKeyParameters)) + { + throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters"); + } + + this.key = (DHPrivateKeyParameters)kParam; + this.dhParams = key.getParameters(); + } + + /** + * calculate our initial message. + */ + public BigInteger calculateMessage() + { + DHKeyPairGenerator dhGen = new DHKeyPairGenerator(); + dhGen.init(new DHKeyGenerationParameters(random, dhParams)); + AsymmetricCipherKeyPair dhPair = dhGen.generateKeyPair(); + + this.privateValue = ((DHPrivateKeyParameters)dhPair.getPrivate()).getX(); + + return ((DHPublicKeyParameters)dhPair.getPublic()).getY(); + } + + /** + * given a message from a given party and the corresponding public key, + * calculate the next message in the agreement sequence. In this case + * this will represent the shared secret. + */ + public BigInteger calculateAgreement( + DHPublicKeyParameters pub, + BigInteger message) + { + if (!pub.getParameters().equals(dhParams)) + { + throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters."); + } + + BigInteger p = dhParams.getP(); + + return message.modPow(key.getX(), p).multiply(pub.getY().modPow(privateValue, p)).mod(p); + } +} |