package ssh.v2; import java.util.Random; import app.Settings; public class PublicKeyAuthentication { public static final BigInteger p = new BigInteger( "d1c9009c7f181e9b27ce020e014d72c499f604c8d978a4dd9a8614362b09a74be4004cdd1b6ccf2bb2d2a4d4710be0817a375c85e8b0ce05e92a1f7c0b4886418dc6de84457dfd8dc19efdc0efb5c15bbab7a860b3e95c169d6e8aceef445deddc85ab44a11d5870847b99239011ff7d36a0f52cd11c3a0a33c415cdd58d85a1", 16), q = new BigInteger("e691d26b30a8b43081b981d96a8189fe78d04f8f", 16), g = new BigInteger( "6ded9dc637ecc98f7ccf5a50839e13354972985cb901ca164fb8174318c84fec50ce84bfef5f4ee4981c239ed7c2bcf0718fcc0f30382df782221f64bfd09c9dc8e098ad10f296eadd9f5650f17414a77d3ff5ca8d103235e2de14a392c9a1156b2a5652d135111858af96d531688d80e962c52c75738f3d48aa09d59ca064a6", 16); public BigInteger x, y; //#ifdef ssh2 public PublicKeyAuthentication() { this.x = new BigInteger(Settings.x); this.y = new BigInteger(Settings.y); } //#endif public byte[] sign(byte[] session_id, byte[] message) { SshPacket2 buf = new SshPacket2(); buf.putString(session_id); buf.putByte((byte) 50); // SSH2_MSG_USERAUTH_REQUEST buf.putBytes(message); message = buf.getData(); SHA1Digest digest = new SHA1Digest(); digest.update(message, 0, message.length); byte[] hash = new byte[digest.getDigestSize()]; digest.doFinal(hash, 0); BigInteger[] rs = generateSignature(hash); buf = new SshPacket2(); buf.putString(DHKeyExchange.SSH_DSS); byte[] r = rs[0].toByteArray(); byte[] s = rs[1].toByteArray(); byte[] sig = new byte[40]; System.arraycopy(r, r.length > 20 ? 1 : 0, sig, r.length > 20 ? 0 : 20 - r.length, r.length > 20 ? 20 : r.length); System.arraycopy(s, s.length > 20 ? 1 : 0, sig, s.length > 20 ? 20 : 40 - s.length, s.length > 20 ? 20 : s.length); buf.putString(sig); return buf.getData(); } /** * generate a signature for the given message using the key we were * initialised with. For conventional DSA the message should be a SHA-1 hash * of the message of interest. * * @param message * the message that will be verified later. */ public BigInteger[] generateSignature(byte[] message) { BigInteger m = new BigInteger(1, message); BigInteger k; int qBitLength = q.bitLength(); do { k = new BigInteger(qBitLength, new Random()); } while (k.compareTo(q) >= 0); BigInteger r = g.modPow(k, p).mod(q); k = k.modInverse(q).multiply(m.add(x.multiply(r))); BigInteger s = k.mod(q); BigInteger[] res = new BigInteger[2]; res[0] = r; res[1] = s; return res; } public String getPublicKeyText() { byte[] pubblob = getPublicKeyBlob(); byte[] pub = toBase64(pubblob, 0, pubblob.length); return DHKeyExchange.SSH_DSS + " " + new String(pub); } public byte[] getPublicKeyBlob() { SshPacket2 buf = new SshPacket2(); buf.putString(DHKeyExchange.SSH_DSS); buf.putMpInt(p.toByteArray()); buf.putMpInt(q.toByteArray()); buf.putMpInt(g.toByteArray()); buf.putMpInt(y.toByteArray()); return buf.getData(); } public static byte[][] generateKeyPair() { BigInteger x, y; do { x = new BigInteger(160, new Random()); } while (x.equals(BigInteger.ZERO) || x.compareTo(q) >= 0); // // calculate the public key. // y = g.modPow(x, p); byte[][] res = new byte[2][]; res[0] = x.toByteArray(); res[1] = y.toByteArray(); return res; } private static final byte[] b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .getBytes(); private static byte[] toBase64(byte[] buf, int start, int length) { byte[] tmp = new byte[length * 2]; int i, j, k; int foo = (length / 3) * 3 + start; i = 0; for (j = start; j < foo; j += 3) { k = (buf[j] >>> 2) & 0x3f; tmp[i++] = b64[k]; k = (buf[j] & 0x03) << 4 | (buf[j + 1] >>> 4) & 0x0f; tmp[i++] = b64[k]; k = (buf[j + 1] & 0x0f) << 2 | (buf[j + 2] >>> 6) & 0x03; tmp[i++] = b64[k]; k = buf[j + 2] & 0x3f; tmp[i++] = b64[k]; } foo = (start + length) - foo; if (foo == 1) { k = (buf[j] >>> 2) & 0x3f; tmp[i++] = b64[k]; k = ((buf[j] & 0x03) << 4) & 0x3f; tmp[i++] = b64[k]; tmp[i++] = (byte) '='; tmp[i++] = (byte) '='; } else if (foo == 2) { k = (buf[j] >>> 2) & 0x3f; tmp[i++] = b64[k]; k = (buf[j] & 0x03) << 4 | (buf[j + 1] >>> 4) & 0x0f; tmp[i++] = b64[k]; k = ((buf[j + 1] & 0x0f) << 2) & 0x3f; tmp[i++] = b64[k]; tmp[i++] = (byte) '='; } byte[] bar = new byte[i]; System.arraycopy(tmp, 0, bar, 0, i); return bar; } }