/* * Copyright 2011 David Brazdil * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package uk.ac.cam.db538.cryptosms.crypto; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import org.spongycastle.crypto.AsymmetricCipherKeyPair; import org.spongycastle.crypto.agreement.ECDHBasicAgreement; import org.spongycastle.crypto.generators.ECKeyPairGenerator; import org.spongycastle.crypto.params.ECDomainParameters; import org.spongycastle.crypto.params.ECKeyGenerationParameters; import org.spongycastle.crypto.params.ECPrivateKeyParameters; import org.spongycastle.crypto.params.ECPublicKeyParameters; import org.spongycastle.math.ec.ECCurve; import org.spongycastle.math.ec.ECPoint; import org.spongycastle.util.encoders.Hex; /* * Class handling the ECDH key negotiation */ public class EllipticCurveDeffieHellman { public static final int LENGTH_PUBLIC_KEY = 33; public static final int LENGTH_PRIVATE_KEY = 32; public static final BigInteger ECDH_P = new BigInteger("0FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", 16); public static final BigInteger ECDH_A = new BigInteger("0FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", 16); public static final BigInteger ECDH_B = new BigInteger("05AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", 16); public static final BigInteger ECDH_N = new BigInteger("0FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", 16); public static final BigInteger ECDH_H = BigInteger.valueOf(1); public static final BigInteger ECDH_G_X = new BigInteger("06B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", 16); public static final BigInteger ECDH_G_Y = new BigInteger("04FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", 16); public static final byte[] ECDH_G = Hex.decode("036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"); public static final ECCurve.Fp ECDH_CURVE = new ECCurve.Fp(ECDH_P, ECDH_A, ECDH_B); public static final ECDomainParameters ECDH_PARAMS = new ECDomainParameters(ECDH_CURVE, ECDH_CURVE.decodePoint(ECDH_G), ECDH_N, ECDH_H); private static SecureRandom mRandom; static { try { mRandom = SecureRandom.getInstance("SHA1PRNG"); } catch (NoSuchAlgorithmException e){ throw new RuntimeException("No secure random available!"); } } private AsymmetricCipherKeyPair mKeyPair; /** * Instantiates a new elliptic curve deffie hellman. */ public EllipticCurveDeffieHellman() { ECKeyGenerationParameters paramsKeyGen = new ECKeyGenerationParameters(ECDH_PARAMS, mRandom); ECKeyPairGenerator keyGen = new ECKeyPairGenerator(); keyGen.init(paramsKeyGen); mKeyPair = keyGen.generateKeyPair(); } /** * Instantiates a new elliptic curve deffie hellman. * * @param privateKey the private key */ public EllipticCurveDeffieHellman(byte[] privateKey) { ECKeyGenerationParameters paramsKeyGen = new ECKeyGenerationParameters(ECDH_PARAMS, mRandom); ECKeyPairGenerator keyGen = new ECKeyPairGenerator(); keyGen.init(paramsKeyGen); mKeyPair = keyGen.createKeyPair(new BigInteger(privateKey)); } public byte[] getPublicKey() { return ((ECPublicKeyParameters) mKeyPair.getPublic()).getQ().getCompressed().getEncoded(); } public byte[] getPrivateKey() { return ((ECPrivateKeyParameters) mKeyPair.getPrivate()).getD().toByteArray(); } /** * Gets the shared key. * * @param otherPublicKey the other public key * @return the shared key */ public BigInteger getSharedKey(byte[] otherPublicKey) { ECPoint point = ECDH_CURVE.decodePoint(otherPublicKey); // return the shared secret ECDHBasicAgreement agreement = new ECDHBasicAgreement(); agreement.init(mKeyPair.getPrivate()); return agreement.calculateAgreement(new ECPublicKeyParameters(point, ECDH_PARAMS)); } }