Mercurial > 510Connectbot
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; + } + } +}