001: /* -*-mode:java; c-basic-offset:2; indent-tabs-mode:nil -*- */
002: /*
003: Copyright (c) 2002-2008 ymnk, JCraft,Inc. All rights reserved.
004:
005: Redistribution and use in source and binary forms, with or without
006: modification, are permitted provided that the following conditions are met:
007:
008: 1. Redistributions of source code must retain the above copyright notice,
009: this list of conditions and the following disclaimer.
010:
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in
013: the documentation and/or other materials provided with the distribution.
014:
015: 3. The names of the authors may not be used to endorse or promote products
016: derived from this software without specific prior written permission.
017:
018: THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
019: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
020: FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
021: INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
022: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
023: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
024: OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
027: EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: */
029:
030: package com.jcraft.jsch.jce;
031:
032: import java.math.BigInteger;
033: import java.security.*;
034: import java.security.spec.*;
035:
036: public class SignatureDSA implements com.jcraft.jsch.SignatureDSA {
037:
038: java.security.Signature signature;
039: KeyFactory keyFactory;
040:
041: public void init() throws Exception {
042: signature = java.security.Signature.getInstance("SHA1withDSA");
043: keyFactory = KeyFactory.getInstance("DSA");
044: }
045:
046: public void setPubKey(byte[] y, byte[] p, byte[] q, byte[] g)
047: throws Exception {
048: DSAPublicKeySpec dsaPubKeySpec = new DSAPublicKeySpec(
049: new BigInteger(y), new BigInteger(p),
050: new BigInteger(q), new BigInteger(g));
051: PublicKey pubKey = keyFactory.generatePublic(dsaPubKeySpec);
052: signature.initVerify(pubKey);
053: }
054:
055: public void setPrvKey(byte[] x, byte[] p, byte[] q, byte[] g)
056: throws Exception {
057: DSAPrivateKeySpec dsaPrivKeySpec = new DSAPrivateKeySpec(
058: new BigInteger(x), new BigInteger(p),
059: new BigInteger(q), new BigInteger(g));
060: PrivateKey prvKey = keyFactory.generatePrivate(dsaPrivKeySpec);
061: signature.initSign(prvKey);
062: }
063:
064: public byte[] sign() throws Exception {
065: byte[] sig = signature.sign();
066: /*
067: System.err.print("sign["+sig.length+"] ");
068: for(int i=0; i<sig.length;i++){
069: System.err.print(Integer.toHexString(sig[i]&0xff)+":");
070: }
071: System.err.println("");
072: */
073: // sig is in ASN.1
074: // SEQUENCE::={ r INTEGER, s INTEGER }
075: int len = 0;
076: int index = 3;
077: len = sig[index++] & 0xff;
078: //System.err.println("! len="+len);
079: byte[] r = new byte[len];
080: System.arraycopy(sig, index, r, 0, r.length);
081: index = index + len + 1;
082: len = sig[index++] & 0xff;
083: //System.err.println("!! len="+len);
084: byte[] s = new byte[len];
085: System.arraycopy(sig, index, s, 0, s.length);
086:
087: byte[] result = new byte[40];
088:
089: // result must be 40 bytes, but length of r and s may not be 20 bytes
090:
091: System.arraycopy(r, (r.length > 20) ? 1 : 0, result,
092: (r.length > 20) ? 0 : 20 - r.length,
093: (r.length > 20) ? 20 : r.length);
094: System.arraycopy(s, (s.length > 20) ? 1 : 0, result,
095: (s.length > 20) ? 20 : 40 - s.length,
096: (s.length > 20) ? 20 : s.length);
097:
098: // System.arraycopy(sig, (sig[3]==20?4:5), result, 0, 20);
099: // System.arraycopy(sig, sig.length-20, result, 20, 20);
100:
101: return result;
102: }
103:
104: public void update(byte[] foo) throws Exception {
105: signature.update(foo);
106: }
107:
108: public boolean verify(byte[] sig) throws Exception {
109: int i = 0;
110: int j = 0;
111: byte[] tmp;
112:
113: if (sig[0] == 0 && sig[1] == 0 && sig[2] == 0) {
114: j = ((sig[i++] << 24) & 0xff000000)
115: | ((sig[i++] << 16) & 0x00ff0000)
116: | ((sig[i++] << 8) & 0x0000ff00)
117: | ((sig[i++]) & 0x000000ff);
118: i += j;
119: j = ((sig[i++] << 24) & 0xff000000)
120: | ((sig[i++] << 16) & 0x00ff0000)
121: | ((sig[i++] << 8) & 0x0000ff00)
122: | ((sig[i++]) & 0x000000ff);
123: tmp = new byte[j];
124: System.arraycopy(sig, i, tmp, 0, j);
125: sig = tmp;
126: }
127:
128: // ASN.1
129: int frst = ((sig[0] & 0x80) != 0 ? 1 : 0);
130: int scnd = ((sig[20] & 0x80) != 0 ? 1 : 0);
131: //System.err.println("frst: "+frst+", scnd: "+scnd);
132:
133: int length = sig.length + 6 + frst + scnd;
134: tmp = new byte[length];
135: tmp[0] = (byte) 0x30;
136: tmp[1] = (byte) 0x2c;
137: tmp[1] += frst;
138: tmp[1] += scnd;
139: tmp[2] = (byte) 0x02;
140: tmp[3] = (byte) 0x14;
141: tmp[3] += frst;
142: System.arraycopy(sig, 0, tmp, 4 + frst, 20);
143: tmp[4 + tmp[3]] = (byte) 0x02;
144: tmp[5 + tmp[3]] = (byte) 0x14;
145: tmp[5 + tmp[3]] += scnd;
146: System.arraycopy(sig, 20, tmp, 6 + tmp[3] + scnd, 20);
147: sig = tmp;
148:
149: /*
150: tmp=new byte[sig.length+6];
151: tmp[0]=(byte)0x30; tmp[1]=(byte)0x2c;
152: tmp[2]=(byte)0x02; tmp[3]=(byte)0x14;
153: System.arraycopy(sig, 0, tmp, 4, 20);
154: tmp[24]=(byte)0x02; tmp[25]=(byte)0x14;
155: System.arraycopy(sig, 20, tmp, 26, 20); sig=tmp;
156: */
157: return signature.verify(sig);
158: }
159: }
|