Mercurial > 510Connectbot
comparison src/ch/ethz/ssh2/signature/DSASHA1Verify.java @ 273:91a31873c42a ganymed
start conversion from trilead to ganymed
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Fri, 18 Jul 2014 11:21:46 -0700 |
parents | |
children | d7e088fa2123 |
comparison
equal
deleted
inserted
replaced
272:ce2f4e397703 | 273:91a31873c42a |
---|---|
1 /* | |
2 * Copyright (c) 2006-2011 Christian Plattner. All rights reserved. | |
3 * Please refer to the LICENSE.txt for licensing details. | |
4 */ | |
5 package ch.ethz.ssh2.signature; | |
6 | |
7 import java.io.IOException; | |
8 import java.math.BigInteger; | |
9 import java.security.DigestException; | |
10 import java.security.SecureRandom; | |
11 | |
12 import ch.ethz.ssh2.PacketFormatException; | |
13 import ch.ethz.ssh2.crypto.digest.SHA1; | |
14 import ch.ethz.ssh2.log.Logger; | |
15 import ch.ethz.ssh2.packets.TypesReader; | |
16 import ch.ethz.ssh2.packets.TypesWriter; | |
17 | |
18 /** | |
19 * DSASHA1Verify. | |
20 * | |
21 * @author Christian Plattner | |
22 * @version $Id: DSASHA1Verify.java 154 2014-04-28 11:45:02Z dkocher@sudo.ch $ | |
23 */ | |
24 public class DSASHA1Verify { | |
25 private static final Logger log = Logger.getLogger(DSASHA1Verify.class); | |
26 | |
27 public static DSAPublicKey decodeSSHDSAPublicKey(byte[] key) throws IOException { | |
28 TypesReader tr = new TypesReader(key); | |
29 | |
30 String key_format = tr.readString(); | |
31 | |
32 if(!key_format.equals("ssh-dss")) { | |
33 throw new IllegalArgumentException("Not a ssh-dss public key"); | |
34 } | |
35 | |
36 BigInteger p = tr.readMPINT(); | |
37 BigInteger q = tr.readMPINT(); | |
38 BigInteger g = tr.readMPINT(); | |
39 BigInteger y = tr.readMPINT(); | |
40 | |
41 if(tr.remain() != 0) { | |
42 throw new PacketFormatException("Padding in DSA public key"); | |
43 } | |
44 | |
45 return new DSAPublicKey(p, q, g, y); | |
46 } | |
47 | |
48 public static byte[] encodeSSHDSAPublicKey(DSAPublicKey pk) throws IOException { | |
49 TypesWriter tw = new TypesWriter(); | |
50 | |
51 tw.writeString("ssh-dss"); | |
52 tw.writeMPInt(pk.getP()); | |
53 tw.writeMPInt(pk.getQ()); | |
54 tw.writeMPInt(pk.getG()); | |
55 tw.writeMPInt(pk.getY()); | |
56 | |
57 return tw.getBytes(); | |
58 } | |
59 | |
60 public static byte[] encodeSSHDSASignature(DSASignature ds) { | |
61 TypesWriter tw = new TypesWriter(); | |
62 | |
63 tw.writeString("ssh-dss"); | |
64 | |
65 byte[] r = ds.getR().toByteArray(); | |
66 byte[] s = ds.getS().toByteArray(); | |
67 | |
68 byte[] a40 = new byte[40]; | |
69 | |
70 /* Patch (unsigned) r and s into the target array. */ | |
71 | |
72 int r_copylen = (r.length < 20) ? r.length : 20; | |
73 int s_copylen = (s.length < 20) ? s.length : 20; | |
74 | |
75 System.arraycopy(r, r.length - r_copylen, a40, 20 - r_copylen, r_copylen); | |
76 System.arraycopy(s, s.length - s_copylen, a40, 40 - s_copylen, s_copylen); | |
77 | |
78 tw.writeString(a40, 0, 40); | |
79 | |
80 return tw.getBytes(); | |
81 } | |
82 | |
83 public static DSASignature decodeSSHDSASignature(byte[] sig) throws IOException { | |
84 byte[] rsArray; | |
85 | |
86 if(sig.length == 40) { | |
87 rsArray = sig; | |
88 } | |
89 else { | |
90 TypesReader tr = new TypesReader(sig); | |
91 | |
92 String sig_format = tr.readString(); | |
93 | |
94 if(sig_format.equals("ssh-dss") == false) { | |
95 throw new PacketFormatException("Peer sent wrong signature format"); | |
96 } | |
97 | |
98 rsArray = tr.readByteString(); | |
99 | |
100 if(rsArray.length != 40) { | |
101 throw new PacketFormatException("Peer sent corrupt signature"); | |
102 } | |
103 | |
104 if(tr.remain() != 0) { | |
105 throw new PacketFormatException("Padding in DSA signature!"); | |
106 } | |
107 } | |
108 | |
109 /* Remember, s and r are unsigned ints. */ | |
110 | |
111 byte[] tmp = new byte[20]; | |
112 | |
113 System.arraycopy(rsArray, 0, tmp, 0, 20); | |
114 BigInteger r = new BigInteger(1, tmp); | |
115 | |
116 System.arraycopy(rsArray, 20, tmp, 0, 20); | |
117 BigInteger s = new BigInteger(1, tmp); | |
118 | |
119 if(log.isDebugEnabled()) { | |
120 log.debug("decoded ssh-dss signature: first bytes r(" + ((rsArray[0]) & 0xff) + "), s(" | |
121 + ((rsArray[20]) & 0xff) + ")"); | |
122 } | |
123 | |
124 return new DSASignature(r, s); | |
125 } | |
126 | |
127 public static boolean verifySignature(byte[] message, DSASignature ds, DSAPublicKey dpk) throws IOException { | |
128 /* Inspired by Bouncycastle's DSASigner class */ | |
129 | |
130 SHA1 md = new SHA1(); | |
131 md.update(message); | |
132 byte[] sha_message = new byte[md.getDigestLength()]; | |
133 try { | |
134 md.digest(sha_message); | |
135 } | |
136 catch(DigestException e) { | |
137 throw new IOException(e); | |
138 } | |
139 | |
140 BigInteger m = new BigInteger(1, sha_message); | |
141 | |
142 BigInteger r = ds.getR(); | |
143 BigInteger s = ds.getS(); | |
144 | |
145 BigInteger g = dpk.getG(); | |
146 BigInteger p = dpk.getP(); | |
147 BigInteger q = dpk.getQ(); | |
148 BigInteger y = dpk.getY(); | |
149 | |
150 BigInteger zero = BigInteger.ZERO; | |
151 | |
152 if(log.isDebugEnabled()) { | |
153 log.debug("ssh-dss signature: m: " + m.toString(16)); | |
154 log.debug("ssh-dss signature: r: " + r.toString(16)); | |
155 log.debug("ssh-dss signature: s: " + s.toString(16)); | |
156 log.debug("ssh-dss signature: g: " + g.toString(16)); | |
157 log.debug("ssh-dss signature: p: " + p.toString(16)); | |
158 log.debug("ssh-dss signature: q: " + q.toString(16)); | |
159 log.debug("ssh-dss signature: y: " + y.toString(16)); | |
160 } | |
161 | |
162 if(zero.compareTo(r) >= 0 || q.compareTo(r) <= 0) { | |
163 log.warning("ssh-dss signature: zero.compareTo(r) >= 0 || q.compareTo(r) <= 0"); | |
164 return false; | |
165 } | |
166 | |
167 if(zero.compareTo(s) >= 0 || q.compareTo(s) <= 0) { | |
168 log.warning("ssh-dss signature: zero.compareTo(s) >= 0 || q.compareTo(s) <= 0"); | |
169 return false; | |
170 } | |
171 | |
172 BigInteger w = s.modInverse(q); | |
173 | |
174 BigInteger u1 = m.multiply(w).mod(q); | |
175 BigInteger u2 = r.multiply(w).mod(q); | |
176 | |
177 u1 = g.modPow(u1, p); | |
178 u2 = y.modPow(u2, p); | |
179 | |
180 BigInteger v = u1.multiply(u2).mod(p).mod(q); | |
181 | |
182 return v.equals(r); | |
183 } | |
184 | |
185 public static DSASignature generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd) throws IOException { | |
186 SHA1 md = new SHA1(); | |
187 md.update(message); | |
188 byte[] sha_message = new byte[md.getDigestLength()]; | |
189 try { | |
190 md.digest(sha_message); | |
191 } | |
192 catch(DigestException e) { | |
193 throw new IOException(e); | |
194 } | |
195 | |
196 BigInteger m = new BigInteger(1, sha_message); | |
197 BigInteger k; | |
198 int qBitLength = pk.getQ().bitLength(); | |
199 | |
200 do { | |
201 k = new BigInteger(qBitLength, rnd); | |
202 } | |
203 while(k.compareTo(pk.getQ()) >= 0); | |
204 | |
205 BigInteger r = pk.getG().modPow(k, pk.getP()).mod(pk.getQ()); | |
206 | |
207 k = k.modInverse(pk.getQ()).multiply(m.add((pk).getX().multiply(r))); | |
208 | |
209 BigInteger s = k.mod(pk.getQ()); | |
210 | |
211 return new DSASignature(r, s); | |
212 } | |
213 } |