📄 cryptotestcase.cs
字号:
padding = PaddingMode.Zeros; } } else { // Stream cipher mode - padding is never required. padding = PaddingMode.None; } switch(padding) { case PaddingMode.None: break; case PaddingMode.PKCS7: { len = input.Length; len += size - (len % size); pad = len - input.Length; padded = new byte [len]; Array.Copy(input, 0, padded, 0, input.Length); len = input.Length; while(len < padded.Length) { padded[len++] = (byte)pad; } input = padded; } break; case PaddingMode.Zeros: { len = input.Length; if((len % size) != 0) { len += size - (len % size); } padded = new byte [len]; Array.Copy(input, 0, padded, 0, input.Length); input = padded; } break; } return input; } // Create a test key for a specific algorihtm. private byte[] CreateKey(SymmetricAlgorithm alg) { byte[] key = new byte [alg.KeySize / 8]; int posn; for(posn = 0; posn < key.Length; ++posn) { key[posn] = (byte)posn; } return key; } // Create a test IV for a specific algorithm. private byte[] CreateIV(SymmetricAlgorithm alg) { if(alg.Mode == CipherMode.ECB) { // ECB modes don't need an IV. return null; } else { // All other modes do need an IV. byte[] iv = new byte [alg.BlockSize / 8]; int posn; for(posn = 0; posn < iv.Length; ++posn) { iv[posn] = (byte)(iv.Length - posn); } return iv; } } // ECB-encrypt a buffer. private byte[] DoECB(byte[] input, SymmetricAlgorithm alg, byte[] key) { byte[] output = new byte [input.Length]; int size = alg.BlockSize / 8; Array.Copy(input, 0, output, 0, input.Length); int index = 0; while(index < input.Length) { ECBBlock(output, index, alg, key); index += size; } return output; } // CBC-encrypt a buffer. private byte[] DoCBC(byte[] input, SymmetricAlgorithm alg, byte[] key, byte[] _iv) { byte[] iv = new byte [_iv.Length]; Array.Copy(_iv, 0, iv, 0, _iv.Length); byte[] output = new byte [input.Length]; int size = alg.BlockSize / 8; Array.Copy(input, 0, output, 0, input.Length); int index = 0; while(index < input.Length) { XorBlock(output, index, iv, 0, alg); ECBBlock(output, index, alg, key); CopyBlock(output, index, iv, 0, alg); index += size; } return output; } // OFB-encrypt a buffer. private byte[] DoOFB(byte[] input, SymmetricAlgorithm alg, byte[] key, byte[] _iv) { byte[] iv = new byte [_iv.Length]; Array.Copy(_iv, 0, iv, 0, _iv.Length); byte[] output = new byte [input.Length]; Array.Copy(input, 0, output, 0, input.Length); int size = alg.BlockSize / 8; int index = 0; while(index < input.Length) { ECBBlock(iv, 0, alg, key); if((input.Length - index) >= size) { XorBlock(output, index, iv, 0, alg); } else { XorBlock(output, index, iv, 0, input.Length - index); } index += size; } return output; } // CFB-encrypt a buffer. private byte[] DoCFB(byte[] input, SymmetricAlgorithm alg, byte[] key, byte[] _iv) { byte[] iv = new byte [_iv.Length]; Array.Copy(_iv, 0, iv, 0, _iv.Length); byte[] output = new byte [input.Length]; Array.Copy(input, 0, output, 0, input.Length); int size = alg.BlockSize / 8; int index = 0; while(index < input.Length) { ECBBlock(iv, 0, alg, key); if((input.Length - index) >= size) { XorBlock(output, index, iv, 0, alg); CopyBlock(output, index, iv, 0, alg); } else { XorBlock(output, index, iv, 0, input.Length - index); } index += size; } return output; } // CTS-encrypt a buffer. private byte[] DoCTS(byte[] input, SymmetricAlgorithm alg, byte[] key, byte[] _iv) { if(input.Length < (alg.BlockSize / 8)) { // Streams shorter than one block are CFB-encrypted. return DoCFB(input, alg, key, _iv); } byte[] iv = new byte [_iv.Length]; Array.Copy(_iv, 0, iv, 0, _iv.Length); byte[] output = new byte [input.Length]; int size = alg.BlockSize / 8; Array.Copy(input, 0, output, 0, input.Length); int index = 0; int limit = input.Length; limit -= limit % size; limit -= size; // Encrypt the bulk of the input with CBC. while(index < limit) { XorBlock(output, index, iv, 0, alg); ECBBlock(output, index, alg, key); CopyBlock(output, index, iv, 0, alg); index += size; } // Encrypt the last two blocks using ciphertext stealing. byte[] last = new byte [size * 2]; Array.Copy(output, index, last, 0, input.Length - limit); XorBlock(last, 0, iv, 0, alg); ECBBlock(last, 0, alg, key); XorBlock(last, size, last, 0, alg); ECBBlock(last, size, alg, key); Array.Copy(last, size, output, index, size); Array.Copy(last, 0, output, index + size, input.Length % size); return output; } // Get a string that describes a particular cipher mode test, // for use in error messages. private static String GetError(String msg, SymmetricAlgorithm alg, String input) { return msg + String.Format (" ({0}, {1}, \"{2}\")", alg.Mode, alg.Padding, input); } // Run a cipher mode test. private void RunModeTest(SymmetricAlgorithm alg, CipherMode mode, PaddingMode padding, String input) { // Set the algorithm modes. alg.Mode = mode; alg.Padding = padding; // Get the raw and padded versions of the input. byte[] rawInput = Encoding.ASCII.GetBytes(input); byte[] paddedInput = StringToBytes(input, alg); // Generate key and IV values. byte[] key = CreateKey(alg); byte[] iv = CreateIV(alg); // Encrypt the raw input in the selected mode. int size = alg.BlockSize / 8; int cutoff = rawInput.Length - rawInput.Length % size; ICryptoTransform encryptor; encryptor = alg.CreateEncryptor(key, iv); Assert(GetError("encryptor cannot transform multiple blocks", alg, input), encryptor.CanTransformMultipleBlocks); if(mode == CipherMode.ECB || mode == CipherMode.CBC) { AssertEquals(GetError("encryptor has wrong input size", alg, input), size, encryptor.InputBlockSize); AssertEquals(GetError("encryptor has wrong output size", alg, input), size, encryptor.OutputBlockSize); } else { AssertEquals(GetError("encryptor has wrong input size", alg, input), 1, encryptor.InputBlockSize); AssertEquals(GetError("encryptor has wrong output size", alg, input), 1, encryptor.OutputBlockSize); } byte[] rawOutput = new byte [rawInput.Length + 256]; int len = encryptor.TransformBlock (rawInput, 0, cutoff, rawOutput, 0); byte[] rawTail = encryptor.TransformFinalBlock (rawInput, cutoff, rawInput.Length - cutoff); Array.Copy(rawTail, 0, rawOutput, len, rawTail.Length); len += rawTail.Length; ((IDisposable)encryptor).Dispose(); // Reverse the ciphertext back to the original. cutoff = len - len % size; ICryptoTransform decryptor; decryptor = alg.CreateDecryptor(key, iv); Assert(GetError("decryptor cannot transform multiple blocks", alg, input), decryptor.CanTransformMultipleBlocks); if(mode == CipherMode.ECB || mode == CipherMode.CBC) { AssertEquals(GetError("decryptor has wrong input size", alg, input), size, decryptor.InputBlockSize); AssertEquals(GetError("decryptor has wrong output size", alg, input), size, decryptor.OutputBlockSize); } else { AssertEquals(GetError("decryptor has wrong input size", alg, input), 1, decryptor.InputBlockSize); AssertEquals(GetError("decryptor has wrong output size", alg, input), 1, decryptor.OutputBlockSize); } byte[] rawReverse = new byte [rawInput.Length + 256]; int rlen = decryptor.TransformBlock (rawOutput, 0, cutoff, rawReverse, 0); rawTail = decryptor.TransformFinalBlock (rawOutput, cutoff, len - cutoff); Array.Copy(rawTail, 0, rawReverse, rlen, rawTail.Length); rlen += rawTail.Length; ((IDisposable)decryptor).Dispose(); // Compare the reversed plaintext with the original. if(padding != PaddingMode.None) { AssertEquals(GetError ("reversed plaintext has incorrect length", alg, input), rawInput.Length, rlen); if(!IdenticalBlock(rawInput, 0, rawReverse, 0, rlen)) { Fail(GetError ("reversed plaintext is not the same as original", alg, input)); } } else { if(rawInput.Length > rlen) { Fail(GetError ("reversed plaintext has incorrect length", alg, input)); } if(!IdenticalBlock(rawInput, 0, rawReverse, 0, rawInput.Length)) { Fail(GetError ("reversed plaintext is not the same as original", alg, input)); } } // Encrypt the padded plaintext using a primitive // algorithm simulation to verify the expected output. byte[] paddedOutput; switch(mode) { case CipherMode.ECB: { paddedOutput = DoECB(paddedInput, alg, key); } break; case CipherMode.CBC: { paddedOutput = DoCBC(paddedInput, alg, key, iv); } break; case CipherMode.OFB: { paddedOutput = DoOFB(paddedInput, alg, key, iv); } break; case CipherMode.CFB: { paddedOutput = DoCFB(paddedInput, alg, key, iv); } break; case CipherMode.CTS: default: { paddedOutput = DoCTS(paddedInput, alg, key, iv); } break; } // Compare the actual output with the expected output. AssertEquals(GetError("ciphertext has incorrect length", alg, input), paddedOutput.Length, len); if(!IdenticalBlock(paddedOutput, 0, rawOutput, 0, len)) { Fail(GetError("ciphertext was not the expected value", alg, input)); } } // Run a mode test using a number of different inputs and padding modes. protected void RunModeTest(SymmetricAlgorithm alg, CipherMode mode, PaddingMode padding) { RunModeTest(alg, mode, padding, ""); RunModeTest(alg, mode, padding, "abc"); RunModeTest(alg, mode, padding, "abcdefgh"); RunModeTest(alg, mode, padding, "abcdefghijk"); RunModeTest(alg, mode, padding, "abcdefghijklmno"); RunModeTest(alg, mode, padding, "The time has come the walrus said."); } protected void RunModeTest(SymmetricAlgorithm alg, CipherMode mode) { RunModeTest(alg, mode, PaddingMode.None); RunModeTest(alg, mode, PaddingMode.PKCS7); RunModeTest(alg, mode, PaddingMode.Zeros); }}; // CryptoTestCase#endif // CONFIG_CRYPTO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -