Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ The main types provided by this library are:
Private keys in OpenSSL traditional PEM format can be encrypted using one of the following cipher methods:
* DES-EDE3-CBC
* DES-EDE3-CFB
* DES-CBC
* AES-128-CBC
* AES-192-CBC
* AES-256-CBC
Expand Down
15 changes: 7 additions & 8 deletions src/Renci.SshNet/ConnectionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
using Renci.SshNet.Security;
using Renci.SshNet.Security.Cryptography;
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;

namespace Renci.SshNet
{
Expand Down Expand Up @@ -363,16 +362,16 @@ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyTy

Encryptions = new Dictionary<string, CipherInfo>
{
{ "aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, iv, AesCipherMode.CTR, pkcs7Padding: false)) },
{ "aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, iv, AesCipherMode.CTR, pkcs7Padding: false)) },
{ "aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, iv, AesCipherMode.CTR, pkcs7Padding: false)) },
{ "aes128-ctr", new CipherInfo(128, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CTR, pkcs7Padding: false)) },
{ "aes192-ctr", new CipherInfo(192, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CTR, pkcs7Padding: false)) },
{ "aes256-ctr", new CipherInfo(256, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CTR, pkcs7Padding: false)) },
{ "aes128-gcm@openssh.com", new CipherInfo(128, (key, iv) => new AesGcmCipher(key, iv, aadLength: 4), isAead: true) },
{ "aes256-gcm@openssh.com", new CipherInfo(256, (key, iv) => new AesGcmCipher(key, iv, aadLength: 4), isAead: true) },
{ "chacha20-poly1305@openssh.com", new CipherInfo(512, (key, iv) => new ChaCha20Poly1305Cipher(key, aadLength: 4), isAead: true) },
{ "aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: false)) },
{ "aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: false)) },
{ "aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: false)) },
{ "3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), padding: null)) },
{ "aes128-cbc", new CipherInfo(128, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false)) },
{ "aes192-cbc", new CipherInfo(192, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false)) },
{ "aes256-cbc", new CipherInfo(256, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false)) },
{ "3des-cbc", new CipherInfo(192, (key, iv) => new TripleDesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false)) },
};

HmacAlgorithms = new Dictionary<string, HashInfo>
Expand Down
15 changes: 7 additions & 8 deletions src/Renci.SshNet/PrivateKeyFile.OpenSSH.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Renci.SshNet.Security;
using Renci.SshNet.Security.Cryptography;
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;

namespace Renci.SshNet
{
Expand Down Expand Up @@ -91,25 +90,25 @@ public Key Parse()
{
case "3des-cbc":
ivLength = 8;
cipherInfo = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), padding: null));
cipherInfo = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false));
break;
case "aes128-cbc":
cipherInfo = new CipherInfo(128, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: false));
cipherInfo = new CipherInfo(128, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false));
break;
case "aes192-cbc":
cipherInfo = new CipherInfo(192, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: false));
cipherInfo = new CipherInfo(192, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false));
break;
case "aes256-cbc":
cipherInfo = new CipherInfo(256, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: false));
cipherInfo = new CipherInfo(256, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: false));
break;
case "aes128-ctr":
cipherInfo = new CipherInfo(128, (key, iv) => new AesCipher(key, iv, AesCipherMode.CTR, pkcs7Padding: false));
cipherInfo = new CipherInfo(128, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CTR, pkcs7Padding: false));
break;
case "aes192-ctr":
cipherInfo = new CipherInfo(192, (key, iv) => new AesCipher(key, iv, AesCipherMode.CTR, pkcs7Padding: false));
cipherInfo = new CipherInfo(192, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CTR, pkcs7Padding: false));
break;
case "aes256-ctr":
cipherInfo = new CipherInfo(256, (key, iv) => new AesCipher(key, iv, AesCipherMode.CTR, pkcs7Padding: false));
cipherInfo = new CipherInfo(256, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CTR, pkcs7Padding: false));
break;
case "aes128-gcm@openssh.com":
cipherInfo = new CipherInfo(128, (key, iv) => new AesGcmCipher(key, iv, aadLength: 0), isAead: true);
Expand Down
15 changes: 5 additions & 10 deletions src/Renci.SshNet/PrivateKeyFile.PKCS1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
using Renci.SshNet.Common;
using Renci.SshNet.Security;
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
using Renci.SshNet.Security.Cryptography.Ciphers.Paddings;

