diff src/com/trilead/ssh2/signature/RSASHA1Verify.java @ 0:0ce5cc452d02

initial version
author Carl Byington <carl@five-ten-sg.com>
date Thu, 22 May 2014 10:41:19 -0700
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/trilead/ssh2/signature/RSASHA1Verify.java	Thu May 22 10:41:19 2014 -0700
@@ -0,0 +1,174 @@
+
+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.Signature;
+import java.security.SignatureException;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.RSAPublicKeySpec;
+
+import com.trilead.ssh2.log.Logger;
+import com.trilead.ssh2.packets.TypesReader;
+import com.trilead.ssh2.packets.TypesWriter;
+
+
+/**
+ * RSASHA1Verify.
+ *
+ * @author Christian Plattner, plattner@trilead.com
+ * @version $Id: RSASHA1Verify.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $
+ */
+public class RSASHA1Verify {
+    private static final Logger log = Logger.getLogger(RSASHA1Verify.class);
+
+    public static RSAPublicKey decodeSSHRSAPublicKey(byte[] key) throws IOException {
+        TypesReader tr = new TypesReader(key);
+        String key_format = tr.readString();
+
+        if (key_format.equals("ssh-rsa") == false)
+            throw new IllegalArgumentException("This is not a ssh-rsa public key");
+
+        BigInteger e = tr.readMPINT();
+        BigInteger n = tr.readMPINT();
+
+        if (tr.remain() != 0)
+            throw new IOException("Padding in RSA public key!");
+
+        KeySpec keySpec = new RSAPublicKeySpec(n, e);
+
+        try {
+            KeyFactory kf = KeyFactory.getInstance("RSA");
+            return (RSAPublicKey) kf.generatePublic(keySpec);
+        }
+        catch (NoSuchAlgorithmException nsae) {
+            IOException ioe = new IOException("No RSA KeyFactory available");
+            ioe.initCause(nsae);
+            throw ioe;
+        }
+        catch (InvalidKeySpecException ikse) {
+            IOException ioe = new IOException("No RSA KeyFactory available");
+            ioe.initCause(ikse);
+            throw ioe;
+        }
+    }
+
+    public static byte[] encodeSSHRSAPublicKey(RSAPublicKey pk) throws IOException {
+        TypesWriter tw = new TypesWriter();
+        tw.writeString("ssh-rsa");
+        tw.writeMPInt(pk.getPublicExponent());
+        tw.writeMPInt(pk.getModulus());
+        return tw.getBytes();
+    }
+
+    public static byte[] decodeSSHRSASignature(byte[] sig) throws IOException {
+        TypesReader tr = new TypesReader(sig);
+        String sig_format = tr.readString();
+
+        if (sig_format.equals("ssh-rsa") == false)
+            throw new IOException("Peer sent wrong signature format");
+
+        /* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string
+         * containing s (which is an integer, without lengths or padding, unsigned and in
+         * network byte order)." See also below.
+         */
+        byte[] s = tr.readByteString();
+
+        if (s.length == 0)
+            throw new IOException("Error in RSA signature, S is empty.");
+
+        if (log.isEnabled()) {
+            log.log(80, "Decoding ssh-rsa signature string (length: " + s.length + ")");
+        }
+
+        if (tr.remain() != 0)
+            throw new IOException("Padding in RSA signature!");
+
+        if (s[0] == 0 && s[1] == 0 && s[2] == 0) {
+            int i = 0;
+            int j = ((s[i++] << 24) & 0xff000000) | ((s[i++] << 16) & 0x00ff0000)
+                    | ((s[i++] << 8) & 0x0000ff00) | ((s[i++]) & 0x000000ff);
+            i += j;
+            j = ((s[i++] << 24) & 0xff000000) | ((s[i++] << 16) & 0x00ff0000)
+                | ((s[i++] << 8) & 0x0000ff00) | ((s[i++]) & 0x000000ff);
+            byte[] tmp = new byte[j];
+            System.arraycopy(s, i, tmp, 0, j);
+            sig = tmp;
+        }
+
+        return s;
+    }
+
+    public static byte[] encodeSSHRSASignature(byte[] s) throws IOException {
+        TypesWriter tw = new TypesWriter();
+        tw.writeString("ssh-rsa");
+
+        /* S is NOT an MPINT. "The value for 'rsa_signature_blob' is encoded as a string
+         * containing s (which is an integer, without lengths or padding, unsigned and in
+         * network byte order)."
+         */
+
+        /* Remove first zero sign byte, if present */
+
+        if ((s.length > 1) && (s[0] == 0x00))
+            tw.writeString(s, 1, s.length - 1);
+        else
+            tw.writeString(s, 0, s.length);
+
+        return tw.getBytes();
+    }
+
+    public static byte[] generateSignature(byte[] message, RSAPrivateKey pk) throws IOException {
+        try {
+            Signature s = Signature.getInstance("SHA1withRSA");
+            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;
+        }
+    }
+
+    public static boolean verifySignature(byte[] message, byte[] ds, RSAPublicKey dpk) throws IOException {
+        try {
+            Signature s = Signature.getInstance("SHA1withRSA");
+            s.initVerify(dpk);
+            s.update(message);
+            return s.verify(ds);
+        }
+        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;
+        }
+    }
+}