Skip to content

Commit ef7fbc4

Browse files
committed
Add stronger algorithms for message authentication and key exchange.
SHA-2 from JCE was used to add support for - message authentication - hmac-sha2-256 - hmac-sha2-512 - key exchange as described in https://tools.ietf.org/html/rfc3526 - diffie-hellman-group14-sha256 - diffie-hellman-group16-sha512 - diffie-hellman-group18-sha512
1 parent 53131fd commit ef7fbc4

File tree

14 files changed

+302
-40
lines changed

14 files changed

+302
-40
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.gradle
2+
build

HISTORY.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
Release Notes:
33
==============
44

5+
build263 2020-07-20
6+
7+
- Add gradle build.
8+
9+
- Add OSGi support.
10+
11+
- Message authentication: add support for hmac-sha2-256 and hmac-sha2-512.
12+
13+
- Key exchange: add support for diffie-hellman-group14-sha256, diffie-hellman-group16-sha512 and diffie-hellman-group18-sha512.
14+
515
build261, 2013-08-09
616

717
- Joint work by Christian Plattner and David Kocher.

README.txt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
This repository is forked from one of the automatic exports of code.google.com/p/ganymed-ssh-2 and contains updates on top of the ganymed-ssh2-262 tag. The ganymed-ssh2-262 tag was used to produce the latest public build in Maven Central, which is version 262, so builds from this repository should be version 263. The latest public build in Maven Central is available at https://search.maven.org/artifact/ch.ethz.ganymed/ganymed-ssh2/262/jar
2+
The following features were added in version 263:
3+
- Gradle build support.
4+
- OSGi support.
5+
- Message authentication: support for hmac-sha2-256 and hmac-sha2-512.
6+
- Key exchange: support for diffie-hellman-group14-sha256, diffie-hellman-group16-sha512, and diffie-hellman-group18-sha512.
7+
8+
The code from this repository is used in Software AG Command Central and tested using the Command Central continuous integration. However, this code is not officially supported by Software AG.
9+
10+
11+
**********************************
12+
13+
This software is provided as-is and without warranty or support. It does not constitute part of the Software AG product suite. Users are free to use, fork and modify it, subject to the license agreement. While Software AG welcomes contributions, we cannot guarantee to include every contribution in the master project.
14+
15+
**********************************
16+
17+
18+
19+
20+
Original content:
21+
22+
23+
124

225
Ganymed SSH-2 for Java - build 261
326
==================================

build.gradle

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
plugins {
2+
id 'java-library'
3+
}
4+
5+
repositories {
6+
jcenter()
7+
}
8+
9+
dependencies {
10+
testImplementation 'junit:junit:4.11'
11+
}
12+
13+
group = 'ch.ethz.ganymed'
14+
version = '263'
15+
description = 'ganymed-ssh2'
16+
sourceCompatibility = '1.6'
17+
18+
sourceSets.main.resources.srcDir project.rootDir
19+
sourceSets.main.resources.includes = [ 'FAQ.html', 'HISTORY.txt', 'LICENSE.txt', 'overview.html', 'README.txt' ]
20+
21+
java {
22+
withSourcesJar()
23+
withJavadocJar()
24+
}
25+
26+
javadoc.failOnError = false
27+
28+
jar {
29+
manifest {
30+
attributes(
31+
'Bundle-Description': 'Ganymed SSH2 Client Library',
32+
'Bundle-SymbolicName': 'ch.ethz.ssh2.ganymed-ssh2',
33+
'Bundle-ManifestVersion': '2',
34+
'Bundle-ActivationPolicy': 'lazy',
35+
'Bundle-RequiredExecutionEnvironment': 'JavaSE-1.6',
36+
'Export-Package': 'ch.ethz.ssh2;version=1.0.0,ch.ethz.ssh2.auth;version=1.0.0,ch.ethz.ssh2.channel;version=1.0.0,ch.ethz.ssh2.crypto;version=1.0.0,ch.ethz.ssh2.crypto.cipher;version=1.0.0,ch.ethz.ssh2.crypto.dh;version=1.0.0,ch.ethz.ssh2.crypto.digest;version=1.0.0,ch.ethz.ssh2.log;version=1.0.0,ch.ethz.ssh2.packets;version=1.0.0,ch.ethz.ssh2.server;version=1.0.0,ch.ethz.ssh2.sftp;version=1.0.0,ch.ethz.ssh2.signature;version=1.0.0,ch.ethz.ssh2.transport;version=1.0.0,ch.ethz.ssh2.util;version=1.0.0',
37+
'Bundle-Version': '1.0.263',
38+
'Bundle-Name': 'Ganymed SSH2'
39+
)
40+
}
41+
}

