1 package org.bouncycastle.crypto.agreement; 2 3 import java.math.BigInteger; 4 5 import org.bouncycastle.crypto.BasicAgreement; 6 import org.bouncycastle.crypto.CipherParameters; 7 import org.bouncycastle.crypto.params.AsymmetricKeyParameter; 8 import org.bouncycastle.crypto.params.DHParameters; 9 import org.bouncycastle.crypto.params.DHPrivateKeyParameters; 10 import org.bouncycastle.crypto.params.DHPublicKeyParameters; 11 import org.bouncycastle.crypto.params.ParametersWithRandom; 12 13 /** 14 * a Diffie-Hellman key agreement class. 15 * <p> 16 * note: This is only the basic algorithm, it doesn't take advantage of 17 * long term public keys if they are available. See the DHAgreement class 18 * for a "better" implementation. 19 */ 20 public class DHBasicAgreement 21 implements BasicAgreement 22 { 23 private static final BigInteger ONE = BigInteger.valueOf(1); 24 25 private DHPrivateKeyParameters key; 26 private DHParameters dhParams; 27 init( CipherParameters param)28 public void init( 29 CipherParameters param) 30 { 31 AsymmetricKeyParameter kParam; 32 33 if (param instanceof ParametersWithRandom) 34 { 35 ParametersWithRandom rParam = (ParametersWithRandom)param; 36 kParam = (AsymmetricKeyParameter)rParam.getParameters(); 37 } 38 else 39 { 40 kParam = (AsymmetricKeyParameter)param; 41 } 42 43 if (!(kParam instanceof DHPrivateKeyParameters)) 44 { 45 throw new IllegalArgumentException("DHEngine expects DHPrivateKeyParameters"); 46 } 47 48 this.key = (DHPrivateKeyParameters)kParam; 49 this.dhParams = key.getParameters(); 50 } 51 getFieldSize()52 public int getFieldSize() 53 { 54 return (key.getParameters().getP().bitLength() + 7) / 8; 55 } 56 57 /** 58 * given a short term public key from a given party calculate the next 59 * message in the agreement sequence. 60 */ calculateAgreement( CipherParameters pubKey)61 public BigInteger calculateAgreement( 62 CipherParameters pubKey) 63 { 64 DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey; 65 66 if (!pub.getParameters().equals(dhParams)) 67 { 68 throw new IllegalArgumentException("Diffie-Hellman public key has wrong parameters."); 69 } 70 71 BigInteger p = dhParams.getP(); 72 73 BigInteger peerY = pub.getY(); 74 if (peerY == null || peerY.compareTo(ONE) <= 0 || peerY.compareTo(p.subtract(ONE)) >= 0) 75 { 76 throw new IllegalArgumentException("Diffie-Hellman public key is weak"); 77 } 78 79 BigInteger result = peerY.modPow(key.getX(), p); 80 if (result.equals(ONE)) 81 { 82 throw new IllegalStateException("Shared key can't be 1"); 83 } 84 85 return result; 86 } 87 } 88