FileDocCategorySizeDatePackage
SHA1withDSA_SignatureImpl.javaAPI DocAndroid 1.5 API13547Wed May 06 22:41:06 BST 2009org.apache.harmony.security.provider.crypto

SHA1withDSA_SignatureImpl

public class SHA1withDSA_SignatureImpl extends Signature

Fields Summary
private MessageDigest
msgDigest
private DSAKey
dsaKey
Constructors Summary
public SHA1withDSA_SignatureImpl()
The solo constructor.


        super("SHA1withDSA"); //$NON-NLS-1$

        msgDigest = MessageDigest.getInstance("SHA1"); //$NON-NLS-1$
    
Methods Summary
private booleancheckSignature(byte[] sigBytes, int offset, int length)


        // names of below BigIntegers are the same as they are defined in DSA standard
        BigInteger r, s, w;
        BigInteger u1, u2, v;

        // parameters and public key
        BigInteger p, q, g, y;

        DSAParams params;

        int n1, n2;

        byte bytes[];
        byte digest[];

        // checking up on signature's ASN1
        try {
            byte dummy;
            n1 = sigBytes[offset + 3];
            n2 = sigBytes[offset + n1 + 5];

            if (sigBytes[offset + 0] != 0x30 || sigBytes[offset + 2] != 2
                    || sigBytes[offset + n1 + 4] != 2
                    || sigBytes[offset + 1] != (n1 + n2 + 4) || n1 > 21
                    || n2 > 21
                    || (length != 0 && (sigBytes[offset + 1] + 2) > length)) {
                throw new SignatureException(Messages.getString("security.16F")); //$NON-NLS-1$
            }

            dummy = sigBytes[5 + n1 + n2]; // to check length of sigBytes
        } catch (ArrayIndexOutOfBoundsException e) {
            throw new SignatureException(Messages.getString("security.170")); //$NON-NLS-1$
        }

        digest = msgDigest.digest();

        bytes = new byte[n1];
        System.arraycopy(sigBytes, offset + 4, bytes, 0, n1);
        r = new BigInteger(bytes);

        bytes = new byte[n2];
        System.arraycopy(sigBytes, offset + 6 + n1, bytes, 0, n2);
        s = new BigInteger(bytes);

        params = dsaKey.getParams();
        p = params.getP();
        q = params.getQ();
        g = params.getG();
        y = ((DSAPublicKey) dsaKey).getY();

        // forming signature according algorithm described in chapter 6 of DSA standard

        if (r.signum() != 1 || r.compareTo(q) != -1 || s.signum() != 1
                || s.compareTo(q) != -1) {
            return false;
        }

        w = s.modInverse(q);

        u1 = (new BigInteger(1, digest)).multiply(w).mod(q);
        u2 = r.multiply(w).mod(q);

        v = g.modPow(u1, p).multiply(y.modPow(u2, p)).mod(p).mod(q);

        if (v.compareTo(r) != 0) {
            return false;
        }
        return true;
    
protected java.lang.ObjectengineGetParameter(java.lang.String param)
Deprecated method.

return
null

        if (param == null) {
            throw new NullPointerException(Messages.getString("security.01")); //$NON-NLS-1$
        }
        return null;
    
protected voidengineInitSign(java.security.PrivateKey privateKey)
Initializes this signature object with PrivateKey object passed as argument to the method.

params
privateKey DSAPrivateKey object
throws
InvalidKeyException if privateKey is not DSAPrivateKey object


        DSAParams params;

        // parameters and private key
        BigInteger p, q, g, x;

        int n;

        if (privateKey == null || !(privateKey instanceof DSAPrivateKey)) {
            throw new InvalidKeyException(
                    Messages.getString("security.168")); //$NON-NLS-1$
        }

        params = ((DSAPrivateKey) privateKey).getParams();
        p = params.getP();
        q = params.getQ();
        g = params.getG();
        x = ((DSAPrivateKey) privateKey).getX();

        // checks described in DSA standard
        n = p.bitLength();
        if (p.compareTo(BigInteger.valueOf(1)) != 1 || n < 512 || n > 1024
                || (n & 077) != 0) {
            throw new InvalidKeyException(Messages.getString("security.169")); //$NON-NLS-1$
        }
        if (q.signum() != 1 && q.bitLength() != 160) {
            throw new InvalidKeyException(Messages.getString("security.16A")); //$NON-NLS-1$
        }
        if (x.signum() != 1 || x.compareTo(q) != -1) {
            throw new InvalidKeyException(Messages.getString("security.16B")); //$NON-NLS-1$
        }

        dsaKey = (DSAKey) privateKey;

        msgDigest.reset();
    
protected voidengineInitVerify(java.security.PublicKey publicKey)
Initializes this signature object with PublicKey object passed as argument to the method.

params
publicKey DSAPublicKey object
throws
InvalidKeyException if publicKey is not DSAPublicKey object


        // parameters and public key
        BigInteger p, q, g, y;

        int n1;

        if (publicKey == null || !(publicKey instanceof DSAPublicKey)) {
            throw new InvalidKeyException(
                    Messages.getString("security.16C")); //$NON-NLS-1$
        }

        DSAParams params = ((DSAPublicKey) publicKey).getParams();
        p = params.getP();
        q = params.getQ();
        g = params.getG();
        y = ((DSAPublicKey) publicKey).getY();

        // checks described in DSA standard
        n1 = p.bitLength();
        if (p.compareTo(BigInteger.valueOf(1)) != 1 || n1 < 512 || n1 > 1024
                || (n1 & 077) != 0) {
            throw new InvalidKeyException(Messages.getString("security.169")); //$NON-NLS-1$
        }
        if (q.signum() != 1 || q.bitLength() != 160) {
            throw new InvalidKeyException(Messages.getString("security.16A")); //$NON-NLS-1$
        }
        if (y.signum() != 1) {
            throw new InvalidKeyException(Messages.getString("security.16D")); //$NON-NLS-1$
        }

        dsaKey = (DSAKey) publicKey;

        msgDigest.reset();
    