settings.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
rootProject.name = 'ganymed-ssh2'

src/main/java/ch/ethz/ssh2/Connection.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,6 +1215,26 @@ public synchronized void setServerHostKeyAlgorithms(String[] algos) {
12151215
cryptoWishList.serverHostKeyAlgorithms = algos;
12161216
}
12171217

1218+
/**
1219+
* Define the set of allowed key exchange methods.
1220+
*
1221+
* @param algos An array of allowed key exchange methods. The following are supported:
1222+
* diffie-hellman-group14-sha256,
1223+
* diffie-hellman-group16-sha512,
1224+
* diffie-hellman-group18-sha512,
1225+
* diffie-hellman-group14-sha1,
1226+
* diffie-hellman-group1-sha1,
1227+
* diffie-hellman-group-exchange-sha1
1228+
*/
1229+
public synchronized void setClientKexAlgorithms(String[] algos) {
1230+
if ((algos == null) || (algos.length == 0)) {
1231+
throw new IllegalArgumentException();
1232+
}
1233+
algos = removeDuplicates(algos);
1234+
KexManager.checkClientKexAlgorithmList(algos);
1235+
cryptoWishList.kexAlgorithms = algos;
1236+
}
1237+
12181238
/**
12191239
* Enable/disable TCP_NODELAY (disable/enable Nagle's algorithm) on the underlying socket.
12201240
* <p/>

src/main/java/ch/ethz/ssh2/crypto/dh/DhExchange.java

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class DhExchange
2121

2222
/* Given by the standard */
2323

24-
static final BigInteger p1, p14;
24+
static final BigInteger p1, p14, p16, p18;
2525
static final BigInteger g;
2626

2727
BigInteger p;
@@ -40,6 +40,8 @@ public class DhExchange
4040

4141
BigInteger k;
4242

43+
private String hashFunction = "SHA1";
44+
4345
static
4446
{
4547
final String p1_string = "17976931348623159077083915679378745319786029604875"
@@ -57,13 +59,62 @@ public class DhExchange
5759
+ "E3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF69558171"
5860
+ "83995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
5961

62+
final String p16_string = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD12902"
63+
+ "4E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1"
64+
+ "4374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386B"
65+
+ "FB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39"
66+
+ "A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E"
67+
+ "4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB"
68+
+ "5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8A"
69+
+ "AAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB39"
70+
+ "70F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A"
71+
+ "0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24"
72+
+ "FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B"
73+
+ "2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC1"
74+
+ "41FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AF"
75+
+ "B81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93"
76+
+ "4063199FFFFFFFFFFFFFFFF";
77+
78+
final String p18_string = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024"
79+
+ "E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14"
80+
+ "374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BF"
81+
+ "B5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A"
82+
+ "69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4"
83+
+ "ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5"
84+
+ "C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AA"
85+
+ "AC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB397"
86+
+ "0F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0"
87+
+ "864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24F"
88+
+ "A074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2"
89+
+ "699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC14"
90+
+ "1FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB"
91+
+ "81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934"
92+
+ "02849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5D"
93+
+ "B382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4"
94+
+ "BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032E"
95+
+ "A15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8"
96+
+ "F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED"
97+
+ "20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
98+
+ "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6"
99+
+ "DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD30074"
100+
+ "1FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39"
101+
+ "D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCB"
102+
+ "C8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F"
103+
+ "82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510"
104+
+ "BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382"
105+
+ "BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD"
106+
+ "98EDD3DFFFFFFFFFFFFFFFFF";
107+
60108
p1 = new BigInteger(p1_string);
61109
p14 = new BigInteger(p14_string, 16);
110+
p16 = new BigInteger(p16_string, 16);
111+
p18 = new BigInteger(p18_string, 16);
62112
g = new BigInteger("2");
63113
}
64114

65-
public DhExchange()
115+
public DhExchange(String hashFunction)
66116
{
117+
this.hashFunction = hashFunction;
67118
}
68119

69120
public void clientInit(int group, SecureRandom rnd)
@@ -74,6 +125,10 @@ public void clientInit(int group, SecureRandom rnd)
74125
p = p1;
75126
else if (group == 14)
76127
p = p14;
128+
else if (group == 16)
129+
p = p16;
130+
else if (group == 18)
131+
p = p18;
77132
else
78133
throw new IllegalArgumentException("Unknown DH group " + group);
79134

@@ -172,7 +227,7 @@ public void setE(BigInteger e)
172227
public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload,
173228
byte[] serverKexPayload, byte[] hostKey)
174229
{
175-
HashForSSH2Types hash = new HashForSSH2Types("SHA1");
230+
HashForSSH2Types hash = new HashForSSH2Types(hashFunction);
176231

177232
if (log.isInfoEnabled())
178233
{
@@ -191,4 +246,9 @@ public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clie
191246

192247
return hash.getDigest();
193248
}
249+
250+
public String getHashFunction()
251+
{
252+
return hashFunction;
253+
}
194254
}

