Skip to content

Commit 95bd7fd

Browse files
committed
Encrypt should take into account *manual* padding for length of inputBuffer passed to EncryptBlock and unpadding for the final output if padding is not specified and mode is CFB or OFB.
1 parent 0303aa9 commit 95bd7fd

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

src/Renci.SshNet/Security/Cryptography/BlockCipher.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,10 @@ protected BlockCipher(byte[] key, byte blockSize, CipherMode mode, CipherPadding
8080
/// </returns>
8181
public override byte[] Encrypt(byte[] input, int offset, int length)
8282
{
83+
var paddingLength = 0;
8384
if (_padding is not null)
8485
{
85-
var paddingLength = _blockSize - (length % _blockSize);
86+
paddingLength = _blockSize - (length % _blockSize);
8687
input = _padding.Pad(input, offset, length, paddingLength);
8788
length += paddingLength;
8889
offset = 0;
@@ -91,10 +92,10 @@ public override byte[] Encrypt(byte[] input, int offset, int length)
9192
{
9293
if (_mode is CfbCipherMode or OfbCipherMode)
9394
{
94-
var paddingLength = _blockSize - (length % _blockSize);
95+
paddingLength = _blockSize - (length % _blockSize);
9596
input = input.Take(offset, length);
96-
Array.Resize(ref input, length + paddingLength);
9797
length += paddingLength;
98+
Array.Resize(ref input, length);
9899
offset = 0;
99100
}
100101
else
@@ -123,6 +124,11 @@ public override byte[] Encrypt(byte[] input, int offset, int length)
123124
throw new InvalidOperationException("Encryption error.");
124125
}
125126

127+
if (_padding is null && paddingLength > 0)
128+
{
129+
Array.Resize(ref output, output.Length - paddingLength);
130+
}
131+
126132
return output;
127133
}
128134

test/Renci.SshNet.Tests/Classes/Security/Cryptography/BlockCipherTest.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,27 @@ public void EncryptShouldTakeIntoAccountPaddingForLengthOfInputBufferPassedToEnc
5656
Assert.IsTrue(output.SequenceEqual(actual));
5757
}
5858

59+
[TestMethod]
60+
public void EncryptShouldTakeIntoAccountManualPaddingForLengthOfInputBufferPassedToDecryptBlockAndUnPaddingForTheFinalOutput_CFB()
61+
{
62+
var input = new byte[] { 0x0a, 0x00, 0x03, 0x02, 0x06 };
63+
var output = new byte[] { 0x2c, 0x1a, 0x05, 0x00, 0x68 };
64+
var key = new byte[] { 0x17, 0x78, 0x56, 0xe1, 0x3e, 0xbd, 0x3e, 0x50, 0x1d, 0x79, 0x3f, 0x0f, 0x55, 0x37, 0x45, 0x54 };
65+
var blockCipher = new BlockCipherStub(key, 8, new CfbCipherModeStub(new byte[8]), null)
66+
{
67+
EncryptBlockDelegate = (inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset) =>
68+
{
69+
Assert.AreEqual(8, inputBuffer.Length);
70+
Buffer.BlockCopy(output, 0, outputBuffer, 0, output.Length);
71+
return inputBuffer.Length;
72+
}
73+
};
74+
75+
var actual = blockCipher.Encrypt(input);
76+
77+
Assert.IsTrue(output.SequenceEqual(actual));
78+
}
79+
5980
[TestMethod]
6081
public void DecryptShouldTakeIntoAccountUnPaddingForTheFinalOutput()
6182
{
@@ -128,6 +149,11 @@ public CfbCipherModeStub(byte[] iv)
128149
{
129150
}
130151

152+
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
153+
{
154+
return Cipher.EncryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
155+
}
156+
131157
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
132158
{
133159
return Cipher.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);

0 commit comments

Comments
 (0)