/*
 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.ec;

import java.security.*;
import java.security.interfaces.*;
import java.security.spec.*;

import javax.crypto.*;
import javax.crypto.spec.*;

import sun.security.util.ECUtil;

KeyAgreement implementation for ECDH.
Since: 1.7
/** * KeyAgreement implementation for ECDH. * * @since 1.7 */
public final class ECDHKeyAgreement extends KeyAgreementSpi { // private key, if initialized private ECPrivateKey privateKey; // encoded public point, non-null between doPhase() & generateSecret() only private byte[] publicValue; // length of the secret to be derived private int secretLen;
Constructs a new ECDHKeyAgreement.
/** * Constructs a new ECDHKeyAgreement. */
public ECDHKeyAgreement() { } // see JCE spec @Override protected void engineInit(Key key, SecureRandom random) throws InvalidKeyException { if (!(key instanceof PrivateKey)) { throw new InvalidKeyException ("Key must be instance of PrivateKey"); } privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key); publicValue = null; } // see JCE spec @Override protected void engineInit(Key key, AlgorithmParameterSpec params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { if (params != null) { throw new InvalidAlgorithmParameterException ("Parameters not supported"); } engineInit(key, random); } // see JCE spec @Override protected Key engineDoPhase(Key key, boolean lastPhase) throws InvalidKeyException, IllegalStateException { if (privateKey == null) { throw new IllegalStateException("Not initialized"); } if (publicValue != null) { throw new IllegalStateException("Phase already executed"); } if (!lastPhase) { throw new IllegalStateException ("Only two party agreement supported, lastPhase must be true"); } if (!(key instanceof ECPublicKey)) { throw new InvalidKeyException ("Key must be a PublicKey with algorithm EC"); } ECPublicKey ecKey = (ECPublicKey)key; ECParameterSpec params = ecKey.getParams(); if (ecKey instanceof ECPublicKeyImpl) { publicValue = ((ECPublicKeyImpl)ecKey).getEncodedPublicValue(); } else { // instanceof ECPublicKey publicValue = ECUtil.encodePoint(ecKey.getW(), params.getCurve()); } int keyLenBits = params.getCurve().getField().getFieldSize(); secretLen = (keyLenBits + 7) >> 3; return null; } // see JCE spec @Override protected byte[] engineGenerateSecret() throws IllegalStateException { if ((privateKey == null) || (publicValue == null)) { throw new IllegalStateException("Not initialized correctly"); } byte[] s = privateKey.getS().toByteArray(); byte[] encodedParams = // DER OID ECUtil.encodeECParameterSpec(null, privateKey.getParams()); try { return deriveKey(s, publicValue, encodedParams); } catch (GeneralSecurityException e) { throw new ProviderException("Could not derive key", e); } } // see JCE spec @Override protected int engineGenerateSecret(byte[] sharedSecret, int offset) throws IllegalStateException, ShortBufferException { if (offset + secretLen > sharedSecret.length) { throw new ShortBufferException("Need " + secretLen + " bytes, only " + (sharedSecret.length - offset) + " available"); } byte[] secret = engineGenerateSecret(); System.arraycopy(secret, 0, sharedSecret, offset, secret.length); return secret.length; } // see JCE spec @Override protected SecretKey engineGenerateSecret(String algorithm) throws IllegalStateException, NoSuchAlgorithmException, InvalidKeyException { if (algorithm == null) { throw new NoSuchAlgorithmException("Algorithm must not be null"); } if (!(algorithm.equals("TlsPremasterSecret"))) { throw new NoSuchAlgorithmException ("Only supported for algorithm TlsPremasterSecret"); } return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret"); }
Generates a secret key using the public and private keys.
Params:
  • s – the private key's S value.
  • w – the public key's W point (in uncompressed form).
  • encodedParams – the curve's DER encoded object identifier.
Returns:byte[] the secret key.
/** * Generates a secret key using the public and private keys. * * @param s the private key's S value. * @param w the public key's W point (in uncompressed form). * @param encodedParams the curve's DER encoded object identifier. * * @return byte[] the secret key. */
private static native byte[] deriveKey(byte[] s, byte[] w, byte[] encodedParams) throws GeneralSecurityException; }