aboutsummaryrefslogtreecommitdiffstats
path: root/lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java
diff options
context:
space:
mode:
authorKenny Root <kenny@the-b.org>2013-02-03 19:00:31 -0800
committerKenny Root <kenny@the-b.org>2013-02-03 22:59:52 -0800
commit4271e2ed172a016e9455f0e43b628a744907ce63 (patch)
tree0ee025c12c415a91d53d11d3812bbff01c7a4c43 /lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java
parent084ced208717d116b07bac3a3f6116f38e453a30 (diff)
downloadsshlib-4271e2ed172a016e9455f0e43b628a744907ce63.tar.gz
sshlib-4271e2ed172a016e9455f0e43b628a744907ce63.tar.bz2
sshlib-4271e2ed172a016e9455f0e43b628a744907ce63.zip
Remove J2ME compatibility layer for keys
Use JCE instead of the DIY crypto library that is in Trilead. This was apparently for J2ME devices. Well, I'm sorry, J2ME devices, you're dead to me.
Diffstat (limited to 'lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java')
-rw-r--r--lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java235
1 files changed, 140 insertions, 95 deletions
diff --git a/lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java b/lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java
index c838ebd..357d66e 100644
--- a/lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java
+++ b/lib/src/main/java/com/trilead/ssh2/signature/DSASHA1Verify.java
@@ -3,9 +3,19 @@ package com.trilead.ssh2.signature;
import java.io.IOException;
import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
+import java.security.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.DSAParams;
+import java.security.interfaces.DSAPrivateKey;
+import java.security.interfaces.DSAPublicKey;
+import java.security.spec.DSAPublicKeySpec;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
-import com.trilead.ssh2.crypto.digest.SHA1;
import com.trilead.ssh2.log.Logger;
import com.trilead.ssh2.packets.TypesReader;
import com.trilead.ssh2.packets.TypesWriter;
@@ -38,7 +48,20 @@ public class DSASHA1Verify
if (tr.remain() != 0)
throw new IOException("Padding in DSA public key!");
- return new DSAPublicKey(p, q, g, y);
+ try {
+ KeyFactory kf = KeyFactory.getInstance("DSA");
+
+ KeySpec ks = new DSAPublicKeySpec(y, p, q, g);
+ return (DSAPublicKey) kf.generatePublic(ks);
+ } catch (NoSuchAlgorithmException e) {
+ IOException ex = new IOException();
+ ex.initCause(e);
+ throw ex;
+ } catch (InvalidKeySpecException e) {
+ IOException ex = new IOException();
+ ex.initCause(e);
+ throw ex;
+ }
}
public static byte[] encodeSSHDSAPublicKey(DSAPublicKey pk) throws IOException
@@ -46,25 +69,47 @@ public class DSASHA1Verify
TypesWriter tw = new TypesWriter();
tw.writeString("ssh-dss");
- tw.writeMPInt(pk.getP());
- tw.writeMPInt(pk.getQ());
- tw.writeMPInt(pk.getG());
+
+ DSAParams params = pk.getParams();
+ tw.writeMPInt(params.getP());
+ tw.writeMPInt(params.getQ());
+ tw.writeMPInt(params.getG());
tw.writeMPInt(pk.getY());
return tw.getBytes();
}
- public static byte[] encodeSSHDSASignature(DSASignature ds)
+ /**
+ * Convert from Java's signature ASN.1 encoding to the SSH spec.
+ * <p>
+ * Java ASN.1 encoding:
+ * <pre>
+ * SEQUENCE ::= {
+ * r INTEGER,
+ * s INTEGER
+ * }
+ * </pre>
+ */
+ public static byte[] encodeSSHDSASignature(byte[] ds)
{
TypesWriter tw = new TypesWriter();
tw.writeString("ssh-dss");
- byte[] r = ds.getR().toByteArray();
- byte[] s = ds.getS().toByteArray();
+ int len, index;
- byte[] a40 = new byte[40];
+ index = 3;
+ len = ds[index++] & 0xff;
+ byte[] r = new byte[len];
+ System.arraycopy(ds, index, r, 0, r.length);
+ index = index + len + 1;
+ len = ds[index++] & 0xff;
+ byte[] s = new byte[len];
+ System.arraycopy(ds, index, s, 0, s.length);
+
+ byte[] a40 = new byte[40];
+
/* Patch (unsigned) r and s into the target array. */
int r_copylen = (r.length < 20) ? r.length : 20;
@@ -78,22 +123,21 @@ public class DSASHA1Verify
return tw.getBytes();
}
- public static DSASignature decodeSSHDSASignature(byte[] sig) throws IOException
+ public static byte[] decodeSSHDSASignature(byte[] sig) throws IOException
{
byte[] rsArray = null;
if (sig.length == 40)
{
/* OK, another broken SSH server. */
- rsArray = sig;
+ rsArray = sig;
}
else
{
- /* Hopefully a server obeing the standard... */
+ /* Hopefully a server obeying the standard... */
TypesReader tr = new TypesReader(sig);
String sig_format = tr.readString();
-
if (sig_format.equals("ssh-dss") == false)
throw new IOException("Peer sent wrong signature format");
@@ -106,105 +150,106 @@ public class DSASHA1Verify
throw new IOException("Padding in DSA signature!");
}
- /* Remember, s and r are unsigned ints. */
-
- byte[] tmp = new byte[20];
-
- System.arraycopy(rsArray, 0, tmp, 0, 20);
- BigInteger r = new BigInteger(1, tmp);
-
- System.arraycopy(rsArray, 20, tmp, 0, 20);
- BigInteger s = new BigInteger(1, tmp);
-
- if (log.isEnabled())
- {
- log.log(30, "decoded ssh-dss signature: first bytes r(" + ((rsArray[0]) & 0xff) + "), s("
- + ((rsArray[20]) & 0xff) + ")");
+ int i = 0;
+ int j = 0;
+ byte[] tmp;
+
+ if (rsArray[0] == 0 && rsArray[1] == 0 && rsArray[2] == 0) {
+ j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000)
+ | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff);
+ i += j;
+ j = ((rsArray[i++] << 24) & 0xff000000) | ((rsArray[i++] << 16) & 0x00ff0000)
+ | ((rsArray[i++] << 8) & 0x0000ff00) | ((rsArray[i++]) & 0x000000ff);
+ tmp = new byte[j];
+ System.arraycopy(rsArray, i, tmp, 0, j);
+ rsArray = tmp;
}
- return new DSASignature(r, s);
- }
-
- public static boolean verifySignature(byte[] message, DSASignature ds, DSAPublicKey dpk) throws IOException
- {
- /* Inspired by Bouncycastle's DSASigner class */
-
- SHA1 md = new SHA1();
- md.update(message);
- byte[] sha_message = new byte[md.getDigestLength()];
- md.digest(sha_message);
+ /* ASN.1 */
+ int frst = ((rsArray[0] & 0x80) != 0 ? 1 : 0);
+ int scnd = ((rsArray[20] & 0x80) != 0 ? 1 : 0);
- BigInteger m = new BigInteger(1, sha_message);
+ /* Calculate output length */
+ int length = rsArray.length + 6 + frst + scnd;
+ tmp = new byte[length];
- BigInteger r = ds.getR();
- BigInteger s = ds.getS();
+ /* DER-encoding to match Java */
+ tmp[0] = (byte) 0x30;
- BigInteger g = dpk.getG();
- BigInteger p = dpk.getP();
- BigInteger q = dpk.getQ();
- BigInteger y = dpk.getY();
-
- BigInteger zero = BigInteger.ZERO;
+ if (rsArray.length != 40)
+ throw new IOException("Peer sent corrupt signature");
+ /* Calculate length */
+ tmp[1] = (byte) 0x2c;
+ tmp[1] += frst;
+ tmp[1] += scnd;
- if (log.isEnabled())
- {
- log.log(60, "ssh-dss signature: m: " + m.toString(16));
- log.log(60, "ssh-dss signature: r: " + r.toString(16));
- log.log(60, "ssh-dss signature: s: " + s.toString(16));
- log.log(60, "ssh-dss signature: g: " + g.toString(16));
- log.log(60, "ssh-dss signature: p: " + p.toString(16));
- log.log(60, "ssh-dss signature: q: " + q.toString(16));
- log.log(60, "ssh-dss signature: y: " + y.toString(16));
- }
+ /* First item */
+ tmp[2] = (byte) 0x02;
- if (zero.compareTo(r) >= 0 || q.compareTo(r) <= 0)
- {
- log.log(20, "ssh-dss signature: zero.compareTo(r) >= 0 || q.compareTo(r) <= 0");
- return false;
- }
+ /* First item length */
+ tmp[3] = (byte) 0x14;
+ tmp[3] += frst;
- if (zero.compareTo(s) >= 0 || q.compareTo(s) <= 0)
- {
- log.log(20, "ssh-dss signature: zero.compareTo(s) >= 0 || q.compareTo(s) <= 0");
- return false;
- }
+ /* Copy in the data for first item */
+ System.arraycopy(rsArray, 0, tmp, 4 + frst, 20);
- BigInteger w = s.modInverse(q);
+ /* Second item */
+ tmp[4 + tmp[3]] = (byte) 0x02;
- BigInteger u1 = m.multiply(w).mod(q);
- BigInteger u2 = r.multiply(w).mod(q);
+ /* Second item length */
+ tmp[5 + tmp[3]] = (byte) 0x14;
+ tmp[5 + tmp[3]] += scnd;
- u1 = g.modPow(u1, p);
- u2 = y.modPow(u2, p);
+ /* Copy in the data for the second item */
+ System.arraycopy(rsArray, 20, tmp, 6 + tmp[3] + scnd, 20);
- BigInteger v = u1.multiply(u2).mod(p).mod(q);
+ /* Swap buffers */
+ rsArray = tmp;
- return v.equals(r);
+ return rsArray;
}
- public static DSASignature generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd)
+ public static boolean verifySignature(byte[] message, byte[] ds, DSAPublicKey dpk) throws IOException
{
- SHA1 md = new SHA1();
- md.update(message);
- byte[] sha_message = new byte[md.getDigestLength()];
- md.digest(sha_message);
-
- BigInteger m = new BigInteger(1, sha_message);
- BigInteger k;
- int qBitLength = pk.getQ().bitLength();
-
- do
- {
- k = new BigInteger(qBitLength, rnd);
+ try {
+ Signature s = Signature.getInstance("SHA1withDSA");
+ s.initVerify(dpk);
+ s.update(message);
+ return s.verify(ds);
+ } catch (NoSuchAlgorithmException e) {
+ IOException ex = new IOException("No such algorithm");
+ ex.initCause(e);
+ throw ex;
+ } catch (InvalidKeyException e) {
+ IOException ex = new IOException("No such algorithm");
+ ex.initCause(e);
+ throw ex;
+ } catch (SignatureException e) {
+ IOException ex = new IOException();
+ ex.initCause(e);
+ throw ex;
}
- while (k.compareTo(pk.getQ()) >= 0);
-
- BigInteger r = pk.getG().modPow(k, pk.getP()).mod(pk.getQ());
-
- k = k.modInverse(pk.getQ()).multiply(m.add((pk).getX().multiply(r)));
-
- BigInteger s = k.mod(pk.getQ());
+ }
- return new DSASignature(r, s);
+ public static byte[] generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd) throws IOException
+ {
+ try {
+ Signature s = Signature.getInstance("SHA1withDSA");
+ s.initSign(pk);
+ s.update(message);
+ return s.sign();
+ } catch (NoSuchAlgorithmException e) {
+ IOException ex = new IOException();
+ ex.initCause(e);
+ throw ex;
+ } catch (InvalidKeyException e) {
+ IOException ex = new IOException();
+ ex.initCause(e);
+ throw ex;
+ } catch (SignatureException e) {
+ IOException ex = new IOException();
+ ex.initCause(e);
+ throw ex;
+ }
}
}