protected voidengineSetParameter(java.lang.String param, java.lang.Object value)

        if (param == null) {
            throw new NullPointerException(Messages.getString("security.83", "param")); //$NON-NLS-1$ //$NON-NLS-2$
        }
        throw new InvalidParameterException(Messages.getString("security.16E")); //$NON-NLS-1$
    
protected byte[]engineSign()
Returns signature bytes as byte array containing ASN1 representation for two BigInteger objects which is SEQUENCE of two INTEGERS. Length of sequence varies from less than 46 to 48. Resets object to the state it was in when previous call to either "initSign" method was called.

return
byte array containing signature in ASN1 representation
throws
SignatureException if object's state is not SIGN or signature algorithm cannot process data


        // names of below BigIntegers are the same as they are defined in DSA standard
        BigInteger r = null;
        BigInteger s = null;
        BigInteger k = null;

        // parameters and private key
        BigInteger p, q, g, x;

        // BigInteger for message digest 
        BigInteger digestBI;

        // various byte array being used in computing signature
        byte randomBytes[];
        byte digest[];
        byte rBytes[], sBytes[], signature[];

        int n, n1, n2;

        DSAParams params;

        if (appRandom == null) {
            appRandom = new SecureRandom();
        }

        params = dsaKey.getParams();
        p = params.getP();
        q = params.getQ();
        g = params.getG();
        x = ((DSAPrivateKey) dsaKey).getX();

        // forming signature according algorithm described in chapter 5 of DSA standard

        digestBI = new BigInteger(1, msgDigest.digest());

        randomBytes = new byte[20];

        for (;;) {

            appRandom.nextBytes(randomBytes);

            k = new BigInteger(1, randomBytes);
            if (k.compareTo(q) != -1) {
                continue;
            }
            r = g.modPow(k, p).mod(q);
            if (r.signum() == 0) {
                continue;
            }

            s = k.modInverse(q).multiply(digestBI.add(x.multiply(r)).mod(q))
                    .mod(q);

            if (s.signum() != 0) {
                break;
            }
        }

        // forming signature's ASN1 representation which is SEQUENCE of two INTEGERs
        // 
        rBytes = r.toByteArray();
        n1 = rBytes.length;
        if ((rBytes[0] & 0x80) != 0) {
            n1++;
        }
        sBytes = s.toByteArray();
        n2 = sBytes.length;
        if ((sBytes[0] & 0x80) != 0) {
            n2++;
        }

        signature = new byte[6 + n1 + n2]; // 48 is max. possible length of signature
        signature[0] = (byte) 0x30; // ASN1 SEQUENCE tag
        signature[1] = (byte) (4 + n1 + n2); // total length of two INTEGERs
        signature[2] = (byte) 0x02; // ASN1 INTEGER tag
        signature[3] = (byte) n1; // length of r
        signature[4 + n1] = (byte) 0x02; // ASN1 INTEGER tag
        signature[5 + n1] = (byte) n2; // length of s

        if (n1 == rBytes.length) {
            n = 4;
        } else {
            n = 5;
        }
        System.arraycopy(rBytes, 0, signature, n, rBytes.length);

        if (n2 == sBytes.length) {
            n = 6 + n1;
        } else {
            n = 7 + n1;
        }
        System.arraycopy(sBytes, 0, signature, n, sBytes.length);

        return signature;
    
protected voidengineUpdate(byte b)
Updates data to sign or to verify.

params
b byte to update
throws
SignatureException if object was not initialized for signing or verifying


        msgDigest.update(b);
    
protected voidengineUpdate(byte[] b, int off, int len)
Updates data to sign or to verify.

params
b byte array containing bytes to update
params
off offset in byte array to start from
params
len number of bytes to use for updating
throws
SignatureException if object was not initialized for signing or verifying


        msgDigest.update(b, off, len);
    
protected booleanengineVerify(byte[] sigBytes)
Verifies the signature bytes.

params
sigBytes byte array with signature bytes to verify.
return
true if signature bytes were verified, false otherwise
throws
SignatureException if object's state is not VERIFY or signature format is not ASN1 representation or signature algorithm cannot process data


        if (sigBytes == null) {
            throw new NullPointerException(Messages.getString("security.83", "sigBytes")); //$NON-NLS-1$ //$NON-NLS-2$
        }

        return checkSignature(sigBytes, 0, 0);
    
protected booleanengineVerify(byte[] sigBytes, int offset, int length)
Verifies the signature bytes.

params
sigBytes byte array with signature bytes to verify.
params
offset index in sigBytes to start from
params
length number of bytes allotted for signature
return
true if signature bytes were verified, false otherwise
throws
SignatureException if object's state is not VERIFY or signature format is not ASN1 representation or signature algorithm cannot process data

        return checkSignature(sigBytes, offset, length);