internal abstract class SymmetricTransform : ICryptoTransform {
protected SymmetricAlgorithm algo;
protected bool encrypt;
- private int BlockSizeByte;
- private byte[] temp;
- private byte[] temp2;
+ protected int BlockSizeByte;
+ protected byte[] temp;
+ protected byte[] temp2;
private byte[] workBuff;
private byte[] workout;
#if !MOONLIGHT
// Silverlight 2.0 does not support any feedback mode
- private int FeedBackByte;
- private int FeedBackIter;
+ protected int FeedBackByte;
#endif
private bool m_disposed = false;
private bool lastBlock;
temp2 = new byte [BlockSizeByte];
#if !MOONLIGHT
FeedBackByte = (algo.FeedbackSize >> 3);
- if (FeedBackByte != 0)
- FeedBackIter = (int) BlockSizeByte / FeedBackByte;
#endif
// transform buffers
workBuff = new byte [BlockSizeByte];
#if !MOONLIGHT
// Cipher-FeedBack (CFB)
+ // this is how *CryptoServiceProvider implements CFB
+ // only AesCryptoServiceProvider support CFB > 8
+ // RijndaelManaged is incompatible with this implementation (and overrides it in it's own transform)
protected virtual void CFB (byte[] input, byte[] output)
{
if (encrypt) {
- for (int x = 0; x < FeedBackIter; x++) {
+ for (int x = 0; x < BlockSizeByte; x++) {
// temp is first initialized with the IV
ECB (temp, temp2);
- for (int i = 0; i < FeedBackByte; i++)
+ for (int i = 0; i < 1; i++)
output[i + x] = (byte)(temp2[i] ^ input[i + x]);
- Buffer.BlockCopy (temp, FeedBackByte, temp, 0, BlockSizeByte - FeedBackByte);
- Buffer.BlockCopy (output, x, temp, BlockSizeByte - FeedBackByte, FeedBackByte);
+ Buffer.BlockCopy (temp, 1, temp, 0, BlockSizeByte - 1);
+ Buffer.BlockCopy (output, x, temp, BlockSizeByte - 1, 1);
}
}
else {
- for (int x = 0; x < FeedBackIter; x++) {
+ for (int x = 0; x < BlockSizeByte; x++) {
// we do not really decrypt this data!
encrypt = true;
// temp is first initialized with the IV
ECB (temp, temp2);
encrypt = false;
- Buffer.BlockCopy (temp, FeedBackByte, temp, 0, BlockSizeByte - FeedBackByte);
- Buffer.BlockCopy (input, x, temp, BlockSizeByte - FeedBackByte, FeedBackByte);
- for (int i = 0; i < FeedBackByte; i++)
+ Buffer.BlockCopy (temp, 1, temp, 0, BlockSizeByte - 1);
+ Buffer.BlockCopy (input, x, temp, BlockSizeByte - 1, 1);
+ for (int i = 0; i < 1; i++)
output[i + x] = (byte)(temp2[i] ^ input[i + x]);
}
}
// Notes: This class is "publicly" new in Fx 2.0 but was already
// existing in Fx 1.0. So this new class is only calling the old
- // (and more general) one (RijndaelTransform) located in
- // RijndaelManaged.cs.
+ // (and more general) one (RijndaelTransform)
[ComVisible (true)]
public sealed class RijndaelManagedTransform: ICryptoTransform, IDisposable {
private RijndaelTransform _st;
private int _bs;
+ private int _ts;
internal RijndaelManagedTransform (Rijndael algo, bool encryption, byte[] key, byte[] iv)
{
_st = new RijndaelTransform (algo, encryption, key, iv);
_bs = algo.BlockSize;
+ _ts = algo.Mode == CipherMode.CFB ? algo.FeedbackSize >> 3 : _st.InputBlockSize;
}
public int BlockSizeValue {
}
public int InputBlockSize {
- get { return _st.InputBlockSize; }
+ get { return _ts; }
}
public int OutputBlockSize {
- get { return _st.OutputBlockSize; }
+ get { return _ts; }
}
public void Clear ()
}
}
- internal class RijndaelTransform : SymmetricTransform
- {
+ class RijndaelTransform : SymmetricTransform {
private uint[] expandedKey;
-
+ private int FeedBackIter;
private int Nb;
private int Nk;
private int Nr;
}
keySize <<= 3; // bytes -> bits
int blockSize = algo.BlockSize;
+ FeedBackIter = (int) BlockSizeByte / FeedBackByte; // for CFB
this.Nb = (blockSize >> 5); // div 32
this.Nk = (keySize >> 5); // div 32
}
}
+ // RijndaelManaged does not implement CFB like any *CryptoServiceProvider does
+ // not even AesCryptoServiceProvider, while AesManaged does not support CFB at all
+ protected override void CFB (byte[] input, byte[] output)
+ {
+ if (encrypt) {
+ for (int x = 0; x < FeedBackIter; x++) {
+ // temp is first initialized with the IV
+ ECB (temp, temp2);
+
+ for (int i = 0; i < FeedBackByte; i++)
+ output[i + x] = (byte)(temp2[i] ^ input[i + x]);
+ Buffer.BlockCopy (temp, FeedBackByte, temp, 0, BlockSizeByte - FeedBackByte);
+ Buffer.BlockCopy (output, x, temp, BlockSizeByte - FeedBackByte, FeedBackByte);
+ }
+ }
+ else {
+ for (int x = 0; x < FeedBackIter; x++) {
+ // we do not really decrypt this data!
+ encrypt = true;
+ // temp is first initialized with the IV
+ ECB (temp, temp2);
+ encrypt = false;
+
+ Buffer.BlockCopy (temp, FeedBackByte, temp, 0, BlockSizeByte - FeedBackByte);
+ Buffer.BlockCopy (input, x, temp, BlockSizeByte - FeedBackByte, FeedBackByte);
+ for (int i = 0; i < FeedBackByte; i++)
+ output[i + x] = (byte)(temp2[i] ^ input[i + x]);
+ }
+ }
+ }
+
private UInt32 SubByte (UInt32 a)
{
UInt32 value = 0xff & a;