Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/crypto/provider/DHPublicKey.java
38922 views
/*1* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.crypto.provider;2627import java.io.*;28import java.util.Objects;29import java.math.BigInteger;30import java.security.KeyRep;31import java.security.InvalidKeyException;32import java.security.ProviderException;33import java.security.PublicKey;34import javax.crypto.spec.DHParameterSpec;35import sun.security.util.*;363738/**39* A public key in X.509 format for the Diffie-Hellman key agreement algorithm.40*41* @author Jan Luehe42*43*44* @see DHPrivateKey45* @see java.security.KeyAgreement46*/47final class DHPublicKey implements PublicKey,48javax.crypto.interfaces.DHPublicKey, Serializable {4950static final long serialVersionUID = 7647557958927458271L;5152// the public key53private BigInteger y;5455// the key bytes, without the algorithm information56private byte[] key;5758// the encoded key59private byte[] encodedKey;6061// the prime modulus62private BigInteger p;6364// the base generator65private BigInteger g;6667// the private-value length (optional)68private int l;6970private int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 };7172/**73* Make a DH public key out of a public value <code>y</code>, a prime74* modulus <code>p</code>, and a base generator <code>g</code>.75*76* @param y the public value77* @param p the prime modulus78* @param g the base generator79*80* @exception InvalidKeyException if the key cannot be encoded81*/82DHPublicKey(BigInteger y, BigInteger p, BigInteger g)83throws InvalidKeyException {84this(y, p, g, 0);85}8687/**88* Make a DH public key out of a public value <code>y</code>, a prime89* modulus <code>p</code>, a base generator <code>g</code>, and a90* private-value length <code>l</code>.91*92* @param y the public value93* @param p the prime modulus94* @param g the base generator95* @param l the private-value length96*97* @exception ProviderException if the key cannot be encoded98*/99DHPublicKey(BigInteger y, BigInteger p, BigInteger g, int l) {100this.y = y;101this.p = p;102this.g = g;103this.l = l;104try {105this.key = new DerValue(DerValue.tag_Integer,106this.y.toByteArray()).toByteArray();107this.encodedKey = getEncoded();108} catch (IOException e) {109throw new ProviderException("Cannot produce ASN.1 encoding", e);110}111}112113/**114* Make a DH public key from its DER encoding (X.509).115*116* @param encodedKey the encoded key117*118* @exception InvalidKeyException if the encoded key does not represent119* a Diffie-Hellman public key120*/121DHPublicKey(byte[] encodedKey) throws InvalidKeyException {122InputStream inStream = new ByteArrayInputStream(encodedKey);123try {124DerValue derKeyVal = new DerValue(inStream);125if (derKeyVal.tag != DerValue.tag_Sequence) {126throw new InvalidKeyException ("Invalid key format");127}128129/*130* Parse the algorithm identifier131*/132DerValue algid = derKeyVal.data.getDerValue();133if (algid.tag != DerValue.tag_Sequence) {134throw new InvalidKeyException("AlgId is not a SEQUENCE");135}136DerInputStream derInStream = algid.toDerInputStream();137ObjectIdentifier oid = derInStream.getOID();138if (oid == null) {139throw new InvalidKeyException("Null OID");140}141if (derInStream.available() == 0) {142throw new InvalidKeyException("Parameters missing");143}144145/*146* Parse the parameters147*/148DerValue params = derInStream.getDerValue();149if (params.tag == DerValue.tag_Null) {150throw new InvalidKeyException("Null parameters");151}152if (params.tag != DerValue.tag_Sequence) {153throw new InvalidKeyException("Parameters not a SEQUENCE");154}155params.data.reset();156this.p = params.data.getBigInteger();157this.g = params.data.getBigInteger();158// Private-value length is OPTIONAL159if (params.data.available() != 0) {160this.l = params.data.getInteger();161}162if (params.data.available() != 0) {163throw new InvalidKeyException("Extra parameter data");164}165166/*167* Parse the key168*/169this.key = derKeyVal.data.getBitString();170parseKeyBits();171if (derKeyVal.data.available() != 0) {172throw new InvalidKeyException("Excess key data");173}174175this.encodedKey = encodedKey.clone();176} catch (IOException | NumberFormatException e) {177throw new InvalidKeyException("Error parsing key encoding", e);178}179}180181/**182* Returns the encoding format of this key: "X.509"183*/184public String getFormat() {185return "X.509";186}187188/**189* Returns the name of the algorithm associated with this key: "DH"190*/191public String getAlgorithm() {192return "DH";193}194195/**196* Get the encoding of the key.197*/198public synchronized byte[] getEncoded() {199if (this.encodedKey == null) {200try {201DerOutputStream algid = new DerOutputStream();202203// store oid in algid204algid.putOID(new ObjectIdentifier(DH_data));205206// encode parameters207DerOutputStream params = new DerOutputStream();208params.putInteger(this.p);209params.putInteger(this.g);210if (this.l != 0) {211params.putInteger(this.l);212}213// wrap parameters into SEQUENCE214DerValue paramSequence = new DerValue(DerValue.tag_Sequence,215params.toByteArray());216// store parameter SEQUENCE in algid217algid.putDerValue(paramSequence);218219// wrap algid into SEQUENCE, and store it in key encoding220DerOutputStream tmpDerKey = new DerOutputStream();221tmpDerKey.write(DerValue.tag_Sequence, algid);222223// store key data224tmpDerKey.putBitString(this.key);225226// wrap algid and key into SEQUENCE227DerOutputStream derKey = new DerOutputStream();228derKey.write(DerValue.tag_Sequence, tmpDerKey);229this.encodedKey = derKey.toByteArray();230} catch (IOException e) {231return null;232}233}234return this.encodedKey.clone();235}236237/**238* Returns the public value, <code>y</code>.239*240* @return the public value, <code>y</code>241*/242public BigInteger getY() {243return this.y;244}245246/**247* Returns the key parameters.248*249* @return the key parameters250*/251public DHParameterSpec getParams() {252if (this.l != 0) {253return new DHParameterSpec(this.p, this.g, this.l);254} else {255return new DHParameterSpec(this.p, this.g);256}257}258259public String toString() {260String LINE_SEP = System.getProperty("line.separator");261262StringBuffer strbuf263= new StringBuffer("SunJCE Diffie-Hellman Public Key:"264+ LINE_SEP + "y:" + LINE_SEP265+ Debug.toHexString(this.y)266+ LINE_SEP + "p:" + LINE_SEP267+ Debug.toHexString(this.p)268+ LINE_SEP + "g:" + LINE_SEP269+ Debug.toHexString(this.g));270if (this.l != 0)271strbuf.append(LINE_SEP + "l:" + LINE_SEP + " " + this.l);272return strbuf.toString();273}274275private void parseKeyBits() throws InvalidKeyException {276try {277DerInputStream in = new DerInputStream(this.key);278this.y = in.getBigInteger();279} catch (IOException e) {280throw new InvalidKeyException(281"Error parsing key encoding: " + e.toString());282}283}284285/**286* Calculates a hash code value for the object.287* Objects that are equal will also have the same hashcode.288*/289public int hashCode() {290return Objects.hash(y, p, g);291}292293public boolean equals(Object obj) {294if (this == obj) return true;295296if (!(obj instanceof javax.crypto.interfaces.DHPublicKey)) {297return false;298}299300javax.crypto.interfaces.DHPublicKey other =301(javax.crypto.interfaces.DHPublicKey) obj;302DHParameterSpec otherParams = other.getParams();303return ((this.y.compareTo(other.getY()) == 0) &&304(this.p.compareTo(otherParams.getP()) == 0) &&305(this.g.compareTo(otherParams.getG()) == 0));306}307308/**309* Replace the DH public key to be serialized.310*311* @return the standard KeyRep object to be serialized312*313* @throws java.io.ObjectStreamException if a new object representing314* this DH public key could not be created315*/316private Object writeReplace() throws java.io.ObjectStreamException {317return new KeyRep(KeyRep.Type.PUBLIC,318getAlgorithm(),319getFormat(),320getEncoded());321}322}323324325