18212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompackage org.bouncycastle.crypto.agreement; 28212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 38212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport java.math.BigInteger; 48212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 58212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.crypto.BasicAgreement; 68212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.crypto.CipherParameters; 78212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstromimport org.bouncycastle.crypto.params.ECPrivateKeyParameters; 870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.crypto.params.ECPublicKeyParameters; 9f81961d489888391053b9d69720fa47714685509Quan Nguyen// BEGIN android-added 10f81961d489888391053b9d69720fa47714685509Quan Nguyenimport org.bouncycastle.math.ec.ECCurve; 11f81961d489888391053b9d69720fa47714685509Quan Nguyen// END android-added 1270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.math.ec.ECPoint; 138212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 148212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom/** 158212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * P1363 7.2.1 ECSVDP-DH 168212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * 178212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive, 188212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Diffie-Hellman version. It is based on the work of [DH76], [Mil86], 198212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * and [Kob87]. This primitive derives a shared secret value from one 208212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * party's private key and another party's public key, where both have 218212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * the same set of EC domain parameters. If two parties correctly 228212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * execute this primitive, they will produce the same output. This 238212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * primitive can be invoked by a scheme to derive a shared secret key; 248212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * specifically, it may be used with the schemes ECKAS-DH1 and 258212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * DL/ECKAS-DH2. It assumes that the input keys are valid (see also 268212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom * Section 7.2.2). 278212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom */ 288212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrompublic class ECDHBasicAgreement 298212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom implements BasicAgreement 308212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom{ 318212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom private ECPrivateKeyParameters key; 328212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 338212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public void init( 348212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom CipherParameters key) 358212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 368212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom this.key = (ECPrivateKeyParameters)key; 378212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 388212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 3970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom public int getFieldSize() 4070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 4170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return (key.getParameters().getCurve().getFieldSize() + 7) / 8; 4270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 4370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 448212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom public BigInteger calculateAgreement( 458212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom CipherParameters pubKey) 468212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom { 47f81961d489888391053b9d69720fa47714685509Quan Nguyen // BEGIN android-changed 48f81961d489888391053b9d69720fa47714685509Quan Nguyen ECPoint peerPoint = ((ECPublicKeyParameters) pubKey).getQ(); 49f81961d489888391053b9d69720fa47714685509Quan Nguyen ECCurve myCurve = key.getParameters().getCurve(); 50f81961d489888391053b9d69720fa47714685509Quan Nguyen if (peerPoint.isInfinity()) { 51f81961d489888391053b9d69720fa47714685509Quan Nguyen throw new IllegalStateException("Infinity is not a valid public key for ECDH"); 52f81961d489888391053b9d69720fa47714685509Quan Nguyen } 53f81961d489888391053b9d69720fa47714685509Quan Nguyen try { 54f81961d489888391053b9d69720fa47714685509Quan Nguyen myCurve.validatePoint(peerPoint.getXCoord().toBigInteger(), 55f81961d489888391053b9d69720fa47714685509Quan Nguyen peerPoint.getYCoord().toBigInteger()); 56f81961d489888391053b9d69720fa47714685509Quan Nguyen } catch (IllegalArgumentException ex) { 57f81961d489888391053b9d69720fa47714685509Quan Nguyen throw new IllegalStateException("The peer public key must be on the curve for ECDH"); 58f81961d489888391053b9d69720fa47714685509Quan Nguyen } 59f81961d489888391053b9d69720fa47714685509Quan Nguyen // Explicitly construct a public key using the private key's curve. 60f81961d489888391053b9d69720fa47714685509Quan Nguyen ECPoint pubPoint = myCurve.createPoint(peerPoint.getXCoord().toBigInteger(), 61f81961d489888391053b9d69720fa47714685509Quan Nguyen peerPoint.getYCoord().toBigInteger()); 6216f9ee464b68937f45d009d9c1b0eb9b544a8deeSergio Giro ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey; 634caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro if (!pub.getParameters().equals(key.getParameters())) 644caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro { 654caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro throw new IllegalStateException("ECDH public key has wrong domain parameters"); 664caba4cfca3316673ae4e330e8a47932bed8a53aSergio Giro } 67f81961d489888391053b9d69720fa47714685509Quan Nguyen ECPoint P = pubPoint.multiply(key.getD()).normalize(); 68f81961d489888391053b9d69720fa47714685509Quan Nguyen // END android-changed 698212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 705db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root if (P.isInfinity()) 715db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root { 725db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root throw new IllegalStateException("Infinity is not a valid agreement value for ECDH"); 735db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root } 748212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom 755db505e1f6a68c8d5dfdb0fed0b8607dea7bed96Kenny Root return P.getAffineXCoord().toBigInteger(); 768212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom } 778212855a312dc8ebe081a3e08b1d2d8f8757af02Brian Carlstrom} 78