src/main/java/ch/ethz/ssh2/crypto/digest/HMAC.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@ public final class HMAC implements Digest
2121
int size;
2222

2323
public HMAC(Digest md, byte[] key, int size)
24+
{
25+
this(md, key, size, 64);
26+
}
27+
28+
public HMAC(Digest md, byte[] key, int size, int blocksize)
2429
{
2530
this.md = md;
2631
this.size = size;
2732

2833
tmp = new byte[md.getDigestLength()];
2934

30-
final int BLOCKSIZE = 64;
35+
final int BLOCKSIZE = blocksize;
3136

3237
k_xor_ipad = new byte[BLOCKSIZE];
3338
k_xor_opad = new byte[BLOCKSIZE];

src/main/java/ch/ethz/ssh2/crypto/digest/HashForSSH2Types.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,15 @@ public HashForSSH2Types(Digest md)
2323

2424
public HashForSSH2Types(String type)
2525
{
26-
if (type.equals("SHA1"))
26+
if (type.equals("SHA2-512"))
27+
{
28+
md = new SHA2(512);
29+
}
30+
else if (type.equals("SHA2-256"))
31+
{
32+
md = new SHA2(256);
33+
}
34+
else if (type.equals("SHA1"))
2735
{
2836
md = new SHA1();
2937
}

src/main/java/ch/ethz/ssh2/crypto/digest/MAC.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public final static String[] getMacList()
1919
{
2020
/* Higher Priority First */
2121

22-
return new String[] { "hmac-sha1-96", "hmac-sha1", "hmac-md5-96", "hmac-md5" };
22+
return new String[] { "hmac-sha2-256", "hmac-sha2-512", "hmac-sha1-96", "hmac-sha1", "hmac-md5-96", "hmac-md5" };
2323
}
2424

2525
public final static void checkMacList(String[] macs)
@@ -30,6 +30,10 @@ public final static void checkMacList(String[] macs)
3030

3131
public final static int getKeyLen(String type)
3232
{
33+
if (type.equals("hmac-sha2-256"))
34+
return 32;
35+
if (type.equals("hmac-sha2-512"))
36+
return 64;
3337
if (type.equals("hmac-sha1"))
3438
return 20;
3539
if (type.equals("hmac-sha1-96"))
@@ -43,7 +47,15 @@ public final static int getKeyLen(String type)
4347

4448
public MAC(String type, byte[] key)
4549
{
46-
if (type.equals("hmac-sha1"))
50+
if (type.equals("hmac-sha2-256"))
51+
{
52+
mac = new HMAC(new SHA2(256), key, 32);
53+
}
54+
else if (type.equals("hmac-sha2-512"))
55+
{
56+
mac = new HMAC(new SHA2(512), key, 64, 128);
57+
}
58+
else if (type.equals("hmac-sha1"))
4759
{
4860
mac = new HMAC(new SHA1(), key, 20);
4961
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package ch.ethz.ssh2.crypto.digest;
2+
3+
import java.security.DigestException;
4+
import java.security.MessageDigest;
5+
import java.security.NoSuchAlgorithmException;
6+
7+
public class SHA2 implements Digest {
8+
9+
private MessageDigest md = null;
10+
11+
public SHA2(int keyLen) {
12+
try {
13+
md = MessageDigest.getInstance("SHA-" + keyLen);
14+
} catch (NoSuchAlgorithmException e) {
15+
throw new RuntimeException(e);
16+
}
17+
}
18+
19+
@Override
20+
public int getDigestLength() {
21+
return md.getDigestLength();
22+
}
23+
24+
@Override
25+
public void update(byte b) {
26+
md.update(b);
27+
}
28+
29+
@Override
30+
public void update(byte[] b) {
31+
md.update(b);
32+
}
33+
34+
@Override
35+
public void update(byte[] b, int off, int len) {
36+
md.update(b, off, len);
37+
}
38+
39+
@Override
40+
public void reset() {
41+
md.reset();
42+
}
43+
44+
@Override
45+
public void digest(byte[] out) {
46+
try {
47+
md.digest(out, 0, out.length);
48+
} catch (DigestException e) {
49+
throw new RuntimeException(e);
50+
}
51+
}
52+
53+
@Override
54+
public void digest(byte[] out, int off) {
55+
try {
56+
md.digest(out, off, out.length - off);
57+
} catch (DigestException e) {
58+
throw new RuntimeException(e);
59+
}
60+
}
61+
}

0 commit comments

Comments
 (0)