namespace Renci.SshNet
{
Expand Down Expand Up @@ -51,22 +49,19 @@ public Key Parse()
switch (_cipherName)
{
case "DES-EDE3-CBC":
cipher = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()));
cipher = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: true));
break;
case "DES-EDE3-CFB":
cipher = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CfbCipherMode(iv), padding: null));
break;
case "DES-CBC":
cipher = new CipherInfo(64, (key, iv) => new DesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()));
cipher = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, iv, BlockCipherMode.CFB, pkcs7Padding: false));
break;
case "AES-128-CBC":
cipher = new CipherInfo(128, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: true));
cipher = new CipherInfo(128, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: true));
break;
case "AES-192-CBC":
cipher = new CipherInfo(192, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: true));
cipher = new CipherInfo(192, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: true));
break;
case "AES-256-CBC":
cipher = new CipherInfo(256, (key, iv) => new AesCipher(key, iv, AesCipherMode.CBC, pkcs7Padding: true));
cipher = new CipherInfo(256, (key, iv) => new AesCipher(key, iv, BlockCipherMode.CBC, pkcs7Padding: true));
break;
default:
throw new SshException(string.Format(CultureInfo.InvariantCulture, "Private key cipher \"{0}\" is not supported.", _cipherName));
Expand Down
2 changes: 1 addition & 1 deletion src/Renci.SshNet/PrivateKeyFile.PuTTY.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public Key Parse()
throw new SshException("PuTTY key file version " + _version + " is not supported");
}

using (var cipher = new AesCipher(cipherKey, cipherIV, AesCipherMode.CBC, pkcs7Padding: false))
using (var cipher = new AesCipher(cipherKey, cipherIV, BlockCipherMode.CBC, pkcs7Padding: false))
{
privateKey = cipher.Decrypt(_data);
}
Expand Down
3 changes: 1 addition & 2 deletions src/Renci.SshNet/PrivateKeyFile.SSHCOM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using Renci.SshNet.Common;
using Renci.SshNet.Security;
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;

namespace Renci.SshNet
{
Expand Down Expand Up @@ -51,7 +50,7 @@ public Key Parse()
}

var key = GetCipherKey(_passPhrase, 192 / 8);
var ssh2Сipher = new TripleDesCipher(key, new CbcCipherMode(new byte[8]), padding: null);
var ssh2Сipher = new TripleDesCipher(key, new byte[8], BlockCipherMode.CBC, pkcs7Padding: false);
keyData = ssh2Сipher.Decrypt(reader.ReadBytes(blobSize));
}
else
Expand Down
3 changes: 0 additions & 3 deletions src/Renci.SshNet/PrivateKeyFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ namespace Renci.SshNet
/// <description>DES-EDE3-CFB</description>
/// </item>
/// <item>
/// <description>DES-CBC</description>
/// </item>
/// <item>
/// <description>AES-128-CBC</description>
/// </item>
/// <item>
Expand Down
10 changes: 7 additions & 3 deletions src/Renci.SshNet/Security/Cryptography/BlockCipher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;

using Org.BouncyCastle.Crypto.Paddings;

