diff src/com/trilead/ssh2/crypto/dh/DhExchange.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/crypto/dh/DhExchange.java	Thu May 22 10:41:19 2014 -0700
@@ -0,0 +1,140 @@
+/**
+ *
+ */
+package com.trilead.ssh2.crypto.dh;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyFactory;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.spec.InvalidKeySpecException;
+
+import javax.crypto.KeyAgreement;
+import javax.crypto.interfaces.DHPrivateKey;
+import javax.crypto.interfaces.DHPublicKey;
+import javax.crypto.spec.DHParameterSpec;
+import javax.crypto.spec.DHPublicKeySpec;
+
+/**
+ * @author kenny
+ *
+ */
+public class DhExchange extends GenericDhExchange {
+
+    /* Given by the standard */
+
+    private static final BigInteger P1 = new BigInteger(
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+        + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+        + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+        + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
+        + "FFFFFFFFFFFFFFFF", 16);
+
+    private static final BigInteger P14 = new BigInteger(
+        "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+        + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
+        + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+        + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
+        + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+        + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
+        + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+        + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
+        + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+        + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
+        + "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 16);
+
+    private static final BigInteger G = BigInteger.valueOf(2);
+
+    /* Client public and private */
+
+    private DHPrivateKey clientPrivate;
+    private DHPublicKey clientPublic;
+
+    /* Server public */
+
+    private DHPublicKey serverPublic;
+
+    @Override
+    public void init(String name) throws IOException {
+        final DHParameterSpec spec;
+
+        if ("diffie-hellman-group1-sha1".equals(name)) {
+            spec = new DHParameterSpec(P1, G);
+        }
+        else if ("diffie-hellman-group14-sha1".equals(name)) {
+            spec = new DHParameterSpec(P14, G);
+        }
+        else {
+            throw new IllegalArgumentException("Unknown DH group " + name);
+        }
+
+        try {
+            KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
+            kpg.initialize(spec);
+            KeyPair pair = kpg.generateKeyPair();
+            clientPrivate = (DHPrivateKey) pair.getPrivate();
+            clientPublic = (DHPublicKey) pair.getPublic();
+        }
+        catch (NoSuchAlgorithmException e) {
+            throw(IOException) new IOException("No DH keypair generator").initCause(e);
+        }
+        catch (InvalidAlgorithmParameterException e) {
+            throw(IOException) new IOException("Invalid DH parameters").initCause(e);
+        }
+    }
+
+    @Override
+    public byte[] getE() {
+        if (clientPublic == null)
+            throw new IllegalStateException("DhExchange not initialized!");
+
+        return clientPublic.getY().toByteArray();
+    }
+
+    @Override
+    protected byte[] getServerE() {
+        if (serverPublic == null)
+            throw new IllegalStateException("DhExchange not initialized!");
+
+        return serverPublic.getY().toByteArray();
+    }
+
+    @Override
+    public void setF(byte[] f) throws IOException {
+        if (clientPublic == null)
+            throw new IllegalStateException("DhExchange not initialized!");
+
+        final KeyAgreement ka;
+
+        try {
+            KeyFactory kf = KeyFactory.getInstance("DH");
+            DHParameterSpec params = clientPublic.getParams();
+            this.serverPublic = (DHPublicKey) kf.generatePublic(new DHPublicKeySpec(
+                                    new BigInteger(f), params.getP(), params.getG()));
+            ka = KeyAgreement.getInstance("DH");
+            ka.init(clientPrivate);
+            ka.doPhase(serverPublic, true);
+        }
+        catch (NoSuchAlgorithmException e) {
+            throw(IOException) new IOException("No DH key agreement method").initCause(e);
+        }
+        catch (InvalidKeyException e) {
+            throw(IOException) new IOException("Invalid DH key").initCause(e);
+        }
+        catch (InvalidKeySpecException e) {
+            throw(IOException) new IOException("Invalid DH key").initCause(e);
+        }
+
+        sharedSecret = new BigInteger(ka.generateSecret());
+    }
+
+    @Override
+    public String getHashAlgo() {
+        return "SHA1";
+    }
+}