| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.provider;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
import java.util.*;  | 
 | 
import java.math.BigInteger;  | 
 | 
import java.nio.ByteBuffer;  | 
 | 
 | 
 | 
import java.security.*;  | 
 | 
import java.security.SecureRandom;  | 
 | 
import java.security.interfaces.*;  | 
 | 
import java.security.spec.*;  | 
 | 
 | 
 | 
import sun.security.util.Debug;  | 
 | 
import sun.security.util.DerValue;  | 
 | 
import sun.security.util.DerInputStream;  | 
 | 
import sun.security.util.DerOutputStream;  | 
 | 
import sun.security.jca.JCAUtil;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
abstract class DSA extends SignatureSpi { | 
 | 
 | 
 | 
      | 
 | 
    private static final boolean debug = false;  | 
 | 
 | 
 | 
      | 
 | 
    private static final int BLINDING_BITS = 7;  | 
 | 
 | 
 | 
      | 
 | 
    private static final BigInteger BLINDING_CONSTANT =  | 
 | 
        BigInteger.valueOf(1 << BLINDING_BITS);  | 
 | 
 | 
 | 
      | 
 | 
    private DSAParams params;  | 
 | 
 | 
 | 
      | 
 | 
    private BigInteger presetP, presetQ, presetG;  | 
 | 
 | 
 | 
      | 
 | 
    private BigInteger presetY;  | 
 | 
 | 
 | 
      | 
 | 
    private BigInteger presetX;  | 
 | 
 | 
 | 
      | 
 | 
    private SecureRandom signingRandom;  | 
 | 
 | 
 | 
      | 
 | 
    private final MessageDigest md;  | 
 | 
 | 
 | 
      | 
 | 
    private final boolean p1363Format;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    DSA(MessageDigest md) { | 
 | 
        this(md, false);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    DSA(MessageDigest md, boolean p1363Format) { | 
 | 
        super();  | 
 | 
        this.md = md;  | 
 | 
        this.p1363Format = p1363Format;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static void checkKey(DSAParams params, int digestLen, String mdAlgo)  | 
 | 
        throws InvalidKeyException { | 
 | 
        // FIPS186-3 states in sec4.2 that a hash function which provides  | 
 | 
        // a lower security strength than the (L, N) pair ordinarily should  | 
 | 
          | 
 | 
        int valueN = params.getQ().bitLength();  | 
 | 
        if (valueN > digestLen) { | 
 | 
            throw new InvalidKeyException("The security strength of " + | 
 | 
                mdAlgo + " digest algorithm is not sufficient for this key size");  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void engineInitSign(PrivateKey privateKey)  | 
 | 
            throws InvalidKeyException { | 
 | 
        if (!(privateKey instanceof java.security.interfaces.DSAPrivateKey)) { | 
 | 
            throw new InvalidKeyException("not a DSA private key: " + | 
 | 
                                          privateKey);  | 
 | 
        }  | 
 | 
 | 
 | 
        java.security.interfaces.DSAPrivateKey priv =  | 
 | 
            (java.security.interfaces.DSAPrivateKey)privateKey;  | 
 | 
 | 
 | 
          | 
 | 
        DSAParams params = priv.getParams();  | 
 | 
        if (params == null) { | 
 | 
            throw new InvalidKeyException("DSA private key lacks parameters"); | 
 | 
        }  | 
 | 
 | 
 | 
        // check key size against hash output size for signing  | 
 | 
          | 
 | 
        if (md.getAlgorithm() != "NullDigest20") { | 
 | 
            checkKey(params, md.getDigestLength()*8, md.getAlgorithm());  | 
 | 
        }  | 
 | 
 | 
 | 
        this.params = params;  | 
 | 
        this.presetX = priv.getX();  | 
 | 
        this.presetY = null;  | 
 | 
        this.presetP = params.getP();  | 
 | 
        this.presetQ = params.getQ();  | 
 | 
        this.presetG = params.getG();  | 
 | 
        this.md.reset();  | 
 | 
    }  | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected void engineInitVerify(PublicKey publicKey)  | 
 | 
            throws InvalidKeyException { | 
 | 
        if (!(publicKey instanceof java.security.interfaces.DSAPublicKey)) { | 
 | 
            throw new InvalidKeyException("not a DSA public key: " + | 
 | 
                                          publicKey);  | 
 | 
        }  | 
 | 
        java.security.interfaces.DSAPublicKey pub =  | 
 | 
            (java.security.interfaces.DSAPublicKey)publicKey;  | 
 | 
 | 
 | 
          | 
 | 
        DSAParams params = pub.getParams();  | 
 | 
        if (params == null) { | 
 | 
            throw new InvalidKeyException("DSA public key lacks parameters"); | 
 | 
        }  | 
 | 
        this.params = params;  | 
 | 
        this.presetY = pub.getY();  | 
 | 
        this.presetX = null;  | 
 | 
        this.presetP = params.getP();  | 
 | 
        this.presetQ = params.getQ();  | 
 | 
        this.presetG = params.getG();  | 
 | 
        this.md.reset();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void engineUpdate(byte b) { | 
 | 
        md.update(b);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void engineUpdate(byte[] data, int off, int len) { | 
 | 
        md.update(data, off, len);  | 
 | 
    }  | 
 | 
 | 
 | 
    protected void engineUpdate(ByteBuffer b) { | 
 | 
        md.update(b);  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected byte[] engineSign() throws SignatureException { | 
 | 
        BigInteger k = generateK(presetQ);  | 
 | 
        BigInteger r = generateR(presetP, presetQ, presetG, k);  | 
 | 
        BigInteger s = generateS(presetX, presetQ, r, k);  | 
 | 
 | 
 | 
        if (p1363Format) { | 
 | 
              | 
 | 
            byte[] rBytes = r.toByteArray();  | 
 | 
            byte[] sBytes = s.toByteArray();  | 
 | 
 | 
 | 
            int size = presetQ.bitLength() / 8;  | 
 | 
            byte[] outseq = new byte[size * 2];  | 
 | 
 | 
 | 
            int rLength = rBytes.length;  | 
 | 
            int sLength = sBytes.length;  | 
 | 
            int i;  | 
 | 
            for (i = rLength; i > 0 && rBytes[rLength - i] == 0; i--);  | 
 | 
 | 
 | 
            int j;  | 
 | 
            for (j = sLength;  | 
 | 
                    j > 0 && sBytes[sLength - j] == 0; j--);  | 
 | 
 | 
 | 
            System.arraycopy(rBytes, rLength - i, outseq, size - i, i);  | 
 | 
            System.arraycopy(sBytes, sLength - j, outseq, size * 2 - j, j);  | 
 | 
 | 
 | 
            return outseq;  | 
 | 
        } else { | 
 | 
              | 
 | 
            try { | 
 | 
                DerOutputStream outseq = new DerOutputStream(100);  | 
 | 
                outseq.putInteger(r);  | 
 | 
                outseq.putInteger(s);  | 
 | 
                DerValue result = new DerValue(DerValue.tag_Sequence,  | 
 | 
                        outseq.toByteArray());  | 
 | 
 | 
 | 
                return result.toByteArray();  | 
 | 
 | 
 | 
            } catch (IOException e) { | 
 | 
                throw new SignatureException("error encoding signature"); | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean engineVerify(byte[] signature)  | 
 | 
            throws SignatureException { | 
 | 
        return engineVerify(signature, 0, signature.length);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    protected boolean engineVerify(byte[] signature, int offset, int length)  | 
 | 
            throws SignatureException { | 
 | 
 | 
 | 
        BigInteger r = null;  | 
 | 
        BigInteger s = null;  | 
 | 
 | 
 | 
        if (p1363Format) { | 
 | 
            if ((length & 1) == 1) { | 
 | 
                  | 
 | 
                throw new SignatureException("invalid signature format"); | 
 | 
            }  | 
 | 
            int mid = length/2;  | 
 | 
            r = new BigInteger(Arrays.copyOfRange(signature, 0, mid));  | 
 | 
            s = new BigInteger(Arrays.copyOfRange(signature, mid, length));  | 
 | 
        } else { | 
 | 
              | 
 | 
            try { | 
 | 
                  | 
 | 
                DerInputStream in =  | 
 | 
                    new DerInputStream(signature, offset, length, false);  | 
 | 
                DerValue[] values = in.getSequence(2);  | 
 | 
 | 
 | 
                // check number of components in the read sequence  | 
 | 
                  | 
 | 
                if ((values.length != 2) || (in.available() != 0)) { | 
 | 
                    throw new IOException("Invalid encoding for signature"); | 
 | 
                }  | 
 | 
                r = values[0].getBigInteger();  | 
 | 
                s = values[1].getBigInteger();  | 
 | 
            } catch (IOException e) { | 
 | 
                throw new SignatureException("Invalid encoding for signature", e); | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        // some implementations do not correctly encode values in the ASN.1  | 
 | 
        // 2's complement format. force r and s to be positive in order to  | 
 | 
          | 
 | 
        if (r.signum() < 0) { | 
 | 
            r = new BigInteger(1, r.toByteArray());  | 
 | 
        }  | 
 | 
        if (s.signum() < 0) { | 
 | 
            s = new BigInteger(1, s.toByteArray());  | 
 | 
        }  | 
 | 
 | 
 | 
        if ((r.compareTo(presetQ) == -1) && (s.compareTo(presetQ) == -1)) { | 
 | 
            BigInteger w = generateW(presetP, presetQ, presetG, s);  | 
 | 
            BigInteger v = generateV(presetY, presetP, presetQ, presetG, w, r);  | 
 | 
            return v.equals(r);  | 
 | 
        } else { | 
 | 
            throw new SignatureException("invalid signature: out of range values"); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    @Deprecated  | 
 | 
    protected void engineSetParameter(String key, Object param) { | 
 | 
        throw new InvalidParameterException("No parameter accepted"); | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    protected void engineSetParameter(AlgorithmParameterSpec params)  | 
 | 
            throws InvalidAlgorithmParameterException { | 
 | 
        if (params != null) { | 
 | 
            throw new InvalidAlgorithmParameterException("No parameter accepted"); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    @Deprecated  | 
 | 
    protected Object engineGetParameter(String key) { | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
    @Override  | 
 | 
    protected AlgorithmParameters engineGetParameters() { | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    private BigInteger generateR(BigInteger p, BigInteger q, BigInteger g,  | 
 | 
                         BigInteger k) { | 
 | 
 | 
 | 
          | 
 | 
        SecureRandom random = getSigningRandom();  | 
 | 
          | 
 | 
        BigInteger blindingValue = new BigInteger(BLINDING_BITS, random);  | 
 | 
          | 
 | 
        blindingValue = blindingValue.add(BLINDING_CONSTANT);  | 
 | 
          | 
 | 
        k = k.add(q.multiply(blindingValue));  | 
 | 
 | 
 | 
        BigInteger temp = g.modPow(k, p);  | 
 | 
        return temp.mod(q);  | 
 | 
    }  | 
 | 
 | 
 | 
    private BigInteger generateS(BigInteger x, BigInteger q,  | 
 | 
            BigInteger r, BigInteger k) throws SignatureException { | 
 | 
 | 
 | 
        byte[] s2;  | 
 | 
        try { | 
 | 
            s2 = md.digest();  | 
 | 
        } catch (RuntimeException re) { | 
 | 
              | 
 | 
            throw new SignatureException(re.getMessage());  | 
 | 
        }  | 
 | 
          | 
 | 
        int nBytes = q.bitLength()/8;  | 
 | 
        if (nBytes < s2.length) { | 
 | 
            s2 = Arrays.copyOfRange(s2, 0, nBytes);  | 
 | 
        }  | 
 | 
        BigInteger z = new BigInteger(1, s2);  | 
 | 
        BigInteger k1 = k.modInverse(q);  | 
 | 
 | 
 | 
        return x.multiply(r).add(z).multiply(k1).mod(q);  | 
 | 
    }  | 
 | 
 | 
 | 
    private BigInteger generateW(BigInteger p, BigInteger q,  | 
 | 
                         BigInteger g, BigInteger s) { | 
 | 
        return s.modInverse(q);  | 
 | 
    }  | 
 | 
 | 
 | 
    private BigInteger generateV(BigInteger y, BigInteger p,  | 
 | 
             BigInteger q, BigInteger g, BigInteger w, BigInteger r)  | 
 | 
             throws SignatureException { | 
 | 
 | 
 | 
        byte[] s2;  | 
 | 
        try { | 
 | 
            s2 = md.digest();  | 
 | 
        } catch (RuntimeException re) { | 
 | 
              | 
 | 
            throw new SignatureException(re.getMessage());  | 
 | 
        }  | 
 | 
          | 
 | 
        int nBytes = q.bitLength()/8;  | 
 | 
        if (nBytes < s2.length) { | 
 | 
            s2 = Arrays.copyOfRange(s2, 0, nBytes);  | 
 | 
        }  | 
 | 
        BigInteger z = new BigInteger(1, s2);  | 
 | 
 | 
 | 
        BigInteger u1 = z.multiply(w).mod(q);  | 
 | 
        BigInteger u2 = (r.multiply(w)).mod(q);  | 
 | 
 | 
 | 
        BigInteger t1 = g.modPow(u1,p);  | 
 | 
        BigInteger t2 = y.modPow(u2,p);  | 
 | 
        BigInteger t3 = t1.multiply(t2);  | 
 | 
        BigInteger t5 = t3.mod(p);  | 
 | 
        return t5.mod(q);  | 
 | 
    }  | 
 | 
 | 
 | 
    protected BigInteger generateK(BigInteger q) { | 
 | 
          | 
 | 
        SecureRandom random = getSigningRandom();  | 
 | 
        byte[] kValue = new byte[(q.bitLength() + 7)/8 + 8];  | 
 | 
 | 
 | 
        random.nextBytes(kValue);  | 
 | 
        return new BigInteger(1, kValue).mod(  | 
 | 
                q.subtract(BigInteger.ONE)).add(BigInteger.ONE);  | 
 | 
    }  | 
 | 
 | 
 | 
    // Use the application-specified SecureRandom Object if provided.  | 
 | 
      | 
 | 
    protected SecureRandom getSigningRandom() { | 
 | 
        if (signingRandom == null) { | 
 | 
            if (appRandom != null) { | 
 | 
                signingRandom = appRandom;  | 
 | 
            } else { | 
 | 
                signingRandom = JCAUtil.getSecureRandom();  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return signingRandom;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public String toString() { | 
 | 
        String printable = "DSA Signature";  | 
 | 
        if (presetP != null && presetQ != null && presetG != null) { | 
 | 
            printable += "\n\tp: " + Debug.toHexString(presetP);  | 
 | 
            printable += "\n\tq: " + Debug.toHexString(presetQ);  | 
 | 
            printable += "\n\tg: " + Debug.toHexString(presetG);  | 
 | 
        } else { | 
 | 
            printable += "\n\t P, Q or G not initialized.";  | 
 | 
        }  | 
 | 
        if (presetY != null) { | 
 | 
            printable += "\n\ty: " + Debug.toHexString(presetY);  | 
 | 
        }  | 
 | 
        if (presetY == null && presetX == null) { | 
 | 
            printable += "\n\tUNINIIALIZED";  | 
 | 
        }  | 
 | 
        return printable;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class SHA224withDSA extends DSA { | 
 | 
        public SHA224withDSA() throws NoSuchAlgorithmException { | 
 | 
            super(MessageDigest.getInstance("SHA-224")); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class SHA224withDSAinP1363Format extends DSA { | 
 | 
        public SHA224withDSAinP1363Format() throws NoSuchAlgorithmException { | 
 | 
            super(MessageDigest.getInstance("SHA-224"), true); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class SHA256withDSA extends DSA { | 
 | 
        public SHA256withDSA() throws NoSuchAlgorithmException { | 
 | 
            super(MessageDigest.getInstance("SHA-256")); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class SHA256withDSAinP1363Format extends DSA { | 
 | 
        public SHA256withDSAinP1363Format() throws NoSuchAlgorithmException { | 
 | 
            super(MessageDigest.getInstance("SHA-256"), true); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class SHA1withDSA extends DSA { | 
 | 
        public SHA1withDSA() throws NoSuchAlgorithmException { | 
 | 
            super(MessageDigest.getInstance("SHA-1")); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class SHA1withDSAinP1363Format extends DSA { | 
 | 
        public SHA1withDSAinP1363Format() throws NoSuchAlgorithmException { | 
 | 
            super(MessageDigest.getInstance("SHA-1"), true); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static class Raw extends DSA { | 
 | 
        // Internal special-purpose MessageDigest impl for RawDSA  | 
 | 
        // Only override whatever methods used  | 
 | 
          | 
 | 
        public static final class NullDigest20 extends MessageDigest { | 
 | 
              | 
 | 
            private final byte[] digestBuffer = new byte[20];  | 
 | 
 | 
 | 
            // offset into the buffer; use Integer.MAX_VALUE to indicate  | 
 | 
              | 
 | 
            private int ofs = 0;  | 
 | 
 | 
 | 
            protected NullDigest20() { | 
 | 
                super("NullDigest20"); | 
 | 
            }  | 
 | 
            protected void engineUpdate(byte input) { | 
 | 
                if (ofs == digestBuffer.length) { | 
 | 
                    ofs = Integer.MAX_VALUE;  | 
 | 
                } else { | 
 | 
                    digestBuffer[ofs++] = input;  | 
 | 
                }  | 
 | 
            }  | 
 | 
            protected void engineUpdate(byte[] input, int offset, int len) { | 
 | 
                if (len > (digestBuffer.length - ofs)) { | 
 | 
                    ofs = Integer.MAX_VALUE;  | 
 | 
                } else { | 
 | 
                    System.arraycopy(input, offset, digestBuffer, ofs, len);  | 
 | 
                    ofs += len;  | 
 | 
                }  | 
 | 
            }  | 
 | 
            protected final void engineUpdate(ByteBuffer input) { | 
 | 
                int inputLen = input.remaining();  | 
 | 
                if (inputLen > (digestBuffer.length - ofs)) { | 
 | 
                    ofs = Integer.MAX_VALUE;  | 
 | 
                } else { | 
 | 
                    input.get(digestBuffer, ofs, inputLen);  | 
 | 
                    ofs += inputLen;  | 
 | 
                }  | 
 | 
            }  | 
 | 
            protected byte[] engineDigest() throws RuntimeException { | 
 | 
                if (ofs != digestBuffer.length) { | 
 | 
                    throw new RuntimeException  | 
 | 
                        ("Data for RawDSA must be exactly 20 bytes long"); | 
 | 
                }  | 
 | 
                reset();  | 
 | 
                return digestBuffer;  | 
 | 
            }  | 
 | 
            protected int engineDigest(byte[] buf, int offset, int len)  | 
 | 
                throws DigestException { | 
 | 
                if (ofs != digestBuffer.length) { | 
 | 
                    throw new DigestException  | 
 | 
                        ("Data for RawDSA must be exactly 20 bytes long"); | 
 | 
                }  | 
 | 
                if (len < digestBuffer.length) { | 
 | 
                    throw new DigestException  | 
 | 
                        ("Output buffer too small; must be at least 20 bytes"); | 
 | 
                }  | 
 | 
                System.arraycopy(digestBuffer, 0, buf, offset, digestBuffer.length);  | 
 | 
                reset();  | 
 | 
                return digestBuffer.length;  | 
 | 
            }  | 
 | 
 | 
 | 
            protected void engineReset() { | 
 | 
                ofs = 0;  | 
 | 
            }  | 
 | 
            protected final int engineGetDigestLength() { | 
 | 
                return digestBuffer.length;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private Raw(boolean p1363Format) throws NoSuchAlgorithmException { | 
 | 
            super(new NullDigest20(), p1363Format);  | 
 | 
        }  | 
 | 
 | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class RawDSA extends Raw { | 
 | 
        public RawDSA() throws NoSuchAlgorithmException { | 
 | 
            super(false);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static final class RawDSAinP1363Format extends Raw { | 
 | 
        public RawDSAinP1363Format() throws NoSuchAlgorithmException { | 
 | 
            super(true);  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |