Path: blob/master/src/java.base/share/classes/sun/security/provider/DSA.java
67848 views
/*1* Copyright (c) 1996, 2021, 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 sun.security.provider;2627import java.io.*;28import java.util.*;29import java.math.BigInteger;30import java.nio.ByteBuffer;3132import java.security.*;33import java.security.SecureRandom;34import java.security.interfaces.*;35import java.security.spec.*;3637import sun.security.util.Debug;38import sun.security.util.DerValue;39import sun.security.util.DerInputStream;40import sun.security.util.DerOutputStream;41import sun.security.jca.JCAUtil;4243/**44* The Digital Signature Standard (using the Digital Signature45* Algorithm), as described in fips186-3 of the National Instute of46* Standards and Technology (NIST), using SHA digest algorithms47* from FIPS180-3.48*49* This file contains the signature implementation for the50* SHA1withDSA (DSS), SHA224withDSA, SHA256withDSA, SHA384withDSA,51* SHA512withDSA, SHA3-224withDSA, SHA3-256withDSA, SHA3-384withDSA,52* SHA3-512withDSA, as well as RawDSA, used by TLS among others.53* RawDSA expects the 20 byte SHA-1 digest as input via update rather54* than the original data like other signature implementations.55*56* In addition, IEEE P1363 signature format is supported. The57* corresponding implementation is registered under <sig>inP1363Format,58* e.g. SHA256withDSAinP1363Format.59*60* @author Benjamin Renaud61*62* @since 1.163*64* @see DSAPublicKey65* @see DSAPrivateKey66*/67abstract class DSA extends SignatureSpi {6869/* Are we debugging? */70private static final boolean debug = false;7172/* The number of bits used in exponent blinding */73private static final int BLINDING_BITS = 7;7475/* The constant component of the exponent blinding value */76private static final BigInteger BLINDING_CONSTANT =77BigInteger.valueOf(1 << BLINDING_BITS);7879/* The parameter object */80private DSAParams params;8182/* algorithm parameters */83private BigInteger presetP, presetQ, presetG;8485/* The public key, if any */86private BigInteger presetY;8788/* The private key, if any */89private BigInteger presetX;9091/* The RNG used to output a seed for generating k */92private SecureRandom signingRandom;9394/* The message digest object used */95private final MessageDigest md;9697/* The format. true for the IEEE P1363 format. false (default) for ASN.1 */98private final boolean p1363Format;99100/**101* Construct a blank DSA object. It must be102* initialized before being usable for signing or verifying.103*/104DSA(MessageDigest md) {105this(md, false);106}107108/**109* Construct a blank DSA object that will use the specified110* signature format. {@code p1363Format} should be {@code true} to111* use the IEEE P1363 format. If {@code p1363Format} is {@code false},112* the DER-encoded ASN.1 format will be used. The DSA object must be113* initialized before being usable for signing or verifying.114*/115DSA(MessageDigest md, boolean p1363Format) {116super();117this.md = md;118this.p1363Format = p1363Format;119}120121private static void checkKey(DSAParams params, int digestLen, String mdAlgo)122throws InvalidKeyException {123// FIPS186-3 states in sec4.2 that a hash function which provides124// a lower security strength than the (L, N) pair ordinarily should125// not be used.126int valueN = params.getQ().bitLength();127if (valueN > digestLen) {128throw new InvalidKeyException("The security strength of " +129mdAlgo + " digest algorithm is not sufficient for this key size");130}131}132133/**134* Initialize the DSA object with a DSA private key.135*136* @param privateKey the DSA private key137*138* @exception InvalidKeyException if the key is not a valid DSA private139* key.140*/141protected void engineInitSign(PrivateKey privateKey)142throws InvalidKeyException {143if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) {144throw new InvalidKeyException("not a DSA private key: " +145privateKey);146}147148java.security.interfaces.DSAPrivateKey priv =149(java.security.interfaces.DSAPrivateKey)privateKey;150151// check for algorithm specific constraints before doing initialization152DSAParams params = priv.getParams();153if (params == null) {154throw new InvalidKeyException("DSA private key lacks parameters");155}156157// check key size against hash output size for signing158// skip this check for verification to minimize impact on existing apps159if (!"NullDigest20".equals(md.getAlgorithm())) {160checkKey(params, md.getDigestLength()*8, md.getAlgorithm());161}162163this.params = params;164this.presetX = priv.getX();165this.presetY = null;166this.presetP = params.getP();167this.presetQ = params.getQ();168this.presetG = params.getG();169this.md.reset();170}171/**172* Initialize the DSA object with a DSA public key.173*174* @param publicKey the DSA public key.175*176* @exception InvalidKeyException if the key is not a valid DSA public177* key.178*/179protected void engineInitVerify(PublicKey publicKey)180throws InvalidKeyException {181if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) {182throw new InvalidKeyException("not a DSA public key: " +183publicKey);184}185java.security.interfaces.DSAPublicKey pub =186(java.security.interfaces.DSAPublicKey)publicKey;187188// check for algorithm specific constraints before doing initialization189DSAParams params = pub.getParams();190if (params == null) {191throw new InvalidKeyException("DSA public key lacks parameters");192}193this.params = params;194this.presetY = pub.getY();195this.presetX = null;196this.presetP = params.getP();197this.presetQ = params.getQ();198this.presetG = params.getG();199this.md.reset();200}201202/**203* Update a byte to be signed or verified.204*/205protected void engineUpdate(byte b) {206md.update(b);207}208209/**210* Update an array of bytes to be signed or verified.211*/212protected void engineUpdate(byte[] data, int off, int len) {213md.update(data, off, len);214}215216protected void engineUpdate(ByteBuffer b) {217md.update(b);218}219220221/**222* Sign all the data thus far updated. The signature format is223* determined by {@code p1363Format}. If {@code p1363Format} is224* {@code false} (the default), then the signature is formatted225* according to the Canonical Encoding Rules, returned as a DER226* sequence of Integers, r and s. If {@code p1363Format} is227* {@code false}, the signature is returned in the IEEE P1363228* format, which is the concatenation or r and s.229*230* @return a signature block formatted according to the format231* indicated by {@code p1363Format}232*233* @exception SignatureException if the signature object was not234* properly initialized, or if another exception occurs.235*236* @see sun.security.DSA#engineUpdate237* @see sun.security.DSA#engineVerify238*/239protected byte[] engineSign() throws SignatureException {240BigInteger k = generateK(presetQ);241BigInteger r = generateR(presetP, presetQ, presetG, k);242BigInteger s = generateS(presetX, presetQ, r, k);243244if (p1363Format) {245// Return the concatenation of r and s246byte[] rBytes = r.toByteArray();247byte[] sBytes = s.toByteArray();248249int size = presetQ.bitLength() / 8;250byte[] outseq = new byte[size * 2];251252int rLength = rBytes.length;253int sLength = sBytes.length;254int i;255for (i = rLength; i > 0 && rBytes[rLength - i] == 0; i--);256257int j;258for (j = sLength;259j > 0 && sBytes[sLength - j] == 0; j--);260261System.arraycopy(rBytes, rLength - i, outseq, size - i, i);262System.arraycopy(sBytes, sLength - j, outseq, size * 2 - j, j);263264return outseq;265} else {266// Return the DER-encoded ASN.1 form267try {268DerOutputStream outseq = new DerOutputStream(100);269outseq.putInteger(r);270outseq.putInteger(s);271DerValue result = new DerValue(DerValue.tag_Sequence,272outseq.toByteArray());273274return result.toByteArray();275276} catch (IOException e) {277throw new SignatureException("error encoding signature");278}279}280}281282/**283* Verify all the data thus far updated.284*285* @param signature the alleged signature, encoded using the286* Canonical Encoding Rules, as a sequence of integers, r and s.287*288* @exception SignatureException if the signature object was not289* properly initialized, or if another exception occurs.290*291* @see sun.security.DSA#engineUpdate292* @see sun.security.DSA#engineSign293*/294protected boolean engineVerify(byte[] signature)295throws SignatureException {296return engineVerify(signature, 0, signature.length);297}298299/**300* Verify all the data thus far updated.301*302* @param signature the alleged signature, encoded using the303* format indicated by {@code p1363Format}. If {@code p1363Format}304* is {@code false} (the default), then the signature is formatted305* according to the Canonical Encoding Rules, as a DER sequence of306* Integers, r and s. If {@code p1363Format} is {@code false},307* the signature is in the IEEE P1363 format, which is the308* concatenation or r and s.309*310* @param offset the offset to start from in the array of bytes.311*312* @param length the number of bytes to use, starting at offset.313*314* @exception SignatureException if the signature object was not315* properly initialized, or if another exception occurs.316*317* @see sun.security.DSA#engineUpdate318* @see sun.security.DSA#engineSign319*/320protected boolean engineVerify(byte[] signature, int offset, int length)321throws SignatureException {322323BigInteger r = null;324BigInteger s = null;325326if (p1363Format) {327if ((length & 1) == 1) {328// length of signature byte array should be even329throw new SignatureException("invalid signature format");330}331int mid = length/2;332r = new BigInteger(Arrays.copyOfRange(signature, 0, mid));333s = new BigInteger(Arrays.copyOfRange(signature, mid, length));334} else {335// first decode the signature.336try {337// Enforce strict DER checking for signatures338DerInputStream in =339new DerInputStream(signature, offset, length, false);340DerValue[] values = in.getSequence(2);341342// check number of components in the read sequence343// and trailing data344if ((values.length != 2) || (in.available() != 0)) {345throw new IOException("Invalid encoding for signature");346}347r = values[0].getBigInteger();348s = values[1].getBigInteger();349} catch (IOException e) {350throw new SignatureException("Invalid encoding for signature", e);351}352}353354// some implementations do not correctly encode values in the ASN.1355// 2's complement format. force r and s to be positive in order to356// to validate those signatures357if (r.signum() < 0) {358r = new BigInteger(1, r.toByteArray());359}360if (s.signum() < 0) {361s = new BigInteger(1, s.toByteArray());362}363364if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)365&& r.signum() > 0 && s.signum() > 0) {366BigInteger w = generateW(presetP, presetQ, presetG, s);367BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r);368return v.equals(r);369} else {370throw new SignatureException("invalid signature: out of range values");371}372}373374@Deprecated375protected void engineSetParameter(String key, Object param) {376throw new InvalidParameterException("No parameter accepted");377}378379@Override380protected void engineSetParameter(AlgorithmParameterSpec params)381throws InvalidAlgorithmParameterException {382if (params != null) {383throw new InvalidAlgorithmParameterException("No parameter accepted");384}385}386387@Deprecated388protected Object engineGetParameter(String key) {389return null;390}391392@Override393protected AlgorithmParameters engineGetParameters() {394return null;395}396397398private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,399BigInteger k) {400401// exponent blinding to hide information from timing channel402SecureRandom random = getSigningRandom();403// start with a random blinding component404BigInteger blindingValue = new BigInteger(BLINDING_BITS, random);405// add the fixed blinding component406blindingValue = blindingValue.add(BLINDING_CONSTANT);407// replace k with a blinded value that is congruent (mod q)408k = k.add(q.multiply(blindingValue));409410BigInteger temp = g.modPow(k, p);411return temp.mod(q);412}413414private BigInteger generateS(BigInteger x, BigInteger q,415BigInteger r, BigInteger k) throws SignatureException {416417byte[] s2;418try {419s2 = md.digest();420} catch (RuntimeException re) {421// Only for RawDSA due to its 20-byte length restriction422throw new SignatureException(re.getMessage());423}424// get the leftmost min(N, outLen) bits of the digest value425int nBytes = q.bitLength()/8;426if (nBytes < s2.length) {427s2 = Arrays.copyOfRange(s2, 0, nBytes);428}429BigInteger z = new BigInteger(1, s2);430BigInteger k1 = k.modInverse(q);431432return x.multiply(r).add(z).multiply(k1).mod(q);433}434435private BigInteger generateW(BigInteger p, BigInteger q,436BigInteger g, BigInteger s) {437return s.modInverse(q);438}439440private BigInteger generateV(BigInteger y, BigInteger p,441BigInteger q, BigInteger g, BigInteger w, BigInteger r)442throws SignatureException {443444byte[] s2;445try {446s2 = md.digest();447} catch (RuntimeException re) {448// Only for RawDSA due to its 20-byte length restriction449throw new SignatureException(re.getMessage());450}451// get the leftmost min(N, outLen) bits of the digest value452int nBytes = q.bitLength()/8;453if (nBytes < s2.length) {454s2 = Arrays.copyOfRange(s2, 0, nBytes);455}456BigInteger z = new BigInteger(1, s2);457458BigInteger u1 = z.multiply(w).mod(q);459BigInteger u2 = (r.multiply(w)).mod(q);460461BigInteger t1 = g.modPow(u1,p);462BigInteger t2 = y.modPow(u2,p);463BigInteger t3 = t1.multiply(t2);464BigInteger t5 = t3.mod(p);465return t5.mod(q);466}467468protected BigInteger generateK(BigInteger q) {469// Implementation defined in FIPS 186-4 AppendixB.2.1.470SecureRandom random = getSigningRandom();471byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];472473random.nextBytes(kValue);474return new BigInteger(1, kValue).mod(475q.subtract(BigInteger.ONE)).add(BigInteger.ONE);476}477478// Use the application-specified SecureRandom Object if provided.479// Otherwise, use our default SecureRandom Object.480protected SecureRandom getSigningRandom() {481if (signingRandom == null) {482if (appRandom != null) {483signingRandom = appRandom;484} else {485signingRandom = JCAUtil.getSecureRandom();486}487}488return signingRandom;489}490491/**492* Return a human readable rendition of the engine.493*/494public String toString() {495String printable = "DSA Signature";496if (presetP != null && presetQ != null && presetG != null) {497printable += "\n\tp: " + Debug.toHexString(presetP);498printable += "\n\tq: " + Debug.toHexString(presetQ);499printable += "\n\tg: " + Debug.toHexString(presetG);500} else {501printable += "\n\t P, Q or G not initialized.";502}503if (presetY != null) {504printable += "\n\ty: " + Debug.toHexString(presetY);505}506if (presetY == null && presetX == null) {507printable += "\n\tUNINIIALIZED";508}509return printable;510}511512/**513* SHA3-224withDSA implementation.514*/515public static final class SHA3_224withDSA extends DSA {516public SHA3_224withDSA() throws NoSuchAlgorithmException {517super(MessageDigest.getInstance("SHA3-224"));518}519}520521/**522* SHA3-224withDSA implementation that uses the IEEE P1363 format.523*/524public static final class SHA3_224withDSAinP1363Format extends DSA {525public SHA3_224withDSAinP1363Format() throws NoSuchAlgorithmException {526super(MessageDigest.getInstance("SHA3-224"), true);527}528}529530/**531* Standard SHA3-256withDSA implementation.532*/533public static final class SHA3_256withDSA extends DSA {534public SHA3_256withDSA() throws NoSuchAlgorithmException {535super(MessageDigest.getInstance("SHA3-256"));536}537}538539/**540* Standard SHA3-256withDSA implementation that uses the IEEE P1363 format.541*/542public static final class SHA3_256withDSAinP1363Format extends DSA {543public SHA3_256withDSAinP1363Format() throws NoSuchAlgorithmException {544super(MessageDigest.getInstance("SHA3-256"), true);545}546}547548/**549* Standard SHA3-384withDSA implementation.550*/551public static final class SHA3_384withDSA extends DSA {552public SHA3_384withDSA() throws NoSuchAlgorithmException {553super(MessageDigest.getInstance("SHA3-384"));554}555}556557/**558* Standard SHA3-384withDSA implementation that uses the IEEE P1363 format.559*/560public static final class SHA3_384withDSAinP1363Format extends DSA {561public SHA3_384withDSAinP1363Format() throws NoSuchAlgorithmException {562super(MessageDigest.getInstance("SHA3-384"), true);563}564}565566/**567* Standard SHA3-512withDSA implementation.568*/569public static final class SHA3_512withDSA extends DSA {570public SHA3_512withDSA() throws NoSuchAlgorithmException {571super(MessageDigest.getInstance("SHA3-512"));572}573}574575/**576* Standard SHA3-512withDSA implementation that uses the IEEE P1363 format.577*/578public static final class SHA3_512withDSAinP1363Format extends DSA {579public SHA3_512withDSAinP1363Format() throws NoSuchAlgorithmException {580super(MessageDigest.getInstance("SHA3-512"), true);581}582}583584/**585* Standard SHA224withDSA implementation as defined in FIPS186-3.586*/587public static final class SHA224withDSA extends DSA {588public SHA224withDSA() throws NoSuchAlgorithmException {589super(MessageDigest.getInstance("SHA-224"));590}591}592593/**594* SHA224withDSA implementation that uses the IEEE P1363 format.595*/596public static final class SHA224withDSAinP1363Format extends DSA {597public SHA224withDSAinP1363Format() throws NoSuchAlgorithmException {598super(MessageDigest.getInstance("SHA-224"), true);599}600}601602/**603* Standard SHA256withDSA implementation as defined in FIPS186-3.604*/605public static final class SHA256withDSA extends DSA {606public SHA256withDSA() throws NoSuchAlgorithmException {607super(MessageDigest.getInstance("SHA-256"));608}609}610611/**612* SHA256withDSA implementation that uses the IEEE P1363 format.613*/614public static final class SHA256withDSAinP1363Format extends DSA {615public SHA256withDSAinP1363Format() throws NoSuchAlgorithmException {616super(MessageDigest.getInstance("SHA-256"), true);617}618}619620/**621* Standard SHA384withDSA implementation as defined in FIPS186-3.622*/623public static final class SHA384withDSA extends DSA {624public SHA384withDSA() throws NoSuchAlgorithmException {625super(MessageDigest.getInstance("SHA-384"));626}627}628629/**630* SHA384withDSA implementation that uses the IEEE P1363 format.631*/632public static final class SHA384withDSAinP1363Format extends DSA {633public SHA384withDSAinP1363Format() throws NoSuchAlgorithmException {634super(MessageDigest.getInstance("SHA-384"), true);635}636}637638/**639* Standard SHA512withDSA implementation as defined in FIPS186-3.640*/641public static final class SHA512withDSA extends DSA {642public SHA512withDSA() throws NoSuchAlgorithmException {643super(MessageDigest.getInstance("SHA-512"));644}645}646647/**648* SHA512withDSA implementation that uses the IEEE P1363 format.649*/650public static final class SHA512withDSAinP1363Format extends DSA {651public SHA512withDSAinP1363Format() throws NoSuchAlgorithmException {652super(MessageDigest.getInstance("SHA-512"), true);653}654}655656/**657* Standard SHA1withDSA implementation.658*/659public static final class SHA1withDSA extends DSA {660public SHA1withDSA() throws NoSuchAlgorithmException {661super(MessageDigest.getInstance("SHA-1"));662}663}664665/**666* SHA1withDSA implementation that uses the IEEE P1363 format.667*/668public static final class SHA1withDSAinP1363Format extends DSA {669public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException {670super(MessageDigest.getInstance("SHA-1"), true);671}672}673674/**675* Raw DSA.676*677* Raw DSA requires the data to be exactly 20 bytes long. If it is678* not, a SignatureException is thrown when sign()/verify() is called679* per JCA spec.680*/681static class Raw extends DSA {682// Internal special-purpose MessageDigest impl for RawDSA683// Only override whatever methods used684// NOTE: no clone support685public static final class NullDigest20 extends MessageDigest {686// 20 byte digest buffer687private final byte[] digestBuffer = new byte[20];688689// offset into the buffer; use Integer.MAX_VALUE to indicate690// out-of-bound condition691private int ofs = 0;692693protected NullDigest20() {694super("NullDigest20");695}696protected void engineUpdate(byte input) {697if (ofs == digestBuffer.length) {698ofs = Integer.MAX_VALUE;699} else {700digestBuffer[ofs++] = input;701}702}703protected void engineUpdate(byte[] input, int offset, int len) {704if (len > (digestBuffer.length - ofs)) {705ofs = Integer.MAX_VALUE;706} else {707System.arraycopy(input, offset, digestBuffer, ofs, len);708ofs += len;709}710}711protected final void engineUpdate(ByteBuffer input) {712int inputLen = input.remaining();713if (inputLen > (digestBuffer.length - ofs)) {714ofs = Integer.MAX_VALUE;715} else {716input.get(digestBuffer, ofs, inputLen);717ofs += inputLen;718}719}720protected byte[] engineDigest() throws RuntimeException {721if (ofs != digestBuffer.length) {722throw new RuntimeException723("Data for RawDSA must be exactly 20 bytes long");724}725reset();726return digestBuffer;727}728protected int engineDigest(byte[] buf, int offset, int len)729throws DigestException {730if (ofs != digestBuffer.length) {731throw new DigestException732("Data for RawDSA must be exactly 20 bytes long");733}734if (len < digestBuffer.length) {735throw new DigestException736("Output buffer too small; must be at least 20 bytes");737}738System.arraycopy(digestBuffer, 0, buf, offset, digestBuffer.length);739reset();740return digestBuffer.length;741}742743protected void engineReset() {744ofs = 0;745}746protected final int engineGetDigestLength() {747return digestBuffer.length;748}749}750751private Raw(boolean p1363Format) throws NoSuchAlgorithmException {752super(new NullDigest20(), p1363Format);753}754755}756757/**758* Standard Raw DSA implementation.759*/760public static final class RawDSA extends Raw {761public RawDSA() throws NoSuchAlgorithmException {762super(false);763}764}765766/**767* Raw DSA implementation that uses the IEEE P1363 format.768*/769public static final class RawDSAinP1363Format extends Raw {770public RawDSAinP1363Format() throws NoSuchAlgorithmException {771super(true);772}773}774}775776777