aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/ch/ethz/ssh2/signature
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/ch/ethz/ssh2/signature')
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/DSAPrivateKey.java62
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/DSAPublicKey.java49
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/DSASHA1Verify.java210
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/DSASignature.java35
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/RSAPrivateKey.java47
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/RSAPublicKey.java35
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/RSASHA1Verify.java287
-rw-r--r--src/main/java/ch/ethz/ssh2/signature/RSASignature.java30
8 files changed, 755 insertions, 0 deletions
diff --git a/src/main/java/ch/ethz/ssh2/signature/DSAPrivateKey.java b/src/main/java/ch/ethz/ssh2/signature/DSAPrivateKey.java
new file mode 100644
index 0000000..270961d
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/DSAPrivateKey.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.math.BigInteger;
+
+/**
+ * DSAPrivateKey.
+ *
+ * @author Christian Plattner
+ * @version 2.50, 03/15/10
+ */
+public class DSAPrivateKey
+{
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+ private BigInteger x;
+ private BigInteger y;
+
+ public DSAPrivateKey(BigInteger p, BigInteger q, BigInteger g,
+ BigInteger y, BigInteger x)
+ {
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ this.y = y;
+ this.x = x;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+
+ public BigInteger getX()
+ {
+ return x;
+ }
+
+ public DSAPublicKey getPublicKey()
+ {
+ return new DSAPublicKey(p, q, g, y);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/ch/ethz/ssh2/signature/DSAPublicKey.java b/src/main/java/ch/ethz/ssh2/signature/DSAPublicKey.java
new file mode 100644
index 0000000..ec0a06c
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/DSAPublicKey.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.math.BigInteger;
+
+/**
+ * DSAPublicKey.
+ *
+ * @author Christian Plattner
+ * @version 2.50, 03/15/10
+ */
+public class DSAPublicKey
+{
+ private BigInteger p;
+ private BigInteger q;
+ private BigInteger g;
+ private BigInteger y;
+
+ public DSAPublicKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y)
+ {
+ this.p = p;
+ this.q = q;
+ this.g = g;
+ this.y = y;
+ }
+
+ public BigInteger getP()
+ {
+ return p;
+ }
+
+ public BigInteger getQ()
+ {
+ return q;
+ }
+
+ public BigInteger getG()
+ {
+ return g;
+ }
+
+ public BigInteger getY()
+ {
+ return y;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/ch/ethz/ssh2/signature/DSASHA1Verify.java b/src/main/java/ch/ethz/ssh2/signature/DSASHA1Verify.java
new file mode 100644
index 0000000..81e0257
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/DSASHA1Verify.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.SecureRandom;
+
+import ch.ethz.ssh2.crypto.digest.SHA1;
+import ch.ethz.ssh2.log.Logger;
+import ch.ethz.ssh2.packets.TypesReader;
+import ch.ethz.ssh2.packets.TypesWriter;
+
+/**
+ * DSASHA1Verify.
+ *
+ * @author Christian Plattner
+ * @version $Id: DSASHA1Verify.java 41 2011-06-02 10:36:41Z dkocher@sudo.ch $
+ */
+public class DSASHA1Verify
+{
+ private static final Logger log = Logger.getLogger(DSASHA1Verify.class);
+
+ public static DSAPublicKey decodeSSHDSAPublicKey(byte[] key) throws IOException
+ {
+ TypesReader tr = new TypesReader(key);
+
+ String key_format = tr.readString();
+
+ if (key_format.equals("ssh-dss") == false)
+ throw new IllegalArgumentException("This is not a ssh-dss public key!");
+
+ BigInteger p = tr.readMPINT();
+ BigInteger q = tr.readMPINT();
+ BigInteger g = tr.readMPINT();
+ BigInteger y = tr.readMPINT();
+
+ if (tr.remain() != 0)
+ throw new IOException("Padding in DSA public key!");
+
+ return new DSAPublicKey(p, q, g, y);
+ }
+
+ public static byte[] encodeSSHDSAPublicKey(DSAPublicKey pk) throws IOException
+ {
+ TypesWriter tw = new TypesWriter();
+
+ tw.writeString("ssh-dss");
+ tw.writeMPInt(pk.getP());
+ tw.writeMPInt(pk.getQ());
+ tw.writeMPInt(pk.getG());
+ tw.writeMPInt(pk.getY());
+
+ return tw.getBytes();
+ }
+
+ public static byte[] encodeSSHDSASignature(DSASignature ds)
+ {
+ TypesWriter tw = new TypesWriter();
+
+ tw.writeString("ssh-dss");
+
+ byte[] r = ds.getR().toByteArray();
+ byte[] s = ds.getS().toByteArray();
+
+ byte[] a40 = new byte[40];
+
+ /* Patch (unsigned) r and s into the target array. */
+
+ int r_copylen = (r.length < 20) ? r.length : 20;
+ int s_copylen = (s.length < 20) ? s.length : 20;
+
+ System.arraycopy(r, r.length - r_copylen, a40, 20 - r_copylen, r_copylen);
+ System.arraycopy(s, s.length - s_copylen, a40, 40 - s_copylen, s_copylen);
+
+ tw.writeString(a40, 0, 40);
+
+ return tw.getBytes();
+ }
+
+ public static DSASignature decodeSSHDSASignature(byte[] sig) throws IOException
+ {
+ byte[] rsArray;
+
+ if (sig.length == 40)
+ {
+ rsArray = sig;
+ }
+ else
+ {
+ 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");
+
+ rsArray = tr.readByteString();
+
+ if (rsArray.length != 40)
+ throw new IOException("Peer sent corrupt signature");
+
+ if (tr.remain() != 0)
+ 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.isDebugEnabled())
+ {
+ log.debug("decoded ssh-dss signature: first bytes r(" + ((rsArray[0]) & 0xff) + "), s("
+ + ((rsArray[20]) & 0xff) + ")");
+ }
+
+ 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);
+
+ BigInteger m = new BigInteger(1, sha_message);
+
+ BigInteger r = ds.getR();
+ BigInteger s = ds.getS();
+
+ BigInteger g = dpk.getG();
+ BigInteger p = dpk.getP();
+ BigInteger q = dpk.getQ();
+ BigInteger y = dpk.getY();
+
+ BigInteger zero = BigInteger.ZERO;
+
+ if (log.isDebugEnabled())
+ {
+ log.debug("ssh-dss signature: m: " + m.toString(16));
+ log.debug("ssh-dss signature: r: " + r.toString(16));
+ log.debug("ssh-dss signature: s: " + s.toString(16));
+ log.debug("ssh-dss signature: g: " + g.toString(16));
+ log.debug("ssh-dss signature: p: " + p.toString(16));
+ log.debug("ssh-dss signature: q: " + q.toString(16));
+ log.debug("ssh-dss signature: y: " + y.toString(16));
+ }
+
+ if (zero.compareTo(r) >= 0 || q.compareTo(r) <= 0)
+ {
+ log.warning("ssh-dss signature: zero.compareTo(r) >= 0 || q.compareTo(r) <= 0");
+ return false;
+ }
+
+ if (zero.compareTo(s) >= 0 || q.compareTo(s) <= 0)
+ {
+ log.warning("ssh-dss signature: zero.compareTo(s) >= 0 || q.compareTo(s) <= 0");
+ return false;
+ }
+
+ BigInteger w = s.modInverse(q);
+
+ BigInteger u1 = m.multiply(w).mod(q);
+ BigInteger u2 = r.multiply(w).mod(q);
+
+ u1 = g.modPow(u1, p);
+ u2 = y.modPow(u2, p);
+
+ BigInteger v = u1.multiply(u2).mod(p).mod(q);
+
+ return v.equals(r);
+ }
+
+ public static DSASignature generateSignature(byte[] message, DSAPrivateKey pk, SecureRandom rnd)
+ {
+ 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);
+ }
+ 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);
+ }
+}
diff --git a/src/main/java/ch/ethz/ssh2/signature/DSASignature.java b/src/main/java/ch/ethz/ssh2/signature/DSASignature.java
new file mode 100644
index 0000000..65492f3
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/DSASignature.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.math.BigInteger;
+
+/**
+ * DSASignature.
+ *
+ * @author Christian Plattner
+ * @version 2.50, 03/15/10
+ */
+public class DSASignature
+{
+ private BigInteger r;
+ private BigInteger s;
+
+ public DSASignature(BigInteger r, BigInteger s)
+ {
+ this.r = r;
+ this.s = s;
+ }
+
+ public BigInteger getR()
+ {
+ return r;
+ }
+
+ public BigInteger getS()
+ {
+ return s;
+ }
+}
diff --git a/src/main/java/ch/ethz/ssh2/signature/RSAPrivateKey.java b/src/main/java/ch/ethz/ssh2/signature/RSAPrivateKey.java
new file mode 100644
index 0000000..bbf1bcd
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/RSAPrivateKey.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.math.BigInteger;
+
+/**
+ * RSAPrivateKey.
+ *
+ * @author Christian Plattner
+ * @version 2.50, 03/15/10
+ */
+public class RSAPrivateKey
+{
+ private BigInteger d;
+ private BigInteger e;
+ private BigInteger n;
+
+ public RSAPrivateKey(BigInteger d, BigInteger e, BigInteger n)
+ {
+ this.d = d;
+ this.e = e;
+ this.n = n;
+ }
+
+ public BigInteger getD()
+ {
+ return d;
+ }
+
+ public BigInteger getE()
+ {
+ return e;
+ }
+
+ public BigInteger getN()
+ {
+ return n;
+ }
+
+ public RSAPublicKey getPublicKey()
+ {
+ return new RSAPublicKey(e, n);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/ch/ethz/ssh2/signature/RSAPublicKey.java b/src/main/java/ch/ethz/ssh2/signature/RSAPublicKey.java
new file mode 100644
index 0000000..1058ffc
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/RSAPublicKey.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.math.BigInteger;
+
+/**
+ * RSAPublicKey.
+ *
+ * @author Christian Plattner
+ * @version 2.50, 03/15/10
+ */
+public class RSAPublicKey
+{
+ BigInteger e;
+ BigInteger n;
+
+ public RSAPublicKey(BigInteger e, BigInteger n)
+ {
+ this.e = e;
+ this.n = n;
+ }
+
+ public BigInteger getE()
+ {
+ return e;
+ }
+
+ public BigInteger getN()
+ {
+ return n;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/ch/ethz/ssh2/signature/RSASHA1Verify.java b/src/main/java/ch/ethz/ssh2/signature/RSASHA1Verify.java
new file mode 100644
index 0000000..584cdf2
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/RSASHA1Verify.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.io.IOException;
+import java.math.BigInteger;
+
+import ch.ethz.ssh2.crypto.SimpleDERReader;
+import ch.ethz.ssh2.crypto.digest.SHA1;
+import ch.ethz.ssh2.log.Logger;
+import ch.ethz.ssh2.packets.TypesReader;
+import ch.ethz.ssh2.packets.TypesWriter;
+
+/**
+ * RSASHA1Verify.
+ *
+ * @author Christian Plattner
+ * @version $Id: RSASHA1Verify.java 41 2011-06-02 10:36:41Z dkocher@sudo.ch $
+ */
+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!");
+
+ return new RSAPublicKey(e, n);
+ }
+
+ public static byte[] encodeSSHRSAPublicKey(RSAPublicKey pk) throws IOException
+ {
+ TypesWriter tw = new TypesWriter();
+
+ tw.writeString("ssh-rsa");
+ tw.writeMPInt(pk.getE());
+ tw.writeMPInt(pk.getN());
+
+ return tw.getBytes();
+ }
+
+ public static RSASignature 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.isDebugEnabled())
+ {
+ log.debug("Decoding ssh-rsa signature string (length: " + s.length + ")");
+ }
+
+ if (tr.remain() != 0)
+ throw new IOException("Padding in RSA signature!");
+
+ return new RSASignature(new BigInteger(1, s));
+ }
+
+ public static byte[] encodeSSHRSASignature(RSASignature sig) 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)."
+ */
+
+ byte[] s = sig.getS().toByteArray();
+
+ /* 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 RSASignature generateSignature(byte[] message, RSAPrivateKey pk) throws IOException
+ {
+ SHA1 md = new SHA1();
+ md.update(message);
+ byte[] sha_message = new byte[md.getDigestLength()];
+ md.digest(sha_message);
+
+ byte[] der_header = new byte[] { 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00,
+ 0x04, 0x14 };
+
+ int rsa_block_len = (pk.getN().bitLength() + 7) / 8;
+
+ int num_pad = rsa_block_len - (2 + der_header.length + sha_message.length) - 1;
+
+ if (num_pad < 8)
+ throw new IOException("Cannot sign with RSA, message too long");
+
+ byte[] sig = new byte[der_header.length + sha_message.length + 2 + num_pad];
+
+ sig[0] = 0x01;
+
+ for (int i = 0; i < num_pad; i++)
+ {
+ sig[i + 1] = (byte) 0xff;
+ }
+
+ sig[num_pad + 1] = 0x00;
+
+ System.arraycopy(der_header, 0, sig, 2 + num_pad, der_header.length);
+ System.arraycopy(sha_message, 0, sig, 2 + num_pad + der_header.length, sha_message.length);
+
+ BigInteger m = new BigInteger(1, sig);
+
+ BigInteger s = m.modPow(pk.getD(), pk.getN());
+
+ return new RSASignature(s);
+ }
+
+ public static boolean verifySignature(byte[] message, RSASignature ds, RSAPublicKey dpk) throws IOException
+ {
+ SHA1 md = new SHA1();
+ md.update(message);
+ byte[] sha_message = new byte[md.getDigestLength()];
+ md.digest(sha_message);
+
+ BigInteger n = dpk.getN();
+ BigInteger e = dpk.getE();
+ BigInteger s = ds.getS();
+
+ if (n.compareTo(s) <= 0)
+ {
+ log.warning("ssh-rsa signature: n.compareTo(s) <= 0");
+ return false;
+ }
+
+ int rsa_block_len = (n.bitLength() + 7) / 8;
+
+ /* And now the show begins */
+
+ if (rsa_block_len < 1)
+ {
+ log.warning("ssh-rsa signature: rsa_block_len < 1");
+ return false;
+ }
+
+ byte[] v = s.modPow(e, n).toByteArray();
+
+ int startpos = 0;
+
+ if ((v.length > 0) && (v[0] == 0x00))
+ startpos++;
+
+ if ((v.length - startpos) != (rsa_block_len - 1))
+ {
+ log.warning("ssh-rsa signature: (v.length - startpos) != (rsa_block_len - 1)");
+ return false;
+ }
+
+ if (v[startpos] != 0x01)
+ {
+ log.warning("ssh-rsa signature: v[startpos] != 0x01");
+ return false;
+ }
+
+ int pos = startpos + 1;
+
+ while (true)
+ {
+ if (pos >= v.length)
+ {
+ log.warning("ssh-rsa signature: pos >= v.length");
+ return false;
+ }
+ if (v[pos] == 0x00)
+ break;
+ if (v[pos] != (byte) 0xff)
+ {
+ log.warning("ssh-rsa signature: v[pos] != (byte) 0xff");
+ return false;
+ }
+ pos++;
+ }
+
+ int num_pad = pos - (startpos + 1);
+
+ if (num_pad < 8)
+ {
+ log.warning("ssh-rsa signature: num_pad < 8");
+ return false;
+ }
+
+ pos++;
+
+ if (pos >= v.length)
+ {
+ log.warning("ssh-rsa signature: pos >= v.length");
+ return false;
+ }
+
+ SimpleDERReader dr = new SimpleDERReader(v, pos, v.length - pos);
+
+ byte[] seq = dr.readSequenceAsByteArray();
+
+ if (dr.available() != 0)
+ {
+ log.warning("ssh-rsa signature: dr.available() != 0");
+ return false;
+ }
+
+ dr.resetInput(seq);
+
+ /* Read digestAlgorithm */
+
+ byte digestAlgorithm[] = dr.readSequenceAsByteArray();
+
+ /* Inspired by RFC 3347, however, ignoring the comment regarding old BER based implementations */
+
+ if ((digestAlgorithm.length < 8) || (digestAlgorithm.length > 9))
+ {
+ log.warning("ssh-rsa signature: (digestAlgorithm.length < 8) || (digestAlgorithm.length > 9)");
+ return false;
+ }
+
+ byte[] digestAlgorithm_sha1 = new byte[] { 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00 };
+
+ for (int i = 0; i < digestAlgorithm.length; i++)
+ {
+ if (digestAlgorithm[i] != digestAlgorithm_sha1[i])
+ {
+ log.warning("ssh-rsa signature: digestAlgorithm[i] != digestAlgorithm_sha1[i]");
+ return false;
+ }
+ }
+
+ byte[] digest = dr.readOctetString();
+
+ if (dr.available() != 0)
+ {
+ log.warning("ssh-rsa signature: dr.available() != 0 (II)");
+ return false;
+ }
+
+ if (digest.length != sha_message.length)
+ {
+ log.warning("ssh-rsa signature: digest.length != sha_message.length");
+ return false;
+ }
+
+ for (int i = 0; i < sha_message.length; i++)
+ {
+ if (sha_message[i] != digest[i])
+ {
+ log.warning("ssh-rsa signature: sha_message[i] != digest[i]");
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/src/main/java/ch/ethz/ssh2/signature/RSASignature.java b/src/main/java/ch/ethz/ssh2/signature/RSASignature.java
new file mode 100644
index 0000000..ca101df
--- /dev/null
+++ b/src/main/java/ch/ethz/ssh2/signature/RSASignature.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
+ * Please refer to the LICENSE.txt for licensing details.
+ */
+package ch.ethz.ssh2.signature;
+
+import java.math.BigInteger;
+
+
+/**
+ * RSASignature.
+ *
+ * @author Christian Plattner
+ * @version 2.50, 03/15/10
+ */
+
+public class RSASignature
+{
+ BigInteger s;
+
+ public BigInteger getS()
+ {
+ return s;
+ }
+
+ public RSASignature(BigInteger s)
+ {
+ this.s = s;
+ }
+} \ No newline at end of file