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