-
-
Notifications
You must be signed in to change notification settings - Fork 931
/
CfbCipherMode.cs
105 lines (89 loc) · 4.31 KB
/
CfbCipherMode.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
using System;
using System.Globalization;
namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
{
/// <summary>
/// Implements CFB cipher mode.
/// </summary>
public class CfbCipherMode : CipherMode
{
private readonly byte[] _ivOutput;
/// <summary>
/// Initializes a new instance of the <see cref="CfbCipherMode"/> class.
/// </summary>
/// <param name="iv">The iv.</param>
public CfbCipherMode(byte[] iv)
: base(iv)
{
_ivOutput = new byte[iv.Length];
}
/// <summary>
/// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
/// </summary>
/// <param name="inputBuffer">The input data to encrypt.</param>
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
/// <param name="outputBuffer">The output to which to write encrypted data.</param>
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
/// <returns>
/// The number of bytes encrypted.
/// </returns>
public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
if (inputBuffer.Length - inputOffset < _blockSize)
{
throw new ArgumentException("Invalid input buffer");
}
if (outputBuffer.Length - outputOffset < _blockSize)
{
throw new ArgumentException("Invalid output buffer");
}
if (inputCount != _blockSize)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize));
}
_ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0);
for (var i = 0; i < _blockSize; i++)
{
outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]);
}
Buffer.BlockCopy(IV, _blockSize, IV, 0, IV.Length - _blockSize);
Buffer.BlockCopy(outputBuffer, outputOffset, IV, IV.Length - _blockSize, _blockSize);
return _blockSize;
}
/// <summary>
/// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
/// </summary>
/// <param name="inputBuffer">The input data to decrypt.</param>
/// <param name="inputOffset">The offset into the input byte array from which to begin using data.</param>
/// <param name="inputCount">The number of bytes in the input byte array to use as data.</param>
/// <param name="outputBuffer">The output to which to write decrypted data.</param>
/// <param name="outputOffset">The offset into the output byte array from which to begin writing data.</param>
/// <returns>
/// The number of bytes decrypted.
/// </returns>
public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
{
if (inputBuffer.Length - inputOffset < _blockSize)
{
throw new ArgumentException("Invalid input buffer");
}
if (outputBuffer.Length - outputOffset < _blockSize)
{
throw new ArgumentException("Invalid output buffer");
}
if (inputCount != _blockSize)
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", _blockSize));
}
_ = Cipher.EncryptBlock(IV, 0, IV.Length, _ivOutput, 0);
Buffer.BlockCopy(IV, _blockSize, IV, 0, IV.Length - _blockSize);
Buffer.BlockCopy(inputBuffer, inputOffset, IV, IV.Length - _blockSize, _blockSize);
for (var i = 0; i < _blockSize; i++)
{
outputBuffer[outputOffset + i] = (byte)(_ivOutput[i] ^ inputBuffer[inputOffset + i]);
}
return _blockSize;
}
}
}