1package org.bouncycastle.crypto.agreement; 2 3import java.math.BigInteger; 4 5import org.bouncycastle.crypto.BasicAgreement; 6import org.bouncycastle.crypto.CipherParameters; 7import org.bouncycastle.crypto.params.ECPrivateKeyParameters; 8import org.bouncycastle.crypto.params.ECPublicKeyParameters; 9// BEGIN android-added 10import org.bouncycastle.math.ec.ECCurve; 11// END android-added 12import org.bouncycastle.math.ec.ECPoint; 13 14/** 15 * P1363 7.2.1 ECSVDP-DH 16 * 17 * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, 18 * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], 19 * and [Kob87]. This primitive derives a shared secret value from one 20 * party's private key and another party's public key, where both have 21 * the same set of EC domain parameters. If two parties correctly 22 * execute this primitive, they will produce the same output. This 23 * primitive can be invoked by a scheme to derive a shared secret key; 24 * specifically, it may be used with the schemes ECKAS-DH1 and 25 * DL/ECKAS-DH2. It assumes that the input keys are valid (see also 26 * Section 7.2.2). 27 */ 28public class ECDHBasicAgreement 29 implements BasicAgreement 30{ 31 private ECPrivateKeyParameters key; 32 33 public void init( 34 CipherParameters key) 35 { 36 this.key = (ECPrivateKeyParameters)key; 37 } 38 39 public int getFieldSize() 40 { 41 return (key.getParameters().getCurve().getFieldSize() + 7) / 8; 42 } 43 44 public BigInteger calculateAgreement( 45 CipherParameters pubKey) 46 { 47 // BEGIN android-changed 48 ECPoint peerPoint = ((ECPublicKeyParameters) pubKey).getQ(); 49 ECCurve myCurve = key.getParameters().getCurve(); 50 if (peerPoint.isInfinity()) { 51 throw new IllegalStateException("Infinity is not a valid public key for ECDH"); 52 } 53 try { 54 myCurve.validatePoint(peerPoint.getXCoord().toBigInteger(), 55 peerPoint.getYCoord().toBigInteger()); 56 } catch (IllegalArgumentException ex) { 57 throw new IllegalStateException("The peer public key must be on the curve for ECDH"); 58 } 59 // Explicitly construct a public key using the private key's curve. 60 ECPoint pubPoint = myCurve.createPoint(peerPoint.getXCoord().toBigInteger(), 61 peerPoint.getYCoord().toBigInteger()); 62 ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey; 63 if (!pub.getParameters().equals(key.getParameters())) 64 { 65 throw new IllegalStateException("ECDH public key has wrong domain parameters"); 66 } 67 ECPoint P = pubPoint.multiply(key.getD()).normalize(); 68 // END android-changed 69 70 if (P.isInfinity()) 71 { 72 throw new IllegalStateException("Infinity is not a valid agreement value for ECDH"); 73 } 74 75 return P.getAffineXCoord().toBigInteger(); 76 } 77} 78