Mercurial > 510Connectbot
comparison src/com/trilead/ssh2/signature/DSASHA1Verify.java @ 0:0ce5cc452d02
initial version
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Thu, 22 May 2014 10:41:19 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:0ce5cc452d02 |
---|---|
1 | |
2 package com.trilead.ssh2.signature; | |
3 | |
4 import java.io.IOException; | |
5 import java.math.BigInteger; | |
6 import java.security.InvalidKeyException; | |
7 import java.security.KeyFactory; | |
8 import java.security.NoSuchAlgorithmException; | |
9 import java.security.SecureRandom; | |
10 import java.security.Signature; | |
11 import java.security.SignatureException; | |
12 import java.security.interfaces.DSAParams; | |
13 import java.security.interfaces.DSAPrivateKey; | |
14 import java.security.interfaces.DSAPublicKey; | |
15 import java.security.spec.DSAPublicKeySpec; | |
16 import java.security.spec.InvalidKeySpecException; | |
17 import java.security.spec.KeySpec; | |
18 | |
19 import com.trilead.ssh2.log.Logger; | |
20 import com.trilead.ssh2.packets.TypesReader; | |
21 import com.trilead.ssh2.packets.TypesWriter; | |
22 | |
23 | |
24 /** | |
25 * DSASHA1Verify. | |
26 * | |
27 * @author Christian Plattner, plattner@trilead.com | |
28 * @version $Id: DSASHA1Verify.java,v 1.2 2008/04/01 12:38:09 cplattne Exp $ | |
29 */ | |
30 public class DSASHA1Verify { | |
31 private static final Logger log = Logger.getLogger(DSASHA1Verify.class); | |
32 | |
33 public static DSAPublicKey decodeSSHDSAPublicKey(byte[] key) throws IOException { | |
34 TypesReader tr = new TypesReader(key); | |
35 String key_format = tr.readString(); | |
36 | |
37 if (key_format.equals("ssh-dss") == false) | |
38 throw new IllegalArgumentException("This is not a ssh-dss public key!"); | |
39 | |
40 BigInteger p = tr.readMPINT(); | |
41 BigInteger q = tr.readMPINT(); | |
42 BigInteger g = tr.readMPINT(); | |
43 BigInteger y = tr.readMPINT(); | |
44 | |
45 if (tr.remain() != 0) | |
46 throw new IOException("Padding in DSA public key!"); | |
47 | |
48 try { | |
49 KeyFactory kf = KeyFactory.getInstance("DSA"); | |
50 KeySpec ks = new DSAPublicKeySpec(y, p, q, g); | |
51 return (DSAPublicKey) kf.generatePublic(ks); | |
52 } | |
53 catch (NoSuchAlgorithmException e) { | |
54 IOException ex = new IOException(); | |
55 ex.initCause(e); | |
56 throw ex; | |
57 } | |
58 catch (InvalidKeySpecException e) { | |
59 IOException ex = new IOException(); | |
60 ex.initCause(e); | |
61 throw ex; | |
62 } | |
63 } | |
64 | |
65 public static byte[] encodeSSHDSAPublicKey(DSAPublicKey pk) throws IOException { | |
66 TypesWriter tw = new TypesWriter(); | |
67 tw.writeString("ssh-dss"); | |
68 DSAParams params = pk.getParams(); | |
69 tw.writeMPInt(params.getP()); | |
70 tw.writeMPInt(params.getQ()); | |
71 tw.writeMPInt(params.getG()); | |
72 tw.writeMPInt(pk.getY()); | |
73 return tw.getBytes(); | |
74 } | |
75 | |
76 /** | |
77 * Convert from Java's signature ASN.1 encoding to the SSH spec. | |
78 * <p> | |
79 * Java ASN.1 encoding: | |
80 * <pre> | |
81 * SEQUENCE ::= { | |
82 * r INTEGER, | |
83 * s INTEGER | |
84 * } | |
85 * </pre> | |
86 */ | |
87 public static byte[] encodeSSHDSASignature(byte[] ds) { | |
88 TypesWriter tw = new TypesWriter(); | |
89 tw.writeString("ssh-dss"); | |
90 int len, index; | |
91 index = 3; | |
92 len = ds[index++] & 0xff; | |
93 byte[] r = new byte[len]; | |
94 System.arraycopy(ds, index, r, 0, r.length); | |
95 index = index + len + 1; | |
96 len = ds[index++] & 0xff; | |
97 byte[] s = new byte[len]; | |
98 System.arraycopy(ds, index, s, 0, s.length); | |
99 byte[] a40 = new byte[40]; | |
100 /* Patch (unsigned) r and s into the target array. */ | |
101 int r_copylen = (r.length < 20) ? r.length : 20; | |
102 int s_copylen = (s.length < 20) ? s.length : 20; | |
103 System.arraycopy(r, r.length - r_copylen, a40, 20 - r_copylen, r_copylen); | |
104 System.arraycopy(s, s.length - s_copylen, a40, 40 - s_copylen, s_copylen); | |
105 tw.writeString(a40, 0, 40); | |
106 return tw.getBytes(); | |
107 } | |
108 | |
109 public static byte[] decodeSSHDSASignature(byte[] sig) throws IOException { | |
110 byte[] rsArray = null; | |
111 | |
112 if (sig.length == 40) { | |
113 /* OK, another broken SSH server. */ | |
114 rsArray = sig; | |
115 } | |
116 else { | |
117 /* Hopefully a server obeying the standard... */ | |
118 TypesReader tr = new TypesReader(sig); | |
119 String sig_format = tr.readString(); | |
120 | |
121 if (sig_format.equals("ssh-dss") == false) | |
122 throw new IOException("Peer sent wrong signature format"); | |
123 | |
124 rsArray = tr.readByteString(); | |
125 | |
126 if (rsArray.length != 40) | |
127 throw new IOException("Peer sent corrupt signature"); | |
128 | |
129 if (tr.remain() != 0) | |
130 throw new IOException("Padding in DSA signature!"); | |
131 } | |
132 | |
133 int i = 0; | |
134 int j = 0; | |
135 byte[] tmp; | |
136 | |
137 if (rsArray[0] == 0 && rsArray[1] == 0 && rsArray[2] == 0) { | |
138 j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000) | |
139 | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff); | |
140 i += j; | |
141 j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000) | |
142 | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff); | |
143 tmp = new byte[j]; | |
144 System.arraycopy(rsArray, i, tmp, 0, j); | |
145 rsArray = tmp; | |
146 } | |
147 | |
148 /* ASN.1 */ | |
149 int frst = ((rsArray[0] & 0x80) != 0 ? 1 : 0); | |
150 int scnd = ((rsArray[20] & 0x80) != 0 ? 1 : 0); | |
151 /* Calculate output length */ | |
152 int length = rsArray.length + 6 + frst + scnd; | |
153 tmp = new byte[length]; | |
154 /* DER-encoding to match Java */ | |
155 tmp[0] = (byte) 0x30; | |
156 | |
157 if (rsArray.length != 40) | |
158 throw new IOException("Peer sent corrupt signature"); | |
159 | |
160 /* Calculate length */ | |
161 tmp[1] = (byte) 0x2c; | |
162 tmp[1] += frst; | |
163 tmp[1] += scnd; | |
164 /* First item */ | |
165 tmp[2] = (byte) 0x02; | |
166 /* First item length */ | |
167 tmp[3] = (byte) 0x14; | |
168 tmp[3] += frst; | |
169 /* Copy in the data for first item */ | |
170 System.arraycopy(rsArray, 0, tmp, 4 + frst, 20); | |
171 /* Second item */ | |
172 tmp[4 + tmp[3]] = (byte) 0x02; | |
173 /* Second item length */ | |
174 tmp[5 + tmp[3]] = (byte) 0x14; | |
175 tmp[5 + tmp[3]] += scnd; | |
176 /* Copy in the data for the second item */ | |
177 System.arraycopy(rsArray, 20, tmp, 6 + tmp[3] + scnd, 20); | |
178 /* Swap buffers */ | |
179 rsArray = tmp; | |
180 return rsArray; | |
181 } | |
182 | |
183 public static boolean verifySignature(byte[] message, byte[] ds, DSAPublicKey dpk) throws IOException { | |
184 try { | |
185 Signature s = Signature.getInstance("SHA1withDSA"); | |
186 s.initVerify(dpk); | |
187 s.update(message); | |
188 return s.verify(ds); | |
189 } | |
190 catch (NoSuchAlgorithmException e) { | |
191 IOException ex = new IOException("No such algorithm"); | |
192 ex.initCause(e); | |
193 throw ex; | |
194 } | |
195 catch (InvalidKeyException e) { | |
196 IOException ex = new IOException("No such algorithm"); | |
197 ex.initCause(e); | |
198 throw ex; | |
199 } | |
200 catch (SignatureException e) { | |
201 IOException ex = new IOException(); | |
202 ex.initCause(e); | |
203 throw ex; | |
204 } | |
205 } | |
206 | |
207 public static byte[] generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd) throws IOException { | |
208 try { | |
209 Signature s = Signature.getInstance("SHA1withDSA"); | |
210 s.initSign(pk); | |
211 s.update(message); | |
212 return s.sign(); | |
213 } | |
214 catch (NoSuchAlgorithmException e) { | |
215 IOException ex = new IOException(); | |
216 ex.initCause(e); | |
217 throw ex; | |
218 } | |
219 catch (InvalidKeyException e) { | |
220 IOException ex = new IOException(); | |
221 ex.initCause(e); | |
222 throw ex; | |
223 } | |
224 catch (SignatureException e) { | |
225 IOException ex = new IOException(); | |
226 ex.initCause(e); | |
227 throw ex; | |
228 } | |
229 } | |
230 } |