using Renci.SshNet.Common;
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
Expand All @@ -13,7 +15,7 @@ public abstract class BlockCipher : SymmetricCipher
{
private readonly CipherMode _mode;

private readonly CipherPadding _padding;
private readonly IBlockCipherPadding _padding;

/// <summary>
/// Gets the size of the block in bytes.
Expand Down Expand Up @@ -56,7 +58,7 @@ public byte BlockSize
/// <param name="mode">Cipher mode.</param>
/// <param name="padding">Cipher padding.</param>
/// <exception cref="ArgumentNullException"><paramref name="key"/> is <see langword="null"/>.</exception>
protected BlockCipher(byte[] key, byte blockSize, CipherMode mode, CipherPadding padding)
protected BlockCipher(byte[] key, byte blockSize, CipherMode mode, IBlockCipherPadding padding)
: base(key)
{
_blockSize = blockSize;
Expand All @@ -81,7 +83,9 @@ public override byte[] Encrypt(byte[] input, int offset, int length)
if (_padding is not null)
{
paddingLength = _blockSize - (length % _blockSize);
input = _padding.Pad(input, offset, length, paddingLength);
input = input.Take(offset, length);
Array.Resize(ref input, length + paddingLength);
_ = _padding.AddPadding(input, length);
length += paddingLength;
offset = 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public override byte[] Encrypt(byte[] input, int offset, int length)
{
if (_aes.Mode is System.Security.Cryptography.CipherMode.CFB or System.Security.Cryptography.CipherMode.OFB)
{
// Manually pad the input for cfb and ofb cipher mode as BCL doesn't support partial block.
// See https://github.com/dotnet/runtime/blob/e7d837da5b1aacd9325a8b8f2214cfaf4d3f0ff6/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs#L20-L21
paddingLength = BlockSize - (length % BlockSize);
input = input.Take(offset, length);
length += paddingLength;
Expand All @@ -69,6 +71,7 @@ public override byte[] Encrypt(byte[] input, int offset, int length)

if (paddingLength > 0)
{
// Manually unpad the output.
Array.Resize(ref output, output.Length - paddingLength);
}

Expand All @@ -89,11 +92,12 @@ public override byte[] Decrypt(byte[] input, int offset, int length)
{
if (_aes.Mode is System.Security.Cryptography.CipherMode.CFB or System.Security.Cryptography.CipherMode.OFB)
{
// Manually pad the input for cfb and ofb cipher mode as BCL doesn't support partial block.
// See https://github.com/dotnet/runtime/blob/e7d837da5b1aacd9325a8b8f2214cfaf4d3f0ff6/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SymmetricPadding.cs#L20-L21
paddingLength = BlockSize - (length % BlockSize);
var newInput = new byte[input.Length + paddingLength];
Buffer.BlockCopy(input, offset, newInput, 0, length);
input = newInput;
length = input.Length;
input = input.Take(offset, length);
length += paddingLength;
Array.Resize(ref input, length);
offset = 0;
}
}
Expand All @@ -107,6 +111,7 @@ public override byte[] Decrypt(byte[] input, int offset, int length)

if (paddingLength > 0)
{
// Manually unpad the output.
Array.Resize(ref output, output.Length - paddingLength);
}

Expand All @@ -123,21 +128,11 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC
throw new NotImplementedException($"Invalid usage of {nameof(DecryptBlock)}.");
}

private void Dispose(bool disposing)
{
if (disposing)
{
_aes.Dispose();
_encryptor.Dispose();
_decryptor.Dispose();
}
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
_aes.Dispose();
_encryptor.Dispose();
_decryptor.Dispose();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.Security.Cryptography;

using Org.BouncyCastle.Crypto.Paddings;

namespace Renci.SshNet.Security.Cryptography.Ciphers
{
public partial class AesCipher
Expand All @@ -11,7 +13,7 @@ private sealed class BlockImpl : BlockCipher, IDisposable
private readonly ICryptoTransform _encryptor;
private readonly ICryptoTransform _decryptor;

public BlockImpl(byte[] key, CipherMode mode, CipherPadding padding)
public BlockImpl(byte[] key, CipherMode mode, IBlockCipherPadding padding)
: base(key, 16, mode, padding)
{
var aes = Aes.Create();
Expand All @@ -33,21 +35,11 @@ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputC
return _decryptor.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
}

private void Dispose(bool disposing)
{
if (disposing)
{
_aes.Dispose();
_encryptor.Dispose();
_decryptor.Dispose();
}
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
_aes.Dispose();
_encryptor.Dispose();
_decryptor.Dispose();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,20 +105,10 @@ private static void ArrayXOR(byte[] buffer, byte[] data, int offset, int length)
}
}

private void Dispose(bool disposing)
{
if (disposing)
{
_aes.Dispose();
_encryptor.Dispose();
}
}

public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
_aes.Dispose();
_encryptor.Dispose();
}
}
}
Expand Down
Loading