All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.sshtools.client.components.DiffieHellmanGroup Maven / Gradle / Ivy
package com.sshtools.client.components;
/*-
* #%L
* Client API
* %%
* Copyright (C) 2002 - 2024 JADAPTIVE Limited
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
import java.io.IOException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
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 javax.crypto.KeyAgreement;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.DHPublicKeySpec;
import com.sshtools.client.SshClientContext;
import com.sshtools.client.SshKeyExchangeClient;
import com.sshtools.common.logger.Log;
import com.sshtools.common.publickey.SshKeyUtils;
import com.sshtools.common.publickey.SshPublicKeyFileFactory;
import com.sshtools.common.ssh.SecurityLevel;
import com.sshtools.common.ssh.SshException;
import com.sshtools.common.ssh.components.SshPrivateKey;
import com.sshtools.common.ssh.components.SshPublicKey;
import com.sshtools.common.ssh.components.jce.JCEAlgorithms;
import com.sshtools.common.ssh.components.jce.JCEProvider;
import com.sshtools.common.sshd.SshMessage;
import com.sshtools.common.util.ByteArrayReader;
import com.sshtools.common.util.Utils;
import com.sshtools.synergy.ssh.SshTransport;
/**
* Implementation of the required SSH Transport Protocol key exchange method
* "diffie-hellman-group14-sha1".
*/
public abstract class DiffieHellmanGroup extends SshKeyExchangeClient {
final static int SSH_MSG_KEXDH_INIT = 30;
final static int SSH_MSG_KEXDH_REPLY = 31;
final static BigInteger ONE = BigInteger.valueOf(1);
final static BigInteger TWO = BigInteger.valueOf(2);
/** generator, RFC recommends using 2*/
final static BigInteger g = TWO;
/** large safe prime, this comes from ....??*/
BigInteger p = null;
KeyPairGenerator dhKeyPairGen;
KeyAgreement dhKeyAgreement;
KeyFactory dhKeyFactory;
KeyPair dhKeyPair;
String kexAlgorithm;
/**
* Construct an uninitialized instance.
*/
DiffieHellmanGroup(String kexAlgorithm, String hashAlgorithm, BigInteger p, SecurityLevel securityLevel, int priority) {
super(hashAlgorithm, securityLevel, priority);
this.kexAlgorithm = kexAlgorithm;
this.p = p;
}
/**
* Get the algorithm name for this key exchange
* @return "diffie-hellman-group14-sha1"
*/
public String getAlgorithm() {
return kexAlgorithm;
}
@Override
public void init(SshTransport transport, String clientId, String serverId,
byte[] clientKexInit, byte[] serverKexInit, SshPrivateKey prvkey, SshPublicKey pubkey,
boolean firstPacketFollows, boolean useFirstPacket) throws IOException, SshException {
this.clientId = clientId;
this.serverId = serverId;
this.clientKexInit = clientKexInit;
this.serverKexInit = serverKexInit;
this.firstPacketFollows = firstPacketFollows;
this.useFirstPacket = useFirstPacket;
this.transport = transport;
// Generate a random number y
try {
initCrypto();
e = ((DHPublicKey)dhKeyPair.getPublic()).getY();
} catch(Exception ex) {
throw new IOException("Failed to generate DH value: " + ex.getMessage());
}
final byte[] eBytes = e.toByteArray();
transport.postMessage(new SshMessage() {
public boolean writeMessageIntoBuffer(ByteBuffer buf) {
buf.put((byte) SSH_MSG_KEXDH_INIT);
buf.putInt(eBytes.length);
buf.put(eBytes);
return true;
}
public void messageSent(Long sequenceNo) {
if(Log.isDebugEnabled())
Log.debug("Sent SSH_MSG_KEXDH_INIT");
}
}, true);
}
private void initCrypto() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException, InvalidKeyException {
dhKeyFactory = JCEProvider.getProviderForAlgorithm(JCEAlgorithms.JCE_DH)==null ?
KeyFactory.getInstance(JCEAlgorithms.JCE_DH) :
KeyFactory.getInstance(JCEAlgorithms.JCE_DH, JCEProvider.getProviderForAlgorithm(JCEAlgorithms.JCE_DH));
dhKeyPairGen = JCEProvider.getProviderForAlgorithm(JCEAlgorithms.JCE_DH)==null ?
KeyPairGenerator.getInstance(JCEAlgorithms.JCE_DH) :
KeyPairGenerator.getInstance(JCEAlgorithms.JCE_DH, JCEProvider.getProviderForAlgorithm(JCEAlgorithms.JCE_DH));
dhKeyAgreement = JCEProvider.getProviderForAlgorithm(JCEAlgorithms.JCE_DH)==null ?
KeyAgreement.getInstance(JCEAlgorithms.JCE_DH) :
KeyAgreement.getInstance(JCEAlgorithms.JCE_DH, JCEProvider.getProviderForAlgorithm(JCEAlgorithms.JCE_DH));
DHParameterSpec dhSkipParamSpec = new DHParameterSpec(p, g);
dhKeyPairGen.initialize(dhSkipParamSpec, JCEProvider.getSecureRandom());
dhKeyPair = dhKeyPairGen.generateKeyPair();
dhKeyAgreement.init(dhKeyPair.getPrivate());
}
public String getProvider() {
if(dhKeyAgreement!=null)
return dhKeyAgreement.getProvider().getName();
else
return "";
}
public boolean processMessage(byte[] m) throws SshException, IOException {
ByteArrayReader msg = new ByteArrayReader(m);
try {
int msgId = msg.read();
switch (msgId) {
case SSH_MSG_KEXDH_REPLY:
try {
hostKey = msg.readBinaryString();
f = msg.readBigInteger();
signature = msg.readBinaryString();
if(Log.isDebugEnabled()) {
Log.debug("Received SSH_MSG_KEXDH_INIT f={}", f.toString(16));
Log.debug("Host key: {}", SshKeyUtils.getOpenSSHFormattedKey(
SshPublicKeyFileFactory.decodeSSH2PublicKey(hostKey)));
Log.debug("Signature: {}", Utils.bytesToHex(signature));
}
DHPublicKeySpec spec = new DHPublicKeySpec(f, p, g);
dhKeyAgreement.doPhase(dhKeyFactory.generatePublic(spec), true);
byte[] tmp = dhKeyAgreement.generateSecret();
if ((tmp[0] & 0x80) == 0x80) {
byte[] tmp2 = new byte[tmp.length + 1];
System.arraycopy(tmp, 0, tmp2, 1, tmp.length);
tmp = tmp2;
}
// Calculate diffe hellman k value
secret = new BigInteger(tmp);
// Calculate the exchange hash
calculateExchangeHash();
transport.sendNewKeys();
} catch (Exception ex) {
throw new SshException(
"Failed to read SSH_MSG_KEXDH_REPLY from message buffer",
SshException.INTERNAL_ERROR, ex);
}
return true;
default:
return false;
}
} finally {
msg.close();
}
}
public boolean isKeyExchangeMessage(int messageid) {
switch (messageid) {
case SSH_MSG_KEXDH_INIT:
case SSH_MSG_KEXDH_REPLY:
return true;
default:
return false;
}
}
public void test() throws IOException, SshException {
try {
initCrypto();
} catch(Exception e) {
throw new IOException(e.getMessage(), e);
}
}
}