Skip to content

Commit

Permalink
Merge pull request #14 from jenkinsci/SHA256-and-SHA512-HMAC-support
Browse files Browse the repository at this point in the history
[JENKINS-33021] Add support for SHA256 and SHA512 HMAC algorithms
  • Loading branch information
mc1arke committed Apr 10, 2017
2 parents d0178c2 + 32b0250 commit 3aaec83
Show file tree
Hide file tree
Showing 14 changed files with 321 additions and 125 deletions.
8 changes: 4 additions & 4 deletions src/com/trilead/ssh2/Connection.java
Expand Up @@ -5,7 +5,7 @@
import com.trilead.ssh2.channel.ChannelManager;
import com.trilead.ssh2.crypto.CryptoWishList;
import com.trilead.ssh2.crypto.cipher.BlockCipherFactory;
import com.trilead.ssh2.crypto.digest.MAC;
import com.trilead.ssh2.crypto.digest.MessageMac;
import com.trilead.ssh2.log.Logger;
import com.trilead.ssh2.packets.PacketIgnore;
import com.trilead.ssh2.transport.ClientServerHello;
Expand Down Expand Up @@ -75,7 +75,7 @@ public static synchronized String[] getAvailableCiphers()
*/
public static synchronized String[] getAvailableMACs()
{
return MAC.getMacList();
return MessageMac.getMacs();
}

/**
Expand Down Expand Up @@ -1242,7 +1242,7 @@ public synchronized void setClient2ServerMACs(String[] macs)
if ((macs == null) || (macs.length == 0))
throw new IllegalArgumentException();
macs = removeDuplicates(macs);
MAC.checkMacList(macs);
MessageMac.checkMacs(macs);
cryptoWishList.c2s_mac_algos = macs;
}

Expand Down Expand Up @@ -1288,7 +1288,7 @@ public synchronized void setServer2ClientMACs(String[] macs)
throw new IllegalArgumentException();

macs = removeDuplicates(macs);
MAC.checkMacList(macs);
MessageMac.checkMacs(macs);
cryptoWishList.s2c_mac_algos = macs;
}

Expand Down
30 changes: 15 additions & 15 deletions src/com/trilead/ssh2/KnownHosts.java
Expand Up @@ -22,8 +22,8 @@

import com.trilead.ssh2.crypto.Base64;
import com.trilead.ssh2.crypto.digest.Digest;
import com.trilead.ssh2.crypto.digest.HMAC;
import com.trilead.ssh2.crypto.digest.MD5;
import com.trilead.ssh2.crypto.digest.MessageMac;
import com.trilead.ssh2.crypto.digest.SHA1;
import com.trilead.ssh2.log.Logger;

Expand Down Expand Up @@ -162,26 +162,26 @@ public static String createHashedHostname(String hostname)

private static byte[] hmacSha1Hash(byte[] salt, String hostname)
{
SHA1 sha1 = new SHA1();

if (salt.length != sha1.getDigestLength())
if (salt.length != 20) {
throw new IllegalArgumentException("Salt has wrong length (" + salt.length + ")");
}

HMAC hmac = new HMAC(sha1, salt, salt.length);
MessageMac messageMac = new MessageMac("hmac-sha1", salt);

try
{
hmac.update(hostname.getBytes("ISO-8859-1"));
}catch(UnsupportedEncodingException ignore)
{
/* Actually, ISO-8859-1 is supported by all correct
* Java implementations. But... you never know. */
hmac.update(hostname.getBytes());
try {
byte[] message = hostname.getBytes("ISO-8859-1");
messageMac.update(message, 0, message.length);
} catch (UnsupportedEncodingException ignore) {
/* Actually, ISO-8859-1 is supported by all correct
* Java implementations. But... you never know. */
byte[] message = hostname.getBytes();
messageMac.update(message, 0, message.length);
}

byte[] dig = new byte[hmac.getDigestLength()];

hmac.digest(dig);
byte[] dig = new byte[20];

messageMac.getMac(dig, 0);

return dig;
}
Expand Down
6 changes: 3 additions & 3 deletions src/com/trilead/ssh2/crypto/CryptoWishList.java
Expand Up @@ -2,7 +2,7 @@
package com.trilead.ssh2.crypto;

import com.trilead.ssh2.crypto.cipher.BlockCipherFactory;
import com.trilead.ssh2.crypto.digest.MAC;
import com.trilead.ssh2.crypto.digest.MessageMac;
import com.trilead.ssh2.transport.KexManager;


Expand All @@ -18,6 +18,6 @@ public class CryptoWishList
public String[] serverHostKeyAlgorithms = KexManager.getDefaultServerHostkeyAlgorithmList();
public String[] c2s_enc_algos = BlockCipherFactory.getDefaultCipherList();
public String[] s2c_enc_algos = BlockCipherFactory.getDefaultCipherList();
public String[] c2s_mac_algos = MAC.getMacList();
public String[] s2c_mac_algos = MAC.getMacList();
public String[] c2s_mac_algos = MessageMac.getMacs();
public String[] s2c_mac_algos = MessageMac.getMacs();
}
15 changes: 14 additions & 1 deletion src/com/trilead/ssh2/crypto/dh/DhExchange.java
Expand Up @@ -61,8 +61,17 @@ public class DhExchange
g = new BigInteger("2");
}

private final String hashAlgorithm;

@Deprecated
public DhExchange()
{
this("SHA1");
}

public DhExchange(String hashAlgorightm) {
super();
this.hashAlgorithm = hashAlgorightm;
}

