private byte[] ComputeEncryptionKey(IKexAlgorithm kexAlgorithm, byte[] exchangeHash, uint keySize, byte[] sharedSecret, char letter) { // K(X) = HASH(K || H || X || session_id) // Prepare the buffer byte[] keyBuffer = new byte[keySize]; int keyBufferIndex = 0; int currentHashLength = 0; byte[] currentHash = null; // We can stop once we fill the key buffer while (keyBufferIndex < keySize) { using (ByteWriter writer = new ByteWriter()) { // Write "K" writer.WriteMPInt(sharedSecret); // Write "H" writer.WriteRawBytes(exchangeHash); if (currentHash == null) { // If we haven't done this yet, add the "X" and session_id writer.WriteByte((byte)letter); writer.WriteRawBytes(m_SessionId); } else { // If the key isn't long enough after the first pass, we need to // write the current hash as described here: // K1 = HASH(K || H || X || session_id) (X is e.g., "A") // K2 = HASH(K || H || K1) // K3 = HASH(K || H || K1 || K2) // ... // key = K1 || K2 || K3 || ... writer.WriteRawBytes(currentHash); } currentHash = kexAlgorithm.ComputeHash(writer.ToByteArray()); } currentHashLength = Math.Min(currentHash.Length, (int)(keySize - keyBufferIndex)); Array.Copy(currentHash, 0, keyBuffer, keyBufferIndex, currentHashLength); keyBufferIndex += currentHashLength; } return(keyBuffer); }
public IKexAlgorithm PickKexAlgorithm() { foreach (string algo in this.KexAlgorithms) { IKexAlgorithm selectedAlgo = Server.GetType <IKexAlgorithm>(Server.SupportedKexAlgorithms, algo); if (selectedAlgo != null) { return(selectedAlgo); } } // If no algorithm satisfying all these conditions can be found, the // connection fails, and both sides MUST disconnect. throw new SSHServerException(DisconnectReason.SSH_DISCONNECT_KEY_EXCHANGE_FAILED, "Could not find a shared Kex Algorithm"); }
private byte[] ComputeExchangeHash(IKexAlgorithm kexAlgorithm, byte[] hostKeyAndCerts, byte[] clientExchangeValue, byte[] serverExchangeValue, byte[] sharedSecret) { // H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K) using (ByteWriter writer = new ByteWriter()) { writer.WriteString(m_ProtocolVersionExchange); writer.WriteString(Server.ProtocolVersionExchange); writer.WriteBytes(m_KexInitClientToServer.GetBytes()); writer.WriteBytes(m_KexInitServerToClient.GetBytes()); writer.WriteBytes(hostKeyAndCerts); writer.WriteMPInt(clientExchangeValue); writer.WriteMPInt(serverExchangeValue); writer.WriteMPInt(sharedSecret); return(kexAlgorithm.ComputeHash(writer.ToByteArray())); } }