1 2 package ch.ethz.ssh2.signature; 3 4 import java.io.IOException ; 5 import java.math.BigInteger ; 6 import java.security.SecureRandom ; 7 8 import ch.ethz.ssh2.crypto.digest.SHA1; 9 import ch.ethz.ssh2.log.Logger; 10 import ch.ethz.ssh2.packets.TypesReader; 11 import ch.ethz.ssh2.packets.TypesWriter; 12 13 19 public class DSASHA1Verify 20 { 21 private static final Logger log = Logger.getLogger(DSASHA1Verify.class); 22 23 public static DSAPublicKey decodeSSHDSAPublicKey(byte[] key) throws IOException 24 { 25 TypesReader tr = new TypesReader(key); 26 27 String key_format = tr.readString(); 28 29 if (key_format.equals("ssh-dss") == false) 30 throw new IllegalArgumentException ("This is not a ssh-dss public key!"); 31 32 BigInteger p = tr.readMPINT(); 33 BigInteger q = tr.readMPINT(); 34 BigInteger g = tr.readMPINT(); 35 BigInteger y = tr.readMPINT(); 36 37 if (tr.remain() != 0) 38 throw new IOException ("Padding in DSA public key!"); 39 40 return new DSAPublicKey(p, q, g, y); 41 } 42 43 public static byte[] encodeSSHDSAPublicKey(DSAPublicKey pk) throws IOException 44 { 45 TypesWriter tw = new TypesWriter(); 46 47 tw.writeString("ssh-dss"); 48 tw.writeMPInt(pk.getP()); 49 tw.writeMPInt(pk.getQ()); 50 tw.writeMPInt(pk.getG()); 51 tw.writeMPInt(pk.getY()); 52 53 return tw.getBytes(); 54 } 55 56 public static byte[] encodeSSHDSASignature(DSASignature ds) 57 { 58 TypesWriter tw = new TypesWriter(); 59 60 tw.writeString("ssh-dss"); 61 62 byte[] r = ds.getR().toByteArray(); 63 byte[] s = ds.getS().toByteArray(); 64 65 byte[] a40 = new byte[40]; 66 67 68 69 int r_copylen = (r.length < 20) ? r.length : 20; 70 int s_copylen = (s.length < 20) ? s.length : 20; 71 72 System.arraycopy(r, r.length - r_copylen, a40, 20 - r_copylen, r_copylen); 73 System.arraycopy(s, s.length - s_copylen, a40, 40 - s_copylen, s_copylen); 74 75 tw.writeString(a40, 0, 40); 76 77 return tw.getBytes(); 78 } 79 80 public static DSASignature decodeSSHDSASignature(byte[] sig) throws IOException 81 { 82 TypesReader tr = new TypesReader(sig); 83 84 String sig_format = tr.readString(); 85 86 if (sig_format.equals("ssh-dss") == false) 87 throw new IOException ("Peer sent wrong signature format"); 88 89 byte[] rsArray = tr.readByteString(); 90 91 if (rsArray.length != 40) 92 throw new IOException ("Peer sent corrupt signature"); 93 94 if (tr.remain() != 0) 95 throw new IOException ("Padding in DSA signature!"); 96 97 98 99 byte[] tmp = new byte[20]; 100 101 System.arraycopy(rsArray, 0, tmp, 0, 20); 102 BigInteger r = new BigInteger (1, tmp); 103 104 System.arraycopy(rsArray, 20, tmp, 0, 20); 105 BigInteger s = new BigInteger (1, tmp); 106 107 if (log.isEnabled()) 108 { 109 log.log(30, "decoded ssh-dss signature: first bytes r(" + ((rsArray[0]) & 0xff) + "), s(" 110 + ((rsArray[20]) & 0xff) + ")"); 111 } 112 113 return new DSASignature(r, s); 114 } 115 116 public static boolean verifySignature(byte[] message, DSASignature ds, DSAPublicKey dpk) throws IOException 117 { 118 119 120 SHA1 md = new SHA1(); 121 md.update(message); 122 byte[] sha_message = new byte[md.getDigestLength()]; 123 md.digest(sha_message); 124 125 BigInteger m = new BigInteger (1, sha_message); 126 127 BigInteger r = ds.getR(); 128 BigInteger s = ds.getS(); 129 130 BigInteger g = dpk.getG(); 131 BigInteger p = dpk.getP(); 132 BigInteger q = dpk.getQ(); 133 BigInteger y = dpk.getY(); 134 135 BigInteger zero = BigInteger.ZERO; 136 137 if (log.isEnabled()) 138 { 139 log.log(60, "ssh-dss signature: m: " + m.toString(16)); 140 log.log(60, "ssh-dss signature: r: " + r.toString(16)); 141 log.log(60, "ssh-dss signature: s: " + s.toString(16)); 142 log.log(60, "ssh-dss signature: g: " + g.toString(16)); 143 log.log(60, "ssh-dss signature: p: " + p.toString(16)); 144 log.log(60, "ssh-dss signature: q: " + q.toString(16)); 145 log.log(60, "ssh-dss signature: y: " + y.toString(16)); 146 } 147 148 if (zero.compareTo(r) >= 0 || q.compareTo(r) <= 0) 149 { 150 log.log(20, "ssh-dss signature: zero.compareTo(r) >= 0 || q.compareTo(r) <= 0"); 151 return false; 152 } 153 154 if (zero.compareTo(s) >= 0 || q.compareTo(s) <= 0) 155 { 156 log.log(20, "ssh-dss signature: zero.compareTo(s) >= 0 || q.compareTo(s) <= 0"); 157 return false; 158 } 159 160 BigInteger w = s.modInverse(q); 161 162 BigInteger u1 = m.multiply(w).mod(q); 163 BigInteger u2 = r.multiply(w).mod(q); 164 165 u1 = g.modPow(u1, p); 166 u2 = y.modPow(u2, p); 167 168 BigInteger v = u1.multiply(u2).mod(p).mod(q); 169 170 return v.equals(r); 171 } 172 173 public static DSASignature generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd) 174 { 175 SHA1 md = new SHA1(); 176 md.update(message); 177 byte[] sha_message = new byte[md.getDigestLength()]; 178 md.digest(sha_message); 179 180 BigInteger m = new BigInteger (1, sha_message); 181 BigInteger k; 182 int qBitLength = pk.getQ().bitLength(); 183 184 do 185 { 186 k = new BigInteger (qBitLength, rnd); 187 } 188 while (k.compareTo(pk.getQ()) >= 0); 189 190 BigInteger r = pk.getG().modPow(k, pk.getP()).mod(pk.getQ()); 191 192 k = k.modInverse(pk.getQ()).multiply(m.add((pk).getX().multiply(r))); 193 194 BigInteger s = k.mod(pk.getQ()); 195 196 return new DSASignature(r, s); 197 } 198 } 199 | Popular Tags |