DSASigner.java revision 87490acd76f544251011cf49753d4d0a61f86a66
1946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecapackage org.bouncycastle.jcajce.provider.asymmetric.dsa;
2946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca
3946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport java.io.IOException;
4946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport java.math.BigInteger;
5946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport java.security.InvalidKeyException;
6946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport java.security.PrivateKey;
77a05161278531db97212c704a2f0258adb7d3324Brian Paulimport java.security.PublicKey;
88684ffc141ed024ab1d42fcba31d8517288fac40James Bentonimport java.security.SecureRandom;
9d75129dd13c2aac4053340487b87127420449ee8Brian Paulimport java.security.SignatureException;
10d75129dd13c2aac4053340487b87127420449ee8Brian Paulimport java.security.SignatureSpi;
11d75129dd13c2aac4053340487b87127420449ee8Brian Paulimport java.security.interfaces.DSAKey;
12f17d1513ac1912d8cc090bba9206a08ff991f64fBrian Paulimport java.security.spec.AlgorithmParameterSpec;
13cf88dcf7313b6a0112c36c2f05ce6a7e846d268cBrian Paul
14946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport org.bouncycastle.asn1.ASN1Encoding;
15946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport org.bouncycastle.asn1.ASN1Integer;
16946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport org.bouncycastle.asn1.ASN1Primitive;
172876b684de39dbdf803b3f3d1ac231e76fb4357eBrian Paulimport org.bouncycastle.asn1.ASN1Sequence;
18137afe6a550bef675daa00fb3092a521dabe3a3dBrian Paulimport org.bouncycastle.asn1.DERSequence;
1908dd41fd6899bd6b3289d30dc31f8b2998406889José Fonsecaimport org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
20effd33071e7b10bdd2f0c198fc34210202b574ccBrian Paulimport org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
21cd9d9e2436a0815f6ed3a61d2cdf8fad53278506Brian Paulimport org.bouncycastle.asn1.x509.X509ObjectIdentifiers;
221073e39ab92a795f7b3958dd789ab324c82c00aeBrian Paulimport org.bouncycastle.crypto.CipherParameters;
23bfa1a766d6df39963daf54fbc63a84d9c139ec7eBrian Paulimport org.bouncycastle.crypto.DSA;
24d5c5a5aea034a8a647d686bdcb88f78445469f82Chia-I Wuimport org.bouncycastle.crypto.Digest;
25bfa1a766d6df39963daf54fbc63a84d9c139ec7eBrian Paulimport org.bouncycastle.crypto.digests.NullDigest;
261073e39ab92a795f7b3958dd789ab324c82c00aeBrian Paul// BEGIN android-added
271073e39ab92a795f7b3958dd789ab324c82c00aeBrian Paulimport org.bouncycastle.crypto.digests.AndroidDigestFactory;
281073e39ab92a795f7b3958dd789ab324c82c00aeBrian Paul// END android-added
29137afe6a550bef675daa00fb3092a521dabe3a3dBrian Paul// BEGIN android-removed
3024a3b0d23a93378d77198f1c92f6f381c0ad05b8Brian Paul// import org.bouncycastle.crypto.digests.SHA1Digest;
3124a3b0d23a93378d77198f1c92f6f381c0ad05b8Brian Paul// import org.bouncycastle.crypto.digests.SHA224Digest;
32bfa1a766d6df39963daf54fbc63a84d9c139ec7eBrian Paul// import org.bouncycastle.crypto.digests.SHA256Digest;
335ce0380a0f585b9e1fb616b749f7fd18a8afada1Keith Whitwell// import org.bouncycastle.crypto.digests.SHA384Digest;
34946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca// import org.bouncycastle.crypto.digests.SHA512Digest;
35946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca// END android-removed
36946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonsecaimport org.bouncycastle.crypto.params.ParametersWithRandom;
37946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca
38543fb77ddece7e1806e8eaa0d65bb2a945ef9a75Keith Whitwellpublic class DSASigner
393a876e847388ad89ea52486040e2b4682a3524c1Jakob Bornecrantz    extends SignatureSpi
40946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca    implements PKCSObjectIdentifiers, X509ObjectIdentifiers
41137afe6a550bef675daa00fb3092a521dabe3a3dBrian Paul{
42b5e381d9783f17c9a527ac38122444eac6807566Zack Rusin    private Digest                  digest;
43946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca    private DSA                     signer;
44946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca    private SecureRandom            random;
453f36f4b0519f7a568d6de9919de1001880ab5c8aJosé Fonseca
46137afe6a550bef675daa00fb3092a521dabe3a3dBrian Paul    protected DSASigner(
477cebd16fbbb68d76b516098f5e6d6a1fc415b8b0José Fonseca        Digest digest,
48137afe6a550bef675daa00fb3092a521dabe3a3dBrian Paul        DSA signer)
491eec90d660052a597db08332141f1ffee1570209Brian Paul    {
50137afe6a550bef675daa00fb3092a521dabe3a3dBrian Paul        this.digest = digest;
51946f432a08112148d743eb9faf6b27bb8cc7fa76José Fonseca        this.signer = signer;
52182ff3e47a2d18917cdf3344c2ce95bd0a460784José Fonseca    }
536c28cc27eb36f201d9c5ed82836f65e38bf9b6a3Brian Paul
54b29fcc7b3a043f879da1869cddd68eded1b3b305José Fonseca    protected void engineInitVerify(
550a1d49504de4d34b003625ee7c901667afa43deaJosé Fonseca        PublicKey   publicKey)
568260e9a8217bf003f490b17cbd9df93bf0cc6675Chris Li        throws InvalidKeyException
575fa09846618ed702493f054a1d4b0ec2a28fbbd0Chris Li    {
583469715a8a171512cf9b528702e70393f01c6041José Fonseca        CipherParameters    param;
598260e9a8217bf003f490b17cbd9df93bf0cc6675Chris Li
60871feeb165685c3f46b3f76a69ddfbd78b4acb8eBrian Paul        if (publicKey instanceof DSAKey)
61871feeb165685c3f46b3f76a69ddfbd78b4acb8eBrian Paul        {
62871feeb165685c3f46b3f76a69ddfbd78b4acb8eBrian Paul            param = DSAUtil.generatePublicKeyParameter(publicKey);
63992e7c72797545e5d7dac11c4714c107be07d41cJakob Bornecrantz        }
64992e7c72797545e5d7dac11c4714c107be07d41cJakob Bornecrantz        else
6580ee3a440cd3c0403004cf35e0638fc52088b9ffQicheng Christopher Li        {
66182ff3e47a2d18917cdf3344c2ce95bd0a460784José Fonseca            try
678e833c7988a218d3c01ff79f17bdeed40058b32eJosé Fonseca            {
683acc8265200295265b476222299a013791050b73Kenneth Graunke                byte[]  bytes = publicKey.getEncoded();
699b534400d9969eceac46b28145405086dda8c113Brian Paul
7081fe19843ac2afdc4fa1e1c87bc979b295af240eDave Airlie                publicKey = new BCDSAPublicKey(SubjectPublicKeyInfo.getInstance(bytes));
71b3f625f5e49d4f713caf401daf32e7f8843bad24Jakob Bornecrantz
721af8b7250f477cfb36cbd8d4885f0cfb9a2e9779Stéphane Marchesin                if (publicKey instanceof DSAKey)
73476b668ccc3f234676dbd3f15207eafe7965222eChris Li                {
7404c136d5c206bd34d5cd6329d9fdc2cc336305a4Brian Paul                    param = DSAUtil.generatePublicKeyParameter(publicKey);
75476b668ccc3f234676dbd3f15207eafe7965222eChris Li                }
76                else
77                {
78                    throw new InvalidKeyException("can't recognise key type in DSA based signer");
79                }
80            }
81            catch (Exception e)
82            {
83                throw new InvalidKeyException("can't recognise key type in DSA based signer");
84            }
85        }
86
87        digest.reset();
88        signer.init(false, param);
89    }
90
91    protected void engineInitSign(
92        PrivateKey      privateKey,
93        SecureRandom    random)
94        throws InvalidKeyException
95    {
96        this.random = random;
97        engineInitSign(privateKey);
98    }
99
100    protected void engineInitSign(
101        PrivateKey  privateKey)
102        throws InvalidKeyException
103    {
104        CipherParameters    param;
105
106        param = DSAUtil.generatePrivateKeyParameter(privateKey);
107
108        if (random != null)
109        {
110            param = new ParametersWithRandom(param, random);
111        }
112
113        digest.reset();
114        signer.init(true, param);
115    }
116
117    protected void engineUpdate(
118        byte    b)
119        throws SignatureException
120    {
121        digest.update(b);
122    }
123
124    protected void engineUpdate(
125        byte[]  b,
126        int     off,
127        int     len)
128        throws SignatureException
129    {
130        digest.update(b, off, len);
131    }
132
133    protected byte[] engineSign()
134        throws SignatureException
135    {
136        byte[]  hash = new byte[digest.getDigestSize()];
137
138        digest.doFinal(hash, 0);
139
140        try
141        {
142            BigInteger[]    sig = signer.generateSignature(hash);
143
144            return derEncode(sig[0], sig[1]);
145        }
146        catch (Exception e)
147        {
148            throw new SignatureException(e.toString());
149        }
150    }
151
152    protected boolean engineVerify(
153        byte[]  sigBytes)
154        throws SignatureException
155    {
156        byte[]  hash = new byte[digest.getDigestSize()];
157
158        digest.doFinal(hash, 0);
159
160        BigInteger[]    sig;
161
162        try
163        {
164            sig = derDecode(sigBytes);
165        }
166        catch (Exception e)
167        {
168            throw new SignatureException("error decoding signature bytes.");
169        }
170
171        return signer.verifySignature(hash, sig[0], sig[1]);
172    }
173
174    protected void engineSetParameter(
175        AlgorithmParameterSpec params)
176    {
177        throw new UnsupportedOperationException("engineSetParameter unsupported");
178    }
179
180    /**
181     * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)">
182     */
183    protected void engineSetParameter(
184        String  param,
185        Object  value)
186    {
187        throw new UnsupportedOperationException("engineSetParameter unsupported");
188    }
189
190    /**
191     * @deprecated
192     */
193    protected Object engineGetParameter(
194        String      param)
195    {
196        throw new UnsupportedOperationException("engineSetParameter unsupported");
197    }
198
199    private byte[] derEncode(
200        BigInteger  r,
201        BigInteger  s)
202        throws IOException
203    {
204        ASN1Integer[] rs = new ASN1Integer[]{ new ASN1Integer(r), new ASN1Integer(s) };
205        return new DERSequence(rs).getEncoded(ASN1Encoding.DER);
206    }
207
208    private BigInteger[] derDecode(
209        byte[]  encoding)
210        throws IOException
211    {
212        ASN1Sequence s = (ASN1Sequence)ASN1Primitive.fromByteArray(encoding);
213        return new BigInteger[]{
214            ((ASN1Integer)s.getObjectAt(0)).getValue(),
215            ((ASN1Integer)s.getObjectAt(1)).getValue()
216        };
217    }
218
219    static public class stdDSA
220        extends DSASigner
221    {
222        public stdDSA()
223        {
224            // BEGIN android-changed
225            super(AndroidDigestFactory.getSHA1(), new org.bouncycastle.crypto.signers.DSASigner());
226            // END android-changed
227        }
228    }
229
230    static public class dsa224
231        extends DSASigner
232    {
233        public dsa224()
234        {
235            // BEGIN android-changed
236            super(AndroidDigestFactory.getSHA224(), new org.bouncycastle.crypto.signers.DSASigner());
237            // END android-changed
238        }
239    }
240
241    static public class dsa256
242        extends DSASigner
243    {
244        public dsa256()
245        {
246            // BEGIN android-changed
247            super(AndroidDigestFactory.getSHA256(), new org.bouncycastle.crypto.signers.DSASigner());
248            // END android-changed
249        }
250    }
251
252    // BEGIN android-removed
253    // static public class dsa384
254    //     extends DSASigner
255    // {
256    //     public dsa384()
257    //     {
258    //         super(new SHA384Digest(), new org.bouncycastle.crypto.signers.DSASigner());
259    //     }
260    // }
261    //
262    // static public class dsa512
263    //     extends DSASigner
264    // {
265    //     public dsa512()
266    //     {
267    //         super(new SHA512Digest(), new org.bouncycastle.crypto.signers.DSASigner());
268    //     }
269    // }
270    // END android-removed
271
272    static public class noneDSA
273        extends DSASigner
274    {
275        public noneDSA()
276        {
277            super(new NullDigest(), new org.bouncycastle.crypto.signers.DSASigner());
278        }
279    }
280}
281