public void init(int group, SecureRandom rnd)
Expand Down Expand Up @@ -125,7 +134,7 @@ public void setF(BigInteger f)
public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload,
byte[] serverKexPayload, byte[] hostKey) throws UnsupportedEncodingException
{
HashForSSH2Types hash = new HashForSSH2Types("SHA1");
HashForSSH2Types hash = new HashForSSH2Types(getHashAlgorithm());

if (log.isEnabled())
{
Expand All @@ -144,4 +153,8 @@ public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clie

return hash.getDigest();
}

public String getHashAlgorithm() {
return hashAlgorithm;
}
}
17 changes: 15 additions & 2 deletions src/com/trilead/ssh2/crypto/dh/DhGroupExchange.java
Expand Up @@ -34,10 +34,19 @@ public class DhGroupExchange

private BigInteger k;

public DhGroupExchange(BigInteger p, BigInteger g)
private final String hashAlgorithm;

@Deprecated
public DhGroupExchange(BigInteger p, BigInteger g) {
this("SHA1", p, g);
}


public DhGroupExchange(String algorithm, BigInteger p, BigInteger g)
{
this.p = p;
this.g = g;
this.hashAlgorithm = algorithm;
}

public void init(SecureRandom rnd)
Expand Down Expand Up @@ -90,7 +99,7 @@ public void setF(BigInteger f)
public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clientKexPayload,
byte[] serverKexPayload, byte[] hostKey, DHGexParameters para)
{
HashForSSH2Types hash = new HashForSSH2Types("SHA1");
HashForSSH2Types hash = new HashForSSH2Types(getHashAlgorithm());

hash.updateByteString(clientversion);
hash.updateByteString(serverversion);
Expand All @@ -110,4 +119,8 @@ public byte[] calculateH(byte[] clientversion, byte[] serverversion, byte[] clie

return hash.getDigest();
}

public String getHashAlgorithm() {
return hashAlgorithm;
}
}
1 change: 1 addition & 0 deletions src/com/trilead/ssh2/crypto/digest/HMAC.java
Expand Up @@ -7,6 +7,7 @@
* @author Christian Plattner, plattner@trilead.com
* @version $Id: HMAC.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $
*/
@Deprecated
public final class HMAC implements Digest
{
Digest md;
Expand Down
52 changes: 33 additions & 19 deletions src/com/trilead/ssh2/crypto/digest/HashForSSH2Types.java
Expand Up @@ -2,6 +2,8 @@
package com.trilead.ssh2.crypto.digest;

import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;

/**
* HashForSSH2Types.
Expand All @@ -11,46 +13,58 @@
*/
public class HashForSSH2Types
{

/**
* Overwriting this value will not cause the result of the
* digest to change
* @deprecated the actual message digest is held in a private field
*/
@Deprecated
Digest md;

private final Digest messageDigest;



public HashForSSH2Types(Digest md)
{
super();
this.md = md;
this.messageDigest = md;
}

public HashForSSH2Types(String type)
{
if (type.equals("SHA1"))
{
md = new SHA1();
}
else if (type.equals("MD5"))
{
md = new MD5();
this(new JreMessageDigestWrapper(createMessageDigest(type)));
}

private static MessageDigest createMessageDigest(String algorithm) {
try {
return MessageDigest.getInstance(algorithm);
} catch (GeneralSecurityException ex) {
throw new IllegalArgumentException("Could not get Message digest instance", ex);
}
else
throw new IllegalArgumentException("Unknown algorithm " + type);
}

public void updateByte(byte b)
{
/* HACK - to test it with J2ME */
byte[] tmp = new byte[1];
tmp[0] = b;
md.update(tmp);
messageDigest.update(tmp);
}

public void updateBytes(byte[] b)
{
md.update(b);
messageDigest.update(b);
}

public void updateUINT32(int v)
{
md.update((byte) (v >> 24));
md.update((byte) (v >> 16));
md.update((byte) (v >> 8));
md.update((byte) (v));
messageDigest.update((byte) (v >> 24));
messageDigest.update((byte) (v >> 16));
messageDigest.update((byte) (v >> 8));
messageDigest.update((byte) (v));
}

public void updateByteString(byte[] b)
Expand All @@ -66,17 +80,17 @@ public void updateBigInt(BigInteger b)

public void reset()
{
md.reset();
messageDigest.reset();
}

public int getDigestLength()
{
return md.getDigestLength();
return messageDigest.getDigestLength();
}

public byte[] getDigest()
{
byte[] tmp = new byte[md.getDigestLength()];
byte[] tmp = new byte[messageDigest.getDigestLength()];
getDigest(tmp);
return tmp;
}
Expand All @@ -88,6 +102,6 @@ public void getDigest(byte[] out)

public void getDigest(byte[] out, int off)
{
md.digest(out, off);
messageDigest.digest(out, off);
}
}
47 changes: 47 additions & 0 deletions src/com/trilead/ssh2/crypto/digest/JreMessageDigestWrapper.java
@@ -0,0 +1,47 @@
package com.trilead.ssh2.crypto.digest;

import java.security.MessageDigest;

/**
* @author Michael Clarke
*/
public class JreMessageDigestWrapper implements Digest {

private final MessageDigest digest;

public JreMessageDigestWrapper(MessageDigest digest) {
super();
this.digest = digest;
}

public int getDigestLength() {
return digest.getDigestLength();
}

public void update(byte b) {
digest.update(b);
}

public void update(byte[] b) {
digest.update(b);
}

public void update(byte[] b, int off, int len) {
digest.update(b, off, len);
}

public void reset() {
digest.reset();
}

public void digest(byte[] out) {
byte[] output = digest.digest();
System.arraycopy(output, 0, out, 0, out.length);
}

public void digest(byte[] out, int off) {
byte[] output = digest.digest();
System.arraycopy(output, 0, out, off, out.length);

}
}

0 comments on commit 3aaec83

Please sign in to comment.