/// <summary> /// Устанавливает первичные настройки для блоков текста и ключа /// </summary> /// <param name="blockSize"></param> /// <param name="keySize"></param> /// <param name="key"></param> public void SetSettings(BlockSize blockSize, KeySize keySize, byte[] key) { var keyLengthInBytes = RijndaelSizesConverter.KeySizeToInt(keySize) / 8; if (key.Length != keyLengthInBytes) { throw new Exception("Неверная длина ключа"); } _blockSize = blockSize; _keySize = keySize; _key = key; GenerateKeyExpansion(); }
/// <summary> /// Генерирует набор ключей для шифрования и дешифрования /// </summary> private void GenerateKeyExpansion() { var blockSize = _blockSize; var keySize = _keySize; var key = _key; var blockSizeBits = RijndaelSizesConverter.BlockSizeToInt(blockSize); var nb = blockSizeBits / 32; var nr = GetAmountRounds(blockSize, keySize); // amount rounds var nk = RijndaelSizesConverter.KeySizeToInt(keySize) / 32; // amount of columns switch (blockSizeBits > key.Length * 8 ? blockSizeBits : key.Length * 8) { case 128: nr = 10; break; case 192: nr = 12; break; case 256: nr = 14; break; default: throw new Exception("InvalidKeySize"); } _encryptKeyExpansion = new int[nb * (nr + 1)]; _decryptKeyExpansion = new int[nb * (nr + 1)]; int iTemp; var index = 0; for (var i = 0; i < nk; ++i) { int i0 = key[index++]; int i1 = key[index++]; int i2 = key[index++]; int i3 = key[index++]; _encryptKeyExpansion[i] = i3 << 24 | i2 << 16 | i1 << 8 | i0; } if (nk <= 6) { for (var i = nk; i < nb * (nr + 1); ++i) { iTemp = _encryptKeyExpansion[i - 1]; if (i % nk == 0) { iTemp = SubWord(Rot3(iTemp)); iTemp ^= RijndaelTables.Rcon[(i / nk) - 1]; } _encryptKeyExpansion[i] = _encryptKeyExpansion[i - nk] ^ iTemp; } } else { for (var i = nk; i < nb * (nr + 1); ++i) { iTemp = _encryptKeyExpansion[i - 1]; if (i % nk == 0) { iTemp = SubWord(Rot3(iTemp)); iTemp ^= RijndaelTables.Rcon[(i / nk) - 1]; } else if (i % nk == 4) { iTemp = SubWord(iTemp); } _encryptKeyExpansion[i] = _encryptKeyExpansion[i - nk] ^ iTemp; } } for (var i = 0; i < nb; ++i) { _decryptKeyExpansion[i] = _encryptKeyExpansion[i]; _decryptKeyExpansion[nb * nr + i] = _encryptKeyExpansion[nb * nr + i]; } for (var i = nb; i < nb * nr; ++i) { var tmpKey = _encryptKeyExpansion[i]; var mul02 = MulX(tmpKey); var mul04 = MulX(mul02); var mul08 = MulX(mul04); var mul09 = tmpKey ^ mul08; _decryptKeyExpansion[i] = mul02 ^ mul04 ^ mul08 ^ Rot3(mul02 ^ mul09) ^ Rot2(mul04 ^ mul09) ^ Rot1(mul09); } for (var i = 0; i < nr + 1; i++) { for (var k = 0; k < nb; k++) { _decryptKeyExpansion[i * nb + k] = _encryptKeyExpansion[(nr - i) * nb + k]; } } }
/// <summary> /// Ничего интересного. Читаем файл, шифруем/дешифруем его. Решаем пролему некратных блоков. /// </summary> /// <param name="inFile"></param> /// <param name="outFile"></param> /// <param name="handler"></param> /// <param name="isEncrypting"></param> void ProcessFileANSIX923(FileStream inFile, FileStream outFile, Func <byte[], byte[]> handler, bool isEncrypting) { var amountBytesInBlock = RijndaelSizesConverter.BlockSizeToInt(_blockSize) / 8; var fileSize = inFile.Length; var blocksAmount = fileSize / amountBytesInBlock; SetMaximum(blocksAmount); var oneTick = blocksAmount / 100 + 1; // при дешифровке блоков должно быть минимум 2 и размер должен быть кратен блоку var incorrectFile = (fileSize % amountBytesInBlock != 0) && !isEncrypting; if (incorrectFile) { throw new Exception("Неверный формат файла"); } var readedBlocksAmount = 0; var inData = new byte[amountBytesInBlock]; var outData = new byte[0]; int readBytesAmount = 0; while (true) { readBytesAmount = inFile.Read(inData, 0, inData.Length); if (readBytesAmount != amountBytesInBlock) { break; } readedBlocksAmount++; outData = handler(inData); var isLast = blocksAmount == readedBlocksAmount; if (isLast && !isEncrypting) { // последний блок при расшифровке прочитан var amount = outData[amountBytesInBlock - 1]; if (amount < 0 || amount > amountBytesInBlock) { throw new Exception("Неверный формат файла"); } outFile.Write(outData, 0, amount); } else { outFile.Write(outData, 0, outData.Length); } inData = new byte[amountBytesInBlock]; SetValue(readedBlocksAmount); } var gCount = (byte)(inFile.Length % amountBytesInBlock); // сколько байт осталось в потоке if (isEncrypting) { // старшие биты пусты - в самый старший добавить (8 - gCount) if (gCount != amountBytesInBlock) { inData[amountBytesInBlock - 1] = gCount; } // зашифруем данные outData = handler(inData); outFile.Write(outData, 0, amountBytesInBlock); if (gCount == amountBytesInBlock) { // добавим gcount в конец файла зашифровав его var gCountIn = new byte[amountBytesInBlock]; gCountIn[0] = gCount; var gCountOut = handler(gCountIn); outFile.Write(gCountOut, 0, amountBytesInBlock); } } }
public RijndaelKey(BlockSize blockSize, int[] keyExpansion, int offset) : base(RijndaelSizesConverter.BlockSizeToInt(blockSize) / 32) { LoadFromKeyExpansion(keyExpansion, offset); }
public RijndaelState(BlockSize blockSize, byte[] block) : base(RijndaelSizesConverter.BlockSizeToInt(blockSize) / 32) { LoadFromBlock(block); }