using System;
using System.Diagnostics;
using System.Reflection;
using System.IO;
using CryptoSysAPI;
/* $Id: TestAPIcsharp.cs $
* Last updated:
* $Date: 2018-09-16 13:31:00 $
* $Version: 5.3.0 $
*/
/* Some tests using the CryptoSysAPI .NET interface.
*
* Requires `CryptoSys API` to be installed on your system: available from <http://cryptosys.net/api.html>.
* Add a reference to `diCrSysAPINet.dll` installed in `C:\Program Files (x86)\CryptoSysAPI\DotNet`.
*
* This is a Console Application written for target .NET Framework 2.0 and above.
* Please report any bugs to <http://cryptosys.net/contact>.
*/
/******************************* LICENSE ***********************************
* Copyright (C) 2005-18 David Ireland, DI Management Services Pty Limited.
* All rights reserved. <https://di-mgt.com.au> <https://cryptosys.net>
* The code in this module is licensed under the terms of the MIT license.
* For a copy, see <http://opensource.org/licenses/MIT>
****************************************************************************
*/
/* [2015-04] Re-organised into modular form */
/* [2018-09] Changed license on this code to MIT */
namespace TestAPIExamples
{
/// <summary>
/// Test examples for CryptoSysAPI interface
/// </summary>
class TestAPIExamples
{
private const int MIN_API_VERSION = 50300;
// Global vars set by command-line args
private static bool doPrompt = false;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
string origdir; // To store CWD before changed to temp
// Make sure minimum required version of CryptoSys API is installed...
Console.WriteLine("API Version is " + General.Version());
if (General.Version() < MIN_API_VERSION)
{
Console.WriteLine("FATAL ERROR: Require API version " + MIN_API_VERSION + " or later.");
return;
}
/* HANDLE COMMAND-LINE ARGUMENTS
* [some] just do some tests (default = do all)
* [prompt] prompt for keystrokes and passwords
* [noask] do not ask to delete temp dir
*/
bool doSome = false;
bool askDelete = true;
// Global vars...
doPrompt = false;
for (int iarg = 0; iarg < args.Length; iarg++)
{
if (args[iarg] == "some")
doSome = true;
if (args[iarg] == "prompt")
doPrompt = true;
if (args[iarg] == "noask")
askDelete = false;
}
// Setup temp directory
origdir = SetupTestDirectory();
if (null == origdir) return;
//*************
// DO THE TESTS
//*************
if (doSome) // Use "some" in the command line
{ // Do some tests - comment these out as required
Console.WriteLine("Just doing some tests...");
//test_General();
//test_Convert();
//test_ErrorLookup();
//test_Blowfish();
//test_Des();
//test_Tdea();
//test_AES128();
//test_AES192();
//test_AES256();
//test_KeyWrap();
//test_SHA1();
//test_SHA256();
//test_MD5();
//test_Hash();
//test_HashBit();
//test_HMAC();
//test_CMAC();
//test_PBKDF2();
//test_scrypt();
//test_ZLIB();
//test_Random();
//test_Wipe();
//test_CRC();
//test_GCM();
//test_CipherFileExtended();
//test_CipherPad();
//test_StreamCipher();
//test_Poly1305();
//test_AEAD();
//test_AEAD_incremental();
//test_Padding();
//test_SHA3_obj();
//test_SHA3();
//test_KMAC();
test_XOF();
}
else
{ // Do all the test modules (default)
Console.WriteLine("Doing all tests...");
DoAllTests();
}
// FINALLY, DISPLAY QUICK INFO ABOUT THE CORE DLL
Console.WriteLine("\nDETAILS OF CORE DLL...");
Console.WriteLine("DLL Version={0} [{1}] Lic={2} Compiled=[{3}] ",
General.Version(), General.Platform(), General.LicenceType(), General.CompileTime());
Console.WriteLine("[{0}]", General.ModuleName());
//********************************************
Console.WriteLine("\nALL TESTS COMPLETED.");
// Put CWD back to original and offer to remove the test dir
RestoreDirectory(origdir, askDelete);
}
static void DoAllTests()
{ //%-
test_General();
test_Convert();
test_ErrorLookup();
test_Blowfish();
test_Des();
test_Tdea();
test_AES128();
test_AES192();
test_AES256();
test_KeyWrap();
test_SHA1();
test_SHA256();
test_MD5();
test_Hash();
test_HashBit();
test_HMAC();
test_CMAC();
test_PBKDF2();
test_scrypt();
test_ZLIB();
test_Random();
test_Wipe();
test_CRC();
test_GCM();
test_CipherFileExtended();
test_CipherPad();
test_StreamCipher();
test_Poly1305();
test_AEAD();
test_AEAD_incremental();
test_Padding();
test_SHA3_obj();
test_SHA3();
test_KMAC();
test_XOF();
}
//********************
// THE TEST MODULES...
//********************
static void test_General()
{
int n;
char ch;
string s;
//************
// GENERAL TESTS *
//****************
Console.WriteLine("\nGENERAL FUNCTIONS:");
n = General.Version();
Console.WriteLine("Version={0}", n);
n = General.PowerUpTests();
Console.WriteLine("PowerUpTests={0}", n);
s = General.CompileTime();
Console.WriteLine("CompileTime={0}", s);
s = General.ModuleName();
Console.WriteLine("ModuleName={0}", s);
n = General.IsWin64();
Console.WriteLine("IsWin64={0}", n);
s = General.Platform();
Console.WriteLine("Platform={0}", s);
ch = General.LicenceType();
Console.WriteLine("LicenceType={0}", ch);
}
static void test_Convert()
{
string s;
byte[] b;
string b64str;
//%+
//***************************
// HEXADECIMAL CONVERSION TESTS *
//*******************************
Console.WriteLine("\nHEX CONVERSION TESTS:");
b = Cnv.FromHex("deadbeef");
s = Cnv.ToHex(b);
Console.WriteLine("ToHex={0}", s);
s = Cnv.StringFromHex("616263");
Console.WriteLine("0x616263='{0}'", s);
//%+
//**********************
// BASE64 CONVERSION TESTS *
//**************************
Console.WriteLine("BASE64 CONVERSION TESTS:");
// 0xFEDCBA9876543210 in base64
b64str = "/ty6mHZUMhA=";
b = Cnv.FromBase64(b64str);
Console.WriteLine("'{0}'=0x{1}", b64str, Cnv.ToHex(b));
// Back to base64
s = Cnv.ToBase64(b);
Console.WriteLine("In base64='{0}'", s);
// Directly to hex
Console.WriteLine("In hex='{0}'", Cnv.HexFromBase64(b64str));
// hex -> base64
s = "FEDCBA9876543210";
b64str = Cnv.Base64FromHex(s);
Console.WriteLine("0x{0}='{1}'", s, b64str);
}
static void test_ErrorLookup()
{
string s;
//%+
//*****************
// ERROR LOOKUP TESTS *
//*********************
Console.WriteLine("\nERROR CODES:");
for (int i = 0; i < 10000; i++)
{
s = General.ErrorLookup(i);
if (!s.Equals(String.Empty))
Console.WriteLine("Error {0}={1}", i, s);
}
}
static void test_Blowfish()
{
string s;
int n;
byte[] b;
string okhex;
string keyStr, ivStr;
string ptStr, ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
byte[] arrOk;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
//****************************
// BLOWFISH ENCRYPTION TESTS *
//****************************
//%+
Console.WriteLine("\nTESTING BLOWFISH:");
keyStr = "FEDCBA9876543210";
ptStr = "0123456789ABCDEF";
ctStr = "0ACEAB0FC6A0A28D";
// Encrypt in ECB mode using hex strings
s = Blowfish.Encrypt(ptStr, keyStr, Mode.ECB, null);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Blowfish.Encrypt failed");
// Decrypt
s = Blowfish.Decrypt(ctStr, keyStr, Mode.ECB, null);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Blowfish.Decrypt failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
b = Blowfish.Encrypt(arrPlain, arrKey, Mode.ECB, null);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), ctStr, true) == 0, "Blowfish.Encrypt failed");
b = Blowfish.Decrypt(arrCipher, arrKey, Mode.ECB, null);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), ptStr, true) == 0, "Blowfish.Decrypt failed");
//%+
// Encrypt in CBC mode using hex strings
keyStr = "0123456789ABCDEFF0E1D2C3B4A59687";
ivStr = "FEDCBA9876543210";
ptStr = "37363534333231204E6F77206973207468652074696D6520666F722000000000";
ctStr = "6B77B4D63006DEE605B156E27403979358DEB9E7154616D959F1652BD5FF92CC";
s = Blowfish.Encrypt(ptStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Blowfish.Encrypt (CBC) failed");
// Decrypt
s = Blowfish.Decrypt(ctStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Blowfish.Decrypt (CBC) failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
arrIV = Cnv.FromHex(ivStr);
b = Blowfish.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), ctStr, true) == 0, "Blowfish.Encrypt (CBC) failed");
b = Blowfish.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), ptStr, true) == 0, "Blowfish.Decrypt (CBC) failed");
//%-
// And again using base64 strings
keyStr = "ASNFZ4mrze/w4dLDtKWWhw==";
ivStr = "/ty6mHZUMhA=";
ptStr = "NzY1NDMyMSBOb3cgaXMgdGhlIHRpbWUgZm9yIAAAAAA=";
ctStr = "a3e01jAG3uYFsVbidAOXk1jeuecVRhbZWfFlK9X/ksw=";
s = Blowfish.Encrypt(ptStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Blowfish.Encrypt (CBC-base64) failed");
// Decrypt
s = Blowfish.Decrypt(ctStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Blowfish.Decrypt (CBC-base64) failed");
//%-
// Pad some data ready for encryption - first in hex format
okhex = "ffffff";
s = okhex;
ptStr = Blowfish.Pad(s);
Console.WriteLine("Blowfish.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Blowfish.BlockSize * 2)) == 0, "Blowfish.Pad(hex) failed");
// and remove it
s = Blowfish.Unpad(ptStr);
Console.WriteLine("Blowfish.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Blowfish.Unpad(hex) failed");
// again padding an empty string
okhex = "";
s = okhex;
ptStr = Blowfish.Pad(s);
Console.WriteLine("Blowfish.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Blowfish.BlockSize * 2)) == 0, "Blowfish.Pad(hex) failed");
// and remove it
s = Blowfish.Unpad(ptStr);
Console.WriteLine("Blowfish.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Blowfish.Unpad(hex) failed");
// Pad using bytes
arrOk = Cnv.FromHex("ffffffffffffffff");
b = arrOk;
arrPlain = Blowfish.Pad(b);
Console.WriteLine("Blowfish.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
Debug.Assert((arrPlain.Length % Blowfish.BlockSize) == 0, "Blowfish.Pad(bytes) failed");
b = Blowfish.Unpad(arrPlain);
Console.WriteLine("Blowfish.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Blowfish.Unpad(bytes) failed");
//%+
// Now use Init-Update-Final
keyStr = "FEDCBA9876543210";
ivStr = "0123456789abcdef";
// Instantiate a new encryption object
Blowfish oBlf = Blowfish.Instance();
// Setup to encrypt in CBC mode
n = oBlf.InitEncrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oBlf.ErrCode == 0, "Blowfish.Initialize failed");
ptStr = "0101010101010101";
ctStr = "46733BCD9C72C5E3";
s = oBlf.Update(ptStr);
Console.WriteLine("PT1={0}", ptStr);
Console.WriteLine("CT1={0}", s);
Console.WriteLine("OK1={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Blowfish.Update failed");
// Line 2 using bytes
ptStr = "0202020202020202";
ctStr = "F434DA62B6869A06";
b = Cnv.FromHex(ptStr);
b = oBlf.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("PT2={0}", ptStr);
Console.WriteLine("CT2={0}", s);
Console.WriteLine("OK2={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Blowfish.Update failed");
// Lines 3 and 4 together using hex and a longer input
ptStr = "03030303030303030404040404040404";
ctStr = "2AE6DFE458559138DEEBF97D6F83A5F3";
s = oBlf.Update(ptStr);
Console.WriteLine("PT3={0}", ptStr);
Console.WriteLine("CT3={0}", s);
Console.WriteLine("OK3={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Blowfish.Update failed");
//%-
// Create a second object this time to decrypt
// NB You can only have one Instance at a time in the same thread
// So this just overwrites the previous one as a test
// TODO: perhaps return an error here to emphasise the point?
Blowfish oBlf2 = Blowfish.Instance();
n = oBlf2.InitDecrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oBlf2.ErrCode == 0, "Blowfish.Init failed");
ptStr = "0101010101010101";
ctStr = "46733BCD9C72C5E3";
s = oBlf2.Update(ctStr);
Console.WriteLine("CT1={0}", ctStr);
Console.WriteLine("PT1={0}", s);
Console.WriteLine("OK1={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Blowfish.Update failed");
// Line 2 using bytes
ptStr = "0202020202020202";
ctStr = "F434DA62B6869A06";
b = Cnv.FromHex(ctStr);
b = oBlf2.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("CT2={0}", ctStr);
Console.WriteLine("PT2={0}", s);
Console.WriteLine("OK2={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Blowfish.Update failed");
// Lines 3 and 4 using hex
ptStr = "03030303030303030404040404040404";
ctStr = "2AE6DFE458559138DEEBF97D6F83A5F3";
s = oBlf2.Update(ctStr);
Console.WriteLine("CT3={0}", ctStr);
Console.WriteLine("PT3={0}", s);
Console.WriteLine("OK3={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Blowfish.Update failed");
// Experiment with object methods
s = oBlf.ToString();
Console.WriteLine("oBlf.ToString()={0}", s);
Type ty = oBlf.GetType();
Console.WriteLine("oBlf.GetType()={0}", ty);
n = oBlf.GetHashCode();
Console.WriteLine("oBlf.GetHashCode()={0}", n);
n = oBlf2.GetHashCode();
Console.WriteLine("oBlf2.GetHashCode()={0}", n);
// Make sure keys are disposed of
oBlf.Dispose();
oBlf2.Dispose();
Console.WriteLine("Blf Objects disposed of.");
//%+
// Create a test text file
excontent = "This is some sample content.";
fnameData = "excontent.txt";
File.WriteAllText(fnameData, excontent);
// Encrypt a file
keyStr = "fedcba9876543210";
fnameEnc = "excontent.blf.enc.dat";
okhex = "D45B1B15FA7960E34D67F6366B5ECDD91E941467F21F5BE34A1F5A5158A8569C";
n = Blowfish.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
if (0 == n)
Console.WriteLine("Blowfish.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("Blowfish.File returned error code {0}", n);
Debug.Assert(0 == n, "Blowfish.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "Blowfish.FileEncrypt failed");
// Decrypt it using byte format of key instead of hex
fnameCheck = "excontent.blf.chk.txt";
b = Cnv.FromHex(keyStr);
n = Blowfish.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
if (0 == n)
{
Console.WriteLine("Blowfish.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent) == 0, "Decrypted file data does not match");
}
else
Console.WriteLine("Blowfish.File returned error code {0}", n);
Debug.Assert(0 == n, "Blowfish.File failed.");
}
static void test_Des()
{
string s;
int n;
byte[] b;
string okhex;
string keyStr, ivStr;
string ptStr, ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
byte[] arrOk;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
string keyHex;
//***************************
// DES ENCRYPTION TESTS *
//***************************
Console.WriteLine("\nTESTING DES:");
keyStr = "0123456789abcdef";
ptStr = "4e6f772069732074";
ctStr = "3fa40e8a984d4815";
// Encrypt in ECB mode using hex strings
s = Des.Encrypt(ptStr, keyStr, Mode.ECB, null);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Des.HexECB failed");
// Decrypt
s = Des.Decrypt(ctStr, keyStr, Mode.ECB, null);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Des.HexECB failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
b = Des.Encrypt(arrPlain, arrKey, Mode.ECB, null);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Des.Decrypt(arrCipher, arrKey, Mode.ECB, null);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
// Encrypt in CBC mode using hex strings
keyStr = "0123456789abcdef";
ivStr = "1234567890abcdef";
ptStr = "4e6f77206973207468652074696d6520666f7220616c6c20";
ctStr = "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6";
s = Des.Encrypt(ptStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Des.Encrypt{Hex,CBC} failed");
// Decrypt
s = Des.Decrypt(ctStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Des.Decrypt{Hex,CBC} failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
arrIV = Cnv.FromHex(ivStr);
b = Des.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Des.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b)) == 0, "Des.BytesCBC failed");
// And again using base64 strings
keyStr = "ASNFZ4mrze8=";
ivStr = "EjRWeJCrze8=";
ptStr = "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwg";
ctStr = "5cfN3ocr8nxD6TQAjDicD2g3iEmafAX2";
s = Des.Encrypt(ptStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Des.Encrypt{base64,CBC} failed");
// Decrypt
s = Des.Decrypt(ctStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Des.Decrypt{base64,CBC} failed");
// Pad some data ready for encryption - first in hex format
okhex = "ffffff";
s = okhex;
ptStr = Des.Pad(s);
Console.WriteLine("Des.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Des.BlockSize * 2)) == 0, "Des.Pad(hex) failed");
// and remove it
s = Des.Unpad(ptStr);
Console.WriteLine("Des.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Des.Unpad(hex) failed");
// Pad using bytes
arrOk = Cnv.FromHex("ffffffffffffffff");
b = arrOk;
arrPlain = Des.Pad(b);
Console.WriteLine("Des.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
Debug.Assert((arrPlain.Length % Des.BlockSize) == 0, "Des.Pad(bytes) failed");
b = Des.Unpad(arrPlain);
Console.WriteLine("Des.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Des.Unpad(bytes) failed");
// Now use Init-Update-Final
keyStr = "0123456789abcdef";
ivStr = "1234567890abcdef";
// Instantiate a new encryption object
Des oDes = Des.Instance();
n = oDes.InitEncrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oDes.ErrCode == 0, "Des.Initialize failed");
ptStr = "4e6f772069732074";
ctStr = "E5C7CDDE872BF27C";
s = oDes.Update(ptStr);
Console.WriteLine("PT1={0}", ptStr);
Console.WriteLine("CT1={0}", s);
Console.WriteLine("OK1={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Des.Update failed");
// Line 2 using bytes
ptStr = "68652074696d6520";
ctStr = "43E934008C389C0F";
b = Cnv.FromHex(ptStr);
b = oDes.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("PT2={0}", ptStr);
Console.WriteLine("CT2={0}", s);
Console.WriteLine("OK2={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Des.Update failed");
// Line 3 using hex
ptStr = "666f7220616c6c20";
ctStr = "683788499A7C05F6";
s = oDes.Update(ptStr);
Console.WriteLine("PT3={0}", ptStr);
Console.WriteLine("CT3={0}", s);
Console.WriteLine("OK3={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Des.Update failed");
n = oDes.InitDecrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oDes.ErrCode == 0, "Des.Initialize failed");
ptStr = "4e6f772069732074";
ctStr = "E5C7CDDE872BF27C";
s = oDes.Update(ctStr);
Console.WriteLine("CT1={0}", ctStr);
Console.WriteLine("PT1={0}", s);
Console.WriteLine("OK1={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Des.Update failed");
// Line 2 using bytes
ptStr = "68652074696d6520";
ctStr = "43E934008C389C0F";
b = Cnv.FromHex(ctStr);
b = oDes.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("CT2={0}", ctStr);
Console.WriteLine("PT2={0}", s);
Console.WriteLine("OK2={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Des.Update failed");
// Line 3 using hex
ptStr = "666f7220616c6c20";
ctStr = "683788499A7C05F6";
s = oDes.Update(ctStr);
Console.WriteLine("CT3={0}", ctStr);
Console.WriteLine("PT3={0}", s);
Console.WriteLine("OK3={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Des.Update failed");
// Make sure keys are disposed of
oDes.Dispose();
Console.WriteLine("Des Object disposed of.");
// Create a test text file
excontent = "This is some sample content.";
fnameData = "excontent.txt";
File.WriteAllText(fnameData, excontent);
// Encrypt a file
keyStr = "fedcba9876543210";
fnameEnc = "excontent.des.enc.dat";
okhex = "84D1604C0A33D9335F7EDB5C7ABE73F86B9C87F0639D45F2C8172C8AA976B247";
n = Des.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
if (0 == n)
Console.WriteLine("Des.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("Des.File returned error code {0}", n);
Debug.Assert(0 == n, "Des.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "Des.FileEncrypt failed");
// Decrypt it using byte format of key instead of hex
fnameCheck = "excontent.des.chk.txt";
b = Cnv.FromHex(keyStr);
n = Des.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
if (0 == n)
{
Console.WriteLine("Des.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent) == 0, "Decrypted file data does not match");
}
else
Console.WriteLine("Des.File returned error code {0}", n);
Debug.Assert(0 == n, "Des.File failed.");
// Check for a DES weak key (chances of finding in a random-generated key = nil)
Console.WriteLine("Test Des.CheckKey...");
keyHex = "0101010101010101"; // WEAK KEY
n = Des.CheckKey(keyHex);
Console.WriteLine("Des.CheckKey returned {0} for weak DES key {1} in hex format.", n, keyHex);
Debug.Assert(0 != n, "Des.CheckKey failed.");
// again for key in byte array form
arrKey = Cnv.FromHex(keyHex);
n = Des.CheckKey(arrKey);
Console.WriteLine("Des.CheckKey returned {0} for weak DES key {1} in byte format.", n, Cnv.ToHex(arrKey));
Debug.Assert(0 != n, "Des.CheckKey failed.");
keyHex = "0101010101010102"; // NOT QUITE WEAK KEY
n = Des.CheckKey(keyHex);
Console.WriteLine("Des.CheckKey returned {0} for OK DES key {1} in hex format.", n, keyHex);
Debug.Assert(0 == n, "Des.CheckKey failed.");
// again for key in byte array form
arrKey = Cnv.FromHex(keyHex);
n = Des.CheckKey(arrKey);
Console.WriteLine("Des.CheckKey returned {0} for OK DES key {1} in byte format.", n, Cnv.ToHex(arrKey));
Debug.Assert(0 == n, "Des.CheckKey failed.");
}
static void test_Tdea()
{
string s;
int n;
byte[] b;
string okhex;
string keyStr, ivStr;
string ptStr, ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
byte[] arrOk;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
string keyHex;
//*****************************************************
// TDEA (Triple DES, 3DES, DES-EDE3) ENCRYPTION TESTS *
//*****************************************************
Console.WriteLine("\nTESTING TRIPLE DES:");
keyStr = "010101010101010101010101010101010101010101010101";
ptStr = "8000000000000000";
ctStr = "95F8A5E5DD31D900";
// Encrypt in ECB mode using hex strings
s = Tdea.Encrypt(ptStr, keyStr, Mode.ECB, null);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Tdea.HexECB failed");
// Decrypt
s = Tdea.Decrypt(ctStr, keyStr, Mode.ECB, null);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Tdea.HexECB failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
b = Tdea.Encrypt(arrPlain, arrKey, Mode.ECB, null);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Tdea.Decrypt(arrCipher, arrKey, Mode.ECB, null);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
// Encrypt in CBC mode using hex strings
keyStr = "737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32";
ivStr = "B36B6BFB6231084E";
ptStr = "5468697320736F6D652073616D706520636F6E74656E742E0808080808080808";
ctStr = "d76fd1178fbd02f84231f5c1d2a2f74a4159482964f675248254223daf9af8e4";
s = Tdea.Encrypt(ptStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Tdea.Encrypt{Hex,CBC} failed");
// Decrypt
s = Tdea.Decrypt(ctStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Tdea.Decrypt{Hex,CBC} failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
arrIV = Cnv.FromHex(ivStr);
b = Tdea.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Tdea.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b)) == 0, "Tdea.BytesCBC failed");
// ditto using base64 data
keyStr = "c3x5HyXq0OBGKSVDUvfcYpHlyyaRetoy";
ivStr = "s2tr+2IxCE4=";
ptStr = "VGhpcyBzb21lIHNhbXBlIGNvbnRlbnQuCAgICAgICAg=";
ctStr = "12/RF4+9AvhCMfXB0qL3SkFZSClk9nUkglQiPa+a+OQ=";
s = Tdea.Encrypt(ptStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Tdea.Encrypt{Base64,CBC} failed");
// Decrypt
s = Tdea.Decrypt(ctStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Tdea.Decrypt{Base64,CBC} failed");
// Pad some data ready for encryption - first in hex format
okhex = "ffffff";
s = okhex;
ptStr = Tdea.Pad(s);
Console.WriteLine("Tdea.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Tdea.BlockSize * 2)) == 0, "Tdea.Pad(hex) failed");
// and remove it
s = Tdea.Unpad(ptStr);
Console.WriteLine("Tdea.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Tdea.Unpad(hex) failed");
// Pad using bytes
arrOk = Cnv.FromHex("ffffffffffffffff");
b = arrOk;
arrPlain = Tdea.Pad(b);
Console.WriteLine("Tdea.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
Debug.Assert((arrPlain.Length % Tdea.BlockSize) == 0, "Tdea.Pad(bytes) failed");
b = Tdea.Unpad(arrPlain);
Console.WriteLine("Tdea.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Tdea.Unpad(bytes) failed");
// Now use Init-Update-Final
keyStr = "0123456789abcdeffedcba987654321089abcdef01234567";
ivStr = "1234567890abcdef";
// Instantiate a new encryption object
Tdea oTdea = Tdea.Instance();
n = oTdea.InitEncrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oTdea.ErrCode == 0, "Tdea.Initialize failed");
ptStr = "4e6f772069732074";
ctStr = "204011f986e35647";
s = oTdea.Update(ptStr);
Console.WriteLine("PT1={0}", ptStr);
Console.WriteLine("CT1={0}", s);
Console.WriteLine("OK1={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Tdea.Update failed");
// Line 2 using bytes
ptStr = "68652074696d6520";
ctStr = "199e47af391620c5";
b = Cnv.FromHex(ptStr);
b = oTdea.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("PT2={0}", ptStr);
Console.WriteLine("CT2={0}", s);
Console.WriteLine("OK2={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Tdea.Update failed");
// Line 3 using hex
ptStr = "666f7220616c6c20";
ctStr = "bb9a5bcfc86db0bb";
s = oTdea.Update(ptStr);
Console.WriteLine("PT3={0}", ptStr);
Console.WriteLine("CT3={0}", s);
Console.WriteLine("OK3={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Tdea.Update failed");
// Now decrypt
n = oTdea.InitDecrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oTdea.ErrCode == 0, "Tdea.Initialize failed");
ptStr = "4e6f772069732074";
ctStr = "204011f986e35647";
s = oTdea.Update(ctStr);
Console.WriteLine("CT1={0}", ctStr);
Console.WriteLine("PT1={0}", s);
Console.WriteLine("OK1={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Tdea.Update failed");
// Line 2 using bytes
ptStr = "68652074696d6520";
ctStr = "199e47af391620c5";
b = Cnv.FromHex(ctStr);
b = oTdea.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("CT2={0}", ctStr);
Console.WriteLine("PT2={0}", s);
Console.WriteLine("OK2={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Tdea.Update failed");
// Line 3 using hex
ptStr = "666f7220616c6c20";
ctStr = "bb9a5bcfc86db0bb";
s = oTdea.Update(ctStr);
Console.WriteLine("CT3={0}", ctStr);
Console.WriteLine("PT3={0}", s);
Console.WriteLine("OK3={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Tdea.Update failed");
// Make sure keys are disposed of
oTdea.Dispose();
Console.WriteLine("Tdea Object disposed of.");
// Create a test text file
excontent = "This is some sample content.";
fnameData = "excontent.txt";
File.WriteAllText(fnameData, excontent);
// Encrypt a file
keyStr = "fedcba98765432100123456789abcdeffedcba9876543210";
fnameEnc = "excontent.tdea.enc.dat";
okhex = "DD1E1FA430AE6BE1D3B83245F7A5B17C4BF03688238778E95F2CCD05AF1A8F44";
n = Tdea.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
if (0 == n)
Console.WriteLine("Tdea.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("Tdea.File returned error code {0}", n);
Debug.Assert(0 == n, "Tdea.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "Tdea.FileEncrypt failed");
// Decrypt it using byte format of key instead of hex
fnameCheck = "excontent.tdea.chk.txt";
b = Cnv.FromHex(keyStr);
n = Tdea.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
if (0 == n)
{
Console.WriteLine("Tdea.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent) == 0, "Decrypted file data does not match");
}
else
Console.WriteLine("Tdea.File returned error code {0}", n);
Debug.Assert(0 == n, "Tdea.File failed.");
// Attempt to encrypt a file with key and IV of invalid length
Console.WriteLine("Expecting errors...");
arrIV = Cnv.FromHex("BADBAD"); // 3 bytes, expecting 8
// Good key, bad IV
n = Tdea.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV);
Console.WriteLine("Tdea.File returned error code {0} {1}", n, General.ErrorLookup(n));
arrKey = Cnv.FromHex("BADBADBADBAD"); // 6 bytes, expecting 24
// Bad key
n = Tdea.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.ECB, null);
Console.WriteLine("Tdea.File returned error code {0} {1}", n, General.ErrorLookup(n));
// Check for a TDEA weak key (chances of finding in a random-generated key = nil)
Console.WriteLine("Test Tdea.CheckKey...");
keyHex = "0101010101010101ffeeccddbbaa99887766554433221100"; // WEAK KEY
n = Tdea.CheckKey(keyHex);
Console.WriteLine("Tdea.CheckKey returned {0} for weak TDEA key {1} in hex format.", n, keyHex);
Debug.Assert(0 != n, "Tdea.CheckKey failed.");
// again for key in byte array form
arrKey = Cnv.FromHex(keyHex);
n = Tdea.CheckKey(arrKey);
Console.WriteLine("Tdea.CheckKey returned {0} for weak TDEA key {1} in byte format.", n, Cnv.ToHex(arrKey));
Debug.Assert(0 != n, "Tdea.CheckKey failed.");
keyHex = "0101010101010102ffeeccddbbaa99887766554433221100"; // NOT QUITE WEAK KEY
n = Tdea.CheckKey(keyHex);
Console.WriteLine("Tdea.CheckKey returned {0} for OK TDEA key {1} in hex format.", n, keyHex);
Debug.Assert(0 == n, "Tdea.CheckKey failed.");
// again for key in byte array form
arrKey = Cnv.FromHex(keyHex);
n = Tdea.CheckKey(arrKey);
Console.WriteLine("Tdea.CheckKey returned {0} for OK TDEA key {1} in byte format.", n, Cnv.ToHex(arrKey));
Debug.Assert(0 == n, "Tdea.CheckKey failed.");
}
static void test_AES128()
{
string s;
int n;
byte[] b;
string okhex;
string keyStr, ivStr;
string ptStr, ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
byte[] arrOk;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
//***************************
// AES-128 ENCRYPTION TESTS *
//***************************
Console.WriteLine("\nTESTING AES-128:");
keyStr = "000102030405060708090a0b0c0d0e0f";
ptStr = "00112233445566778899aabbccddeeff";
ctStr = "69c4e0d86a7b0430d8cdb78070b4c55a";
// Encrypt in ECB mode using hex strings
s = Aes128.Encrypt(ptStr, keyStr, Mode.ECB, null);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes128.HexECB failed");
// Decrypt
s = Aes128.Decrypt(ctStr, keyStr, Mode.ECB, null);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes128.HexECB failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
b = Aes128.Encrypt(arrPlain, arrKey, Mode.ECB, null);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Aes128.Decrypt(arrCipher, arrKey, Mode.ECB, null);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
// Encrypt in CBC mode using hex strings
keyStr = "56e47a38c5598974bc46903dba290349";
ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "c30e32ffedc0774e6aff6af0869f71aa"
+ "0f3af07a9a31a9c684db207eb0ef8e4e"
+ "35907aa632c3ffdf868bb7b29d3d46ad"
+ "83ce9f9a102ee99d49a53e87f4c3da55";
s = Aes128.Encrypt(ptStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
// Decrypt
s = Aes128.Decrypt(ctStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
arrIV = Cnv.FromHex(ivStr);
b = Aes128.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Aes128.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b)) == 0, "Aes128.BytesCBC failed");
// Ditto using base64 strings
keyStr = "VuR6OMVZiXS8RpA9uikDSQ==";
ivStr = "jOgu776g2jxEaZ7X21G32Q==";
ptStr = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/"
+ "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w==";
ctStr = "ww4y/+3Ad05q/2rwhp9xqg868HqaManGhNsgfrDvjk"
+ "41kHqmMsP/34aLt7KdPUatg86fmhAu6Z1JpT6H9MPaVQ==";
s = Aes128.Encrypt(ptStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
// Decrypt
s = Aes128.Decrypt(ctStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
// Pad some data ready for encryption - first in hex format
okhex = "ffffff";
s = okhex;
ptStr = Aes128.Pad(s);
Console.WriteLine("Aes128.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Aes128.BlockSize * 2)) == 0, "Aes128.Pad(hex) failed");
// and remove it
s = Aes128.Unpad(ptStr);
Console.WriteLine("Aes128.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Aes128.Unpad(hex) failed");
// again padding an empty string
okhex = "";
s = okhex;
ptStr = Aes128.Pad(s);
Console.WriteLine("Aes128.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Aes128.BlockSize * 2)) == 0, "Aes128.Pad(hex) failed");
// and remove it
s = Aes128.Unpad(ptStr);
Console.WriteLine("Aes128.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Aes128.Unpad(hex) failed");
// Pad using bytes
arrOk = Cnv.FromHex("ffffffffffffffff");
b = arrOk;
arrPlain = Aes128.Pad(b);
Console.WriteLine("Aes128.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
Debug.Assert((arrPlain.Length % Aes128.BlockSize) == 0, "Aes128.Pad(bytes) failed");
b = Aes128.Unpad(arrPlain);
Console.WriteLine("Aes128.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Aes128.Unpad(bytes) failed");
// Now use Init-Update-Final
keyStr = "56e47a38c5598974bc46903dba290349";
ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
// Instantiate a new encryption object
Aes128 oAes128 = Aes128.Instance();
n = oAes128.InitEncrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oAes128.ErrCode == 0, "Aes128.Initialize failed");
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
ctStr = "c30e32ffedc0774e6aff6af0869f71aa";
s = oAes128.Update(ptStr);
Console.WriteLine("PT1={0}", ptStr);
Console.WriteLine("CT1={0}", s);
Console.WriteLine("OK1={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes128.Update failed");
// Line 2 using bytes
ptStr = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
ctStr = "0f3af07a9a31a9c684db207eb0ef8e4e";
b = Cnv.FromHex(ptStr);
b = oAes128.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("PT2={0}", ptStr);
Console.WriteLine("CT2={0}", s);
Console.WriteLine("OK2={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes128.Update failed");
// Lines 3 and 4 using hex
ptStr = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "35907aa632c3ffdf868bb7b29d3d46ad83ce9f9a102ee99d49a53e87f4c3da55";
s = oAes128.Update(ptStr);
Console.WriteLine("PT3={0}", ptStr);
Console.WriteLine("CT3={0}", s);
Console.WriteLine("OK3={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes128.Update failed");
// Now decrypt using the same object
n = oAes128.InitDecrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oAes128.ErrCode == 0, "Aes128.Initialize failed");
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
ctStr = "c30e32ffedc0774e6aff6af0869f71aa";
s = oAes128.Update(ctStr);
Console.WriteLine("CT1={0}", ctStr);
Console.WriteLine("PT1={0}", s);
Console.WriteLine("OK1={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes128.Update failed");
// Line 2 using bytes
ptStr = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
ctStr = "0f3af07a9a31a9c684db207eb0ef8e4e";
b = Cnv.FromHex(ctStr);
b = oAes128.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("CT2={0}", ctStr);
Console.WriteLine("PT2={0}", s);
Console.WriteLine("OK2={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes128.Update failed");
// Lines 3 and 4 using hex
ptStr = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "35907aa632c3ffdf868bb7b29d3d46ad83ce9f9a102ee99d49a53e87f4c3da55";
s = oAes128.Update(ctStr);
Console.WriteLine("CT3={0}", ctStr);
Console.WriteLine("PT3={0}", s);
Console.WriteLine("OK3={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes128.Update failed");
// Make sure keys are disposed of
oAes128.Dispose();
Console.WriteLine("AES128 Objects disposed of.");
// Create a test text file
excontent = "This is some sample content.";
fnameData = "excontent.txt";
File.WriteAllText(fnameData, excontent);
// Encrypt a file
keyStr = "fedcba98765432100123456789abcdef";
fnameEnc = "excontent.aes128.enc.dat";
okhex = "DBBACBCC97FBFBE869079864B5077245FA9FD96992CFFF3F4387BD0ABC04EBCA";
n = Aes128.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
if (0 == n)
Console.WriteLine("Aes128.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("Aes128.File returned error code {0}", n);
Debug.Assert(0 == n, "Aes128.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "Aes128.FileEncrypt failed");
// Decrypt it using byte format of key instead of hex
fnameCheck = "excontent.aes128.chk.txt";
b = Cnv.FromHex(keyStr);
n = Aes128.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
if (0 == n)
{
Console.WriteLine("Aes128.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent) == 0, "Decrypted file data does not match");
}
else
Console.WriteLine("Aes128.File returned error code {0}", n);
Debug.Assert(0 == n, "Aes128.File failed.");
}
static void test_AES192()
{
string s;
int n;
byte[] b;
string okhex;
string keyStr, ivStr;
string ptStr, ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
byte[] arrOk;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
//***************************
// AES-192 ENCRYPTION TESTS *
//***************************
Console.WriteLine("\nTESTING AES-192:");
keyStr = "000102030405060708090a0b0c0d0e0f1011121314151617";
ptStr = "00112233445566778899aabbccddeeff";
ctStr = "dda97ca4864cdfe06eaf70a0ec0d7191";
// Encrypt in ECB mode using hex strings
s = Aes192.Encrypt(ptStr, keyStr, Mode.ECB, null);
Console.WriteLine("KY={0}",keyStr);
Console.WriteLine("PT={0}",ptStr);
Console.WriteLine("CT={0}",s);
Console.WriteLine("OK={0}",ctStr);
Debug.Assert(String.Compare(s, ctStr, true)==0, "Aes192.HexECB failed");
// Decrypt
s = Aes192.Decrypt(ctStr, keyStr, Mode.ECB, null);
Console.WriteLine("P'={0}",s);
Console.WriteLine("OK={0}",ptStr);
Debug.Assert(String.Compare(s, ptStr, true)==0, "Aes192.HexECB failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
b = Aes192.Encrypt(arrPlain, arrKey, Mode.ECB, null);
Console.WriteLine("CT={0}",Cnv.ToHex(b));
b = Aes192.Decrypt(arrCipher, arrKey, Mode.ECB, null);
Console.WriteLine("P'={0}",Cnv.ToHex(b));
// Encrypt in CBC mode using hex strings
keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b";
ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "738237036dfdde9dda3374fa182600c5"
+ "38d9187a0299725d0a7fdbe844d77578"
+ "1539e401b5597cbbfa836efd22d998d2"
+ "1605d8df340622417b911467b5e51a12";
s = Aes192.Encrypt(ptStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("KY={0}",keyStr);
Console.WriteLine("IV={0}",ivStr);
Console.WriteLine("PT={0}",ptStr);
Console.WriteLine("CT={0}",s);
Console.WriteLine("OK={0}",ctStr);
// Decrypt
s = Aes192.Decrypt(ctStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("P'={0}",s);
Console.WriteLine("OK={0}",ptStr);
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
arrIV = Cnv.FromHex(ivStr);
b = Aes192.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
Console.WriteLine("CT={0}",Cnv.ToHex(b));
b = Aes192.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
Console.WriteLine("P'={0}",Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b))==0, "Aes192.BytesCBC failed");
// Ditto using base64 strings
keyStr = "VuR6OMVZiXS8RpA9uikDSQapIUA2uKFb";
ivStr = "jOgu776g2jxEaZ7X21G32Q==";
ptStr = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/"
+ "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w==";
ctStr = "c4I3A2393p3aM3T6GCYAxTjZGHoCmXJdCn/b6"
+ "ETXdXgVOeQBtVl8u/qDbv0i2ZjSFgXY3zQGIkF7kRRnteUaEg==";
s = Aes192.Encrypt(ptStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("KY={0}",keyStr);
Console.WriteLine("IV={0}",ivStr);
Console.WriteLine("PT={0}",ptStr);
Console.WriteLine("CT={0}",s);
Console.WriteLine("OK={0}",ctStr);
// Decrypt
s = Aes192.Decrypt(ctStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("P'={0}",s);
Console.WriteLine("OK={0}",ptStr);
// Pad some data ready for encryption - first in hex format
okhex = "ffffff";
s = okhex;
ptStr = Aes192.Pad(s);
Console.WriteLine("Aes192.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Aes192.BlockSize * 2)) == 0, "Aes192.Pad(hex) failed");
// and remove it
s = Aes192.Unpad(ptStr);
Console.WriteLine("Aes192.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Aes192.Unpad(hex) failed");
// Pad using bytes
arrOk = Cnv.FromHex("ffffffffffffffff");
b = arrOk;
arrPlain = Aes192.Pad(b);
Console.WriteLine("Aes192.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
Debug.Assert((arrPlain.Length % Aes192.BlockSize) == 0, "Aes192.Pad(bytes) failed");
b = Aes192.Unpad(arrPlain);
Console.WriteLine("Aes192.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Aes192.Unpad(bytes) failed");
// Now use Init-Update-Final
keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b";
ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
// Instantiate a new encryption object
Aes192 oAes192 = Aes192.Instance();
n = oAes192.InitEncrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oAes192.ErrCode == 0, "Aes192.Initialize failed");
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
ctStr = "738237036dfdde9dda3374fa182600c5";
s = oAes192.Update(ptStr);
Console.WriteLine("PT1={0}", ptStr);
Console.WriteLine("CT1={0}", s);
Console.WriteLine("OK1={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true)==0, "Aes192.Update failed");
// Line 2 using bytes
ptStr = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
ctStr = "38d9187a0299725d0a7fdbe844d77578";
b = Cnv.FromHex(ptStr);
b = oAes192.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("PT2={0}", ptStr);
Console.WriteLine("CT2={0}", s);
Console.WriteLine("OK2={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true)==0, "Aes192.Update failed");
// Lines 3 and 4 using hex
ptStr = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "1539e401b5597cbbfa836efd22d998d21605d8df340622417b911467b5e51a12";
s = oAes192.Update(ptStr);
Console.WriteLine("PT3={0}", ptStr);
Console.WriteLine("CT3={0}", s);
Console.WriteLine("OK3={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true)==0, "Aes192.Update failed");
n = oAes192.InitDecrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oAes192.ErrCode == 0, "Aes192.Initialize failed");
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
ctStr = "738237036dfdde9dda3374fa182600c5";
s = oAes192.Update(ctStr);
Console.WriteLine("CT1={0}", ctStr);
Console.WriteLine("PT1={0}", s);
Console.WriteLine("OK1={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true)==0, "Aes192.Update failed");
// Line 2 using bytes
ptStr = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
ctStr = "38d9187a0299725d0a7fdbe844d77578";
b = Cnv.FromHex(ctStr);
b = oAes192.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("CT2={0}", ctStr);
Console.WriteLine("PT2={0}", s);
Console.WriteLine("OK2={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true)==0, "Aes192.Update failed");
// Lines 3 and 4 using hex
ptStr = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "1539e401b5597cbbfa836efd22d998d21605d8df340622417b911467b5e51a12";
s = oAes192.Update(ctStr);
Console.WriteLine("CT3={0}", ctStr);
Console.WriteLine("PT3={0}", s);
Console.WriteLine("OK3={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true)==0, "Aes192.Update failed");
// Make sure keys are disposed of
oAes192.Dispose();
Console.WriteLine("AES192 Objects disposed of.");
// Create a test text file
excontent = "This is some sample content.";
fnameData = "excontent.txt";
File.WriteAllText(fnameData, excontent);
// Encrypt a file
keyStr = "fedcba98765432100123456789abcdeffedcba9876543210";
fnameEnc = "excontent.aes192.enc.dat";
okhex = "37C94F74ADDC362FA16B2A16DE40B583296A25DB83136E2CD669351EFE61A6C0";
n = Aes192.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
if (0 == n)
Console.WriteLine("Aes192.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("Aes192.File returned error code {0}", n);
Debug.Assert(0 == n, "Aes192.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true)==0, "Aes192.FileEncrypt failed");
// Decrypt it using byte format of key instead of hex
fnameCheck = "excontent.aes192.chk.txt";
b = Cnv.FromHex(keyStr);
n = Aes192.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
if (0 == n)
{
Console.WriteLine("Aes192.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent)==0, "Decrypted file data does not match");
}
else
Console.WriteLine("Aes192.File returned error code {0}", n);
Debug.Assert(0 == n, "Aes192.File failed.");
}
static void test_AES256()
{
string s;
int n;
byte[] b;
string okhex;
string keyStr, ivStr;
string ptStr, ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
byte[] arrOk;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
//***************************
// AES-256 ENCRYPTION TESTS *
//***************************
Console.WriteLine("\nTESTING AES-256:");
keyStr = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
ptStr = "00112233445566778899aabbccddeeff";
ctStr = "8EA2B7CA516745BFEAFC49904B496089";
// Encrypt in ECB mode using hex strings
s = Aes256.Encrypt(ptStr, keyStr, Mode.ECB, null);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes256.HexECB failed");
// Decrypt
s = Aes256.Decrypt(ctStr, keyStr, Mode.ECB, null);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes256.HexECB failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
b = Aes256.Encrypt(arrPlain, arrKey, Mode.ECB, null);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Aes256.Decrypt(arrCipher, arrKey, Mode.ECB, null);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
// Encrypt in CBC mode using hex strings
keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b512e03d534120006";
ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "28409A2982BD2CF7CE343A7D43F6927F"
+ "DB9EC532BBA569EEC92E57A209C4FDBA"
+ "59ADBA05A5C854694DDC9F7991C01634"
+ "E72BEB4FE0236CB3B119A463891E346F";
s = Aes256.Encrypt(ptStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes256.Encrypt{Hex,CBC} failed");
// Decrypt
s = Aes256.Decrypt(ctStr, keyStr, Mode.CBC, ivStr);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes256.Decrypt{Hex,CBC} failed");
// Ditto using byte arrays
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
arrKey = Cnv.FromHex(keyStr);
arrIV = Cnv.FromHex(ivStr);
b = Aes256.Encrypt(arrPlain, arrKey, Mode.CBC, arrIV);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
b = Aes256.Decrypt(arrCipher, arrKey, Mode.CBC, arrIV);
Console.WriteLine("P'={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(arrPlain), Cnv.ToHex(b)) == 0, "Aes256.BytesCBC failed");
// Ditto using base64 strings
keyStr = "VuR6OMVZiXS8RpA9uikDSQapIUA2uKFbUS4D1TQSAAY=";
ivStr = "jOgu776g2jxEaZ7X21G32Q==";
ptStr = "oKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vr/"
+ "AwcLDxMXGx8jJysvMzc7P0NHS09TV1tfY2drb3N3e3w==";
ctStr = "KECaKYK9LPfONDp9Q/aSf9uexTK7pWnuyS5XognE/"
+ "bpZrboFpchUaU3cn3mRwBY05yvrT+AjbLOxGaRjiR40bw==";
s = Aes256.Encrypt(ptStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("IV={0}", ivStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
// Decrypt
s = Aes256.Decrypt(ctStr, keyStr, Mode.CBC, ivStr, EncodingBase.Base64);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
// Pad some data ready for encryption - first in hex format
okhex = "ffffff";
s = okhex;
ptStr = Aes256.Pad(s);
Console.WriteLine("Aes256.Pad('{0}')='{1}'", s, ptStr);
Debug.Assert((ptStr.Length % (Aes256.BlockSize * 2)) == 0, "Aes256.Pad(hex) failed");
// and remove it
s = Aes256.Unpad(ptStr);
Console.WriteLine("Aes256.Unpad('{0}')='{1}'", ptStr, s);
Debug.Assert(s == okhex, "Aes256.Unpad(hex) failed");
// Pad using bytes
arrOk = Cnv.FromHex("ffffffffffffffff");
b = arrOk;
arrPlain = Aes256.Pad(b);
Console.WriteLine("Aes256.Pad(0x{0})=0x{1}", Cnv.ToHex(b), Cnv.ToHex(arrPlain));
Debug.Assert((arrPlain.Length % Aes256.BlockSize) == 0, "Aes256.Pad(bytes) failed");
b = Aes256.Unpad(arrPlain);
Console.WriteLine("Aes256.Unpad(0x{0})=0x{1}", Cnv.ToHex(arrPlain), Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), Cnv.ToHex(arrOk)) == 0, "Aes256.Unpad(bytes) failed");
// Now use Init-Update-Final
keyStr = "56e47a38c5598974bc46903dba29034906a9214036b8a15b512e03d534120006";
ivStr = "8ce82eefbea0da3c44699ed7db51b7d9";
// Instantiate a new encryption object
Aes256 oAes256 = Aes256.Instance();
n = oAes256.InitEncrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oAes256.ErrCode == 0, "Aes256.Initialize failed");
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
ctStr = "28409A2982BD2CF7CE343A7D43F6927F";
s = oAes256.Update(ptStr);
Console.WriteLine("PT1={0}", ptStr);
Console.WriteLine("CT1={0}", s);
Console.WriteLine("OK1={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes256.Update failed");
// Line 2 using bytes
ptStr = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
ctStr = "DB9EC532BBA569EEC92E57A209C4FDBA";
b = Cnv.FromHex(ptStr);
b = oAes256.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("PT2={0}", ptStr);
Console.WriteLine("CT2={0}", s);
Console.WriteLine("OK2={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes256.Update failed");
// Lines 3 and 4 using hex
ptStr = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "59ADBA05A5C854694DDC9F7991C01634E72BEB4FE0236CB3B119A463891E346F";
s = oAes256.Update(ptStr);
Console.WriteLine("PT3={0}", ptStr);
Console.WriteLine("CT3={0}", s);
Console.WriteLine("OK3={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Aes256.Update failed");
n = oAes256.InitDecrypt(keyStr, Mode.CBC, ivStr);
Console.WriteLine("Initialize returns {0}", n);
Debug.Assert(oAes256.ErrCode == 0, "Aes256.Initialize failed");
ptStr = "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf";
ctStr = "28409A2982BD2CF7CE343A7D43F6927F";
s = oAes256.Update(ctStr);
Console.WriteLine("CT1={0}", ctStr);
Console.WriteLine("PT1={0}", s);
Console.WriteLine("OK1={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes256.Update failed");
// Line 2 using bytes
ptStr = "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf";
ctStr = "DB9EC532BBA569EEC92E57A209C4FDBA";
b = Cnv.FromHex(ctStr);
b = oAes256.Update(b);
s = Cnv.ToHex(b);
Console.WriteLine("CT2={0}", ctStr);
Console.WriteLine("PT2={0}", s);
Console.WriteLine("OK2={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes256.Update failed");
// Lines 3 and 4 using hex
ptStr = "c0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedf";
ctStr = "59ADBA05A5C854694DDC9F7991C01634E72BEB4FE0236CB3B119A463891E346F";
s = oAes256.Update(ctStr);
Console.WriteLine("CT3={0}", ctStr);
Console.WriteLine("PT3={0}", s);
Console.WriteLine("OK3={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Aes256.Update failed");
// Make sure keys are disposed of
oAes256.Dispose();
Console.WriteLine("AES256 Objects disposed of.");
// Create a test text file
excontent = "This is some sample content.";
fnameData = "excontent.txt";
File.WriteAllText(fnameData, excontent);
// Encrypt a file
keyStr = "fedcba98765432100123456789abcdeffedcba98765432100123456789abcdef";
fnameEnc = "excontent.aes256.enc.dat";
okhex = "7F94B5E5A76B747B9778FD20D033E804790E633D34F78C9194F799DD967996C4";
n = Aes256.FileEncrypt(fnameEnc, fnameData, keyStr, Mode.ECB, null);
if (0 == n)
Console.WriteLine("Aes256.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("Aes256.File returned error code {0}", n);
Debug.Assert(0 == n, "Aes256.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "Aes256.FileEncrypt failed");
// Decrypt it using byte format of key instead of hex
fnameCheck = "excontent.aes256.chk.txt";
b = Cnv.FromHex(keyStr);
n = Aes256.FileDecrypt(fnameCheck, fnameEnc, b, Mode.ECB, null);
if (0 == n)
{
Console.WriteLine("Aes256.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent) == 0, "Decrypted file data does not match");
}
else
Console.WriteLine("Aes256.File returned error code {0}", n);
Debug.Assert(0 == n, "Aes256.File failed.");
}
static void test_StreamCipher()
{
string s;
int n;
byte[] b;
string okhex;
string keyStr;
string ptStr, ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
//***********************
// STREAM CIPHER TESTS *
//***********************
Console.WriteLine("\nTESTING STREAM CIPHERS:");
Console.WriteLine("ARCFOUR (RC4, PC1):");
// Our original pseudonym for RC4 was PC1
// [v4.8] Pc1 methods now superseded by CipherStream.
keyStr = "0123456789abcdef";
ptStr = "0123456789abcdef";
ctStr = "75b7878099e0c596";
// convert to byte arrays
arrKey = Cnv.FromHex(keyStr);
arrPlain = Cnv.FromHex(ptStr);
arrCipher = Cnv.FromHex(ctStr);
// encrypt
b = Pc1.Encrypt(arrPlain, arrKey);
Console.WriteLine("PC1:");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("PT={0}", Cnv.ToHex(arrPlain));
s = Cnv.ToHex(b);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Pc1.Encrypt failed");
// decrypt by encrypting again
b = Pc1.Encrypt(b, arrKey);
s = Cnv.ToHex(b);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Pc1.Encrypt(2) failed");
// NEW in v4.8: Pc1 methods are superseded. Use CipherStream. methods instead
b = CipherStream.Bytes(arrPlain, arrKey, null, 0, CipherStream.Algorithm.Arcfour);
Console.WriteLine("ARCFOUR:");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("PT={0}", Cnv.ToHex(arrPlain));
s = Cnv.ToHex(b);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "CipherStream.Bytes failed");
// decrypt by encrypting again
b = CipherStream.Bytes(b, arrKey, null, 0, CipherStream.Algorithm.Arcfour);
s = Cnv.ToHex(b);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "CipherStream.Bytes(2) failed");
// Again using data directly in hex format
keyStr = "ef012345";
ptStr = "00000000000000000000";
ctStr = "d6a141a7ec3c38dfbd61";
s = Pc1.Encrypt(ptStr, keyStr);
Console.WriteLine("PC1:");
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "Pc1.Encrypt(Hex) failed");
// decrypt by encrypting again
s = Pc1.Encrypt(s, keyStr);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "Pc1.Encrypt(Hex, 2) failed");
s = CipherStream.Hex(ptStr, keyStr, "", 0, CipherStream.Algorithm.Arcfour);
Console.WriteLine("ARCFOUR:");
Console.WriteLine("KY={0}", keyStr);
Console.WriteLine("PT={0}", ptStr);
Console.WriteLine("CT={0}", s);
Console.WriteLine("OK={0}", ctStr);
Debug.Assert(String.Compare(s, ctStr, true) == 0, "CipherStream.Hex failed");
// decrypt by encrypting again
s = CipherStream.Hex(s, keyStr, "", 0, CipherStream.Algorithm.Arcfour);
Console.WriteLine("P'={0}", s);
Console.WriteLine("OK={0}", ptStr);
Debug.Assert(String.Compare(s, ptStr, true) == 0, "CipherStream.Hex(2) failed");
// Create a test text file
excontent = "This is some sample content.";
fnameData = "excontent.txt";
File.WriteAllText(fnameData, excontent);
// Encrypt a file
keyStr = "fedcba98765432100123456789abcdeffedcba98765432100123456789abcdef";
fnameEnc = "excontent.pc1.enc.dat";
okhex = "E61C8126AC8B830C32E5ECF1862BCD70778C42B7C130310206151AB1";
b = Cnv.FromHex(keyStr);
n = Pc1.File(fnameEnc, fnameData, b);
if (0 == n)
Console.WriteLine("Pc1.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("Pc1.File returned error code {0}", n);
Debug.Assert(0 == n, "Pc1.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "Pc1.FileEncrypt failed");
// Decrypt it by encrypting again
fnameCheck = "excontent.pc1.chk.txt";
b = Cnv.FromHex(keyStr);
n = Pc1.File(fnameCheck, fnameEnc, b);
if (0 == n)
{
Console.WriteLine("Pc1.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent) == 0, "Decrypted file data does not match");
}
else
Console.WriteLine("Pc1.File returned error code {0}", n);
Debug.Assert(0 == n, "Pc1.File failed.");
// DO WITH CipherStream.
fnameEnc = "excontent.rc4.enc.dat";
n = CipherStream.File(fnameEnc, fnameData, b, null, 0, CipherStream.Algorithm.Arcfour);
if (0 == n)
Console.WriteLine("CipherStream.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("CipherStream.File returned error code {0}", n);
Debug.Assert(0 == n, "CipherStream.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "CipherStream.File failed");
// Decrypt it by encrypting again
fnameCheck = "excontent.rc4.chk.txt";
b = Cnv.FromHex(keyStr);
n = CipherStream.File(fnameCheck, fnameEnc, b, null, 0, CipherStream.Algorithm.Arcfour);
if (0 == n)
{
Console.WriteLine("CipherStream.File decrypted to file '{0}'", fnameCheck);
// Show contents of file
s = File.ReadAllText(fnameCheck);
Debug.Assert(String.Compare(s, excontent) == 0, "Decrypted file data does not match");
}
else
Console.WriteLine("CipherStream.File returned error code {0}", n);
Debug.Assert(0 == n, "CipherStream.File failed.");
// Create a test text file (Ref: "ChaCha20 and Poly1305 for IETF protocols")
excontent = "Ladies and Gentlemen of the class of '99: If I could offer you only one tip for the future, sunscreen would be it.";
fnameData = "sunscreen.txt";
File.WriteAllText(fnameData, excontent);
fnameEnc = "sunscreen-chacha.dat";
okhex = "6E2E359A2568F98041BA0728DD0D6981E97E7AEC1D4360C20A27AFCCFD9FAE0BF91B65C5524733AB8F593DABCD62B3571639D624E65152AB8F530C359F0861D807CA0DBF500D6A6156A38E088A22B65E52BC514D16CCF806818CE91AB77937365AF90BBF74A35BE6B40B8EEDF2785E42874D";
// ENCRYPT WITH CHACHA20
Console.WriteLine("\nCHACHA20:");
arrKey = Cnv.FromHex("00:01:02:03:04:05:06:07:08:09:0a:0b:0c:0d:0e:0f:10:11:12:13:14:15:16:17:18:19:1a:1b:1c:1d:1e:1f");
arrIV = Cnv.FromHex("00:00:00:00:00:00:00:4a:00:00:00:00");
Console.WriteLine("Key = " + Cnv.ToHex(arrKey));
Console.WriteLine("Nonce = " + Cnv.ToHex(arrIV));
// Counter = 1
n = CipherStream.File(fnameEnc, fnameData, arrKey, arrIV, 1, CipherStream.Algorithm.Chacha20);
if (0 == n)
Console.WriteLine("CipherStream.File created encrypted file '{0}'", fnameEnc);
else
Console.WriteLine("CipherStream.File returned error code {0}", n);
Debug.Assert(0 == n, "CipherStream.File failed.");
// Check we got what we should
b = File.ReadAllBytes(fnameEnc);
Console.WriteLine("CT={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), okhex, true) == 0, "CipherStream.File failed");
// Stream cipher of 65-byte block
Console.WriteLine("\nSTREAM CIPHER 65-BYTE KEYSTREAM:");
// To generate a keystream of N bytes, encrypt input of N x zero bytes
arrPlain = new byte[65]; // All zeros
Console.WriteLine("ARCFOUR:");
// Ref: RFC6229. Test Vector 7, Key length: 256 bits.
arrKey = Cnv.FromHex("0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20");
okhex = "eaa6bd25880bf93d3f5d1e4ca2611d91cfa45c9f7e714b54bdfa80027cb14380";
Console.WriteLine("Key: " + Cnv.ToHex(arrKey));
Console.WriteLine("IV : " + "n/a");
b = CipherStream.Bytes(arrPlain, arrKey, null, 0, CipherStream.Algorithm.Arcfour);
Debug.Assert(b.Length == arrPlain.Length);
Console.WriteLine("Keystream:\n" + Cnv.ToHex(b));
// Check bytes we have test vector for
Debug.Assert(String.Compare(Cnv.ToHex(b).Substring(0, okhex.Length), okhex, true) == 0, "CipherStream.File failed");
Console.WriteLine("SALSA20:");
// Ref: `verified.test-vectors.txt` Set 3, vector# 0:
arrKey = Cnv.FromHex("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F");
arrIV = Cnv.FromHex("0000000000000000");
okhex = "B580F7671C76E5F7441AF87C146D6B513910DC8B4146EF1B3211CF12AF4A4B49E5C874B3EF4F85E7D7ED539FFEBA73EB73E0CCA74FBD306D8AA716C7783E89AF";
Console.WriteLine("Key: " + Cnv.ToHex(arrKey));
Console.WriteLine("IV : " + Cnv.ToHex(arrIV));
b = CipherStream.Bytes(arrPlain, arrKey, arrIV, 0, CipherStream.Algorithm.Salsa20);
Debug.Assert(b.Length == arrPlain.Length);
Console.WriteLine("Keystream:\n" + Cnv.ToHex(b));
// Check bytes we have test vector for
Debug.Assert(String.Compare(Cnv.ToHex(b).Substring(0, okhex.Length), okhex, true) == 0, "CipherStream.File failed");
Console.WriteLine("CHACHA20:");
// Ref: `draft-strombergson-chacha-test-vectors-02.txt` TC7: Sequence patterns in key and IV. Rounds: 20
arrKey = Cnv.FromHex("00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100");
arrIV = Cnv.FromHex("0f1e2d3c4b5a6978");
okhex = "9fadf409c00811d00431d67efbd88fba59218d5d6708b1d685863fabbb0e961eea480fd6fb532bfd494b2151015057423ab60a63fe4f55f7a212e2167ccab931fb";
Console.WriteLine("Key: " + Cnv.ToHex(arrKey));
Console.WriteLine("IV : " + Cnv.ToHex(arrIV));
b = CipherStream.Bytes(arrPlain, arrKey, arrIV, 0, CipherStream.Algorithm.Chacha20);
Debug.Assert(b.Length == arrPlain.Length);
Console.WriteLine("Keystream:\n" + Cnv.ToHex(b));
// Check bytes we have test vector for
Debug.Assert(String.Compare(Cnv.ToHex(b).Substring(0, okhex.Length), okhex, true) == 0, "CipherStream.File failed");
// USE INCREMENTAL METHODS
Console.WriteLine("CHACHA20 (incremental):");
arrKey = Cnv.FromHex("00112233445566778899aabbccddeeffffeeddccbbaa99887766554433221100");
arrIV = Cnv.FromHex("0f1e2d3c4b5a6978");
okhex = "9fadf409c00811d00431d67efbd88fba59218d5d6708b1d685863fabbb0e961eea480fd6fb532bfd494b2151015057423ab60a63fe4f55f7a212e2167ccab931fb";
CipherStream oCStream = CipherStream.Instance();
n = oCStream.Init(arrKey, arrIV, 0, CipherStream.Algorithm.Chacha20);
Console.WriteLine("oCStream.Init returns {0} (expecting 0)", n);
Debug.Assert(oCStream.ErrCode == 0, "oCStream.Init failed");
// Encrypt a 65-byte input of zeros in chunks of 1, 62 and 2 bytes
arrCipher = new byte[0]; // We'll build up the full ciphertext as we go, for a check
arrPlain = new byte[1];
b = oCStream.Update(arrPlain);
Console.WriteLine(Cnv.ToHex(b));
arrCipher = ByteArraysConcat(arrCipher, b);
arrPlain = new byte[62];
b = oCStream.Update(arrPlain);
Console.WriteLine(Cnv.ToHex(b));
arrCipher = ByteArraysConcat(arrCipher, b);
arrPlain = new byte[2];
b = oCStream.Update(arrPlain);
Console.WriteLine(Cnv.ToHex(b));
arrCipher = ByteArraysConcat(arrCipher, b);
Console.WriteLine(Cnv.ToHex(arrCipher));
Debug.Assert(String.Compare(Cnv.ToHex(arrCipher).Substring(0, okhex.Length), okhex, true) == 0, "CipherStream.Update failed");
// We are done with CipherStream object
oCStream.Dispose();
}
static void test_KeyWrap()
{
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] bcheck;
string strCheck;
// **************
// KEY WRAPPING
// **************
Console.WriteLine("\nKEY WRAPPING WITH BLOCK CIPHER:");
// Some test AES-128 key material data
Console.WriteLine("Using AES128-Wrap");
arrPlain = Cnv.FromHex("00112233 44556677 8899aabb ccddeeff");
Console.WriteLine("Key material={0}", Cnv.ToHex(arrPlain));
// Key Encryption Key
arrKey = Cnv.FromHex("c17a44e8 e28d7d64 81d1ddd5 0a3b8914");
Console.WriteLine("KEK ={0}", Cnv.ToHex(arrKey));
// Wrap with AES128-Wrap algorithm
arrCipher = Cipher.KeyWrap(arrPlain, arrKey, CipherAlgorithm.Aes128);
Debug.Assert(arrCipher.Length > 0, "Cipher.KeyWrap failed.");
Console.WriteLine("Wrapped Key ={0}", Cnv.ToHex(arrCipher));
// Compare to known test vector (AES wrap always gives the same result for the same input)
strCheck = "503D75C73630A7B02ECF51B9B29B907749310B77B0B2E054";
Debug.Assert(String.Compare(strCheck, Cnv.ToHex(arrCipher), true) == 0, "AES128-Wrap key material does not match test vector");
// Check we can unwrap it
bcheck = Cipher.KeyUnwrap(arrCipher, arrKey, CipherAlgorithm.Aes128);
Debug.Assert(arrCipher.Length > 0, "Cipher.KeyUnwrap failed.");
Console.WriteLine("Unwrapped ={0}", Cnv.ToHex(bcheck));
Debug.Assert(ByteArraysEqual(bcheck, arrPlain), "Unwrapped key is different.");
// Some test Triple DES key material data
Console.WriteLine("Using 3DES-Wrap");
arrPlain = Cnv.FromHex("84e7f2d8 78f89fcc cd2d5eba fc56daf7 3300f27e f771cd68");
Console.WriteLine("Key material={0}", Cnv.ToHex(arrPlain));
// Key Encryption Key
arrKey = Cnv.FromHex("8ad8274e 56f46773 8edd83d4 394e5e29 af7c4089 e4f8d9f4");
Console.WriteLine("KEK ={0}", Cnv.ToHex(arrKey));
// Wrap with 3DES-Wrap algorithm
arrCipher = Cipher.KeyWrap(arrPlain, arrKey, CipherAlgorithm.Tdea);
Debug.Assert(arrCipher.Length > 0, "Cipher.KeyWrap failed.");
Console.WriteLine("Wrapped Key ={0}", Cnv.ToHex(arrCipher));
// NOTE: We can't compare to known test vector because 3DES wrap gives a different result each time.
// Check we can unwrap it
bcheck = Cipher.KeyUnwrap(arrCipher, arrKey, CipherAlgorithm.Tdea);
Debug.Assert(arrCipher.Length > 0, "Cipher.KeyUnwrap failed.");
Console.WriteLine("Unwrapped ={0}", Cnv.ToHex(bcheck));
Debug.Assert(ByteArraysEqual(bcheck, arrPlain), "Unwrapped key is different.");
}
static void test_Padding()
{
string s;
int i;
byte[] b;
Padding[] arrPads = new Padding[] {
Padding.Default,
Padding.Pkcs5,
Padding.OneAndZeroes,
Padding.AnsiX923,
};
// *************************
// PADDING FOR BLOCK CIPHERS
// *************************
Console.WriteLine("\nPADDING FOR BLOCK CIPHERS:");
foreach (Padding padding in arrPads) {
Console.WriteLine("PADDING={0}", padding.ToString());
// 1. Pad a byte array of 5 bytes for Triple DES ECB/CBC mode
b = new byte[5] { 0xff, 0xff, 0xff, 0xff, 0xff };
Console.WriteLine("Input =0x{0}", Cnv.ToHex(b));
b = Cipher.Pad(b, CipherAlgorithm.Tdea, padding);
Console.WriteLine("Padded =0x{0}", Cnv.ToHex(b));
// Now strip the padding
b = Cipher.Unpad(b, CipherAlgorithm.Tdea, padding);
Console.WriteLine("Unpadded=0x{0}", Cnv.ToHex(b));
// 2. Pad a byte array of 18 bytes for AES ECB/CBC mode
b = new byte[18];
for (i = 0; i < b.Length; i++) {
b[i] = 0xFF;
}
Console.WriteLine("Input =0x{0}", Cnv.ToHex(b));
b = Cipher.Pad(b, CipherAlgorithm.Aes128, padding);
Console.WriteLine("Padded =0x{0}", Cnv.ToHex(b));
// Now strip the padding
b = Cipher.Unpad(b, CipherAlgorithm.Aes128, padding);
Console.WriteLine("Unpadded=0x{0}", Cnv.ToHex(b));
// 3. Pad an empty byte array for TDEA
b = new byte[0];
Console.WriteLine("Input =0x{0}", Cnv.ToHex(b));
b = Cipher.Pad(b, CipherAlgorithm.Tdea, padding);
Console.WriteLine("Padded =0x{0}", Cnv.ToHex(b));
// Now strip the padding
b = Cipher.Unpad(b, CipherAlgorithm.Tdea, padding);
Console.WriteLine("Unpadded=0x{0}", Cnv.ToHex(b));
// 4. Pad a hex string for AES
s = "ff";
Console.WriteLine("Input ='{0}'", s);
s = Cipher.Pad(s, CipherAlgorithm.Aes128, padding);
Console.WriteLine("Padded ='{0}'", s);
// Now strip the padding
s = Cipher.Unpad(s, CipherAlgorithm.Aes128, padding);
Console.WriteLine("Unpadded='{0}'", s);
// 5. Pad an empty hex string for AES
s = "";
Console.WriteLine("Input ='{0}'", s);
s = Cipher.Pad(s, CipherAlgorithm.Aes128, padding);
Console.WriteLine("Padded ='{0}'", s);
// Now strip the padding
s = Cipher.Unpad(s, CipherAlgorithm.Aes128, padding);
Console.WriteLine("Unpadded='{0}'", s);
}
}
static void test_SHA1()
{
string s;
int n;
byte[] b;
string okhex;
bool isok;
int i;
string fnameData;
byte[] a1000;
//**************************
// SHA-1 HASH DIGEST TESTS *
//**************************
Console.WriteLine("\nTESTING SHA-1:");
// Ansi string input
s = Sha1.HexHash("abc");
Console.WriteLine("Sha1('abc')={0}", s);
// Correct answers from FIPS-180-2
okhex = "a9993e364706816aba3e25717850c26c9cd0d89d";
Debug.Assert(String.Compare(okhex, s, true) == 0, "Sha1('abc') failed");
// byte data input, hex output
b = new byte[] { 0x61, 0x62, 0x63 };
s = Sha1.HexHash(b);
Console.WriteLine("Sha1('abc')={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "Sha1('abc') failed");
// byte data input, byte output
b = Sha1.BytesHash(b);
Console.WriteLine("Sha1('abc')={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(okhex, Cnv.ToHex(b), true) == 0, "Sha1('abc') failed");
// file input
fnameData = "abc.txt";
File.WriteAllText(fnameData, "abc");
s = Sha1.FileHexHash(fnameData);
Console.WriteLine("Sha1('abc')={0}", s);
// Get digest of core DLL file
// See http://cryptosys.net/integrity.html
fnameData = General.ModuleName();
s = Sha1.FileHexHash(fnameData);
Console.WriteLine("Sha1(DLL module)={0}", s);
// Instantiate a new object
Sha1 oSha1 = Sha1.Instance();
isok = oSha1.Init();
Console.WriteLine("oSha1.Init returned {0}", isok);
Debug.Assert(isok, "Sha1.Init failed");
n = oSha1.AddData("a");
n = oSha1.AddData("bc");
s = oSha1.HexDigest();
Console.WriteLine("Sha1('abc')={0}", s);
// Compute SHA1(one million repetitions of 'a')
oSha1.Init();
a1000 = new byte[1000];
for (i = 0; i < 1000; i++)
a1000[i] = 0x61; // 'a' in ascii form
for (i = 0; i < 1000; i++)
{
n = oSha1.AddData(a1000);
Debug.Assert(0 == n, "Sha1.Adddata failed");
}
s = oSha1.HexDigest();
Console.WriteLine("Sha1(1M x 'a')={0}", s);
okhex = "34aa973cd4c4daa4f61eeb2bdbad27316534016f";
Debug.Assert(String.Compare(okhex, s, true) == 0, "Sha1(1M x 'a') failed");
}
static void test_SHA256()
{
string s;
int n;
byte[] b;
string okhex;
bool isok;
int i;
string fnameData;
byte[] a1000;
//****************************
// SHA-256 HASH DIGEST TESTS *
//****************************
Console.WriteLine("\nTESTING SHA-256:");
// Ansi string input
s = Sha256.HexHash("abc");
Console.WriteLine("Sha256('abc')={0}", s);
// Correct answers from FIPS-180-2
okhex = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
Debug.Assert(String.Compare(okhex, s, true)==0, "Sha256('abc') failed");
// byte data input, hex output
b = new byte[] {0x61, 0x62, 0x63};
s = Sha256.HexHash(b);
Console.WriteLine("Sha256('abc')={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "Sha256('abc') failed");
// byte data input, byte output
b = Sha256.BytesHash(b);
Console.WriteLine("Sha256('abc')={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(Cnv.ToHex(b), s, true) == 0, "Sha256('abc') failed");
// file input
fnameData = "abc.txt";
File.WriteAllText(fnameData, "abc");
s = Sha256.FileHexHash(fnameData);
Console.WriteLine("Sha256('abc')={0}", s);
// Get digest of core DLL file
// See http://cryptosys.net/integrity.html
fnameData = General.ModuleName();
s = Sha256.FileHexHash(fnameData);
Console.WriteLine("Sha256(DLL module)={0}", s);
// Instantiate a new object
Sha256 oSha256 = Sha256.Instance();
isok = oSha256.Init();
Console.WriteLine("oSha256.Init returned {0}", isok);
Debug.Assert(isok, "Sha256.Init failed");
n = oSha256.AddData("a");
n = oSha256.AddData("bc");
s = oSha256.HexDigest();
Console.WriteLine("Sha256('abc')={0}", s);
// Compute SHA256(one million repetitions of 'a')
oSha256.Init();
a1000 = new byte[1000];
for (i = 0; i < 1000; i++)
a1000[i] = 0x61; // 'a' in ascii form
for (i = 0; i < 1000; i++)
{
n = oSha256.AddData(a1000);
Debug.Assert(0 == n, "Sha256.Adddata failed");
}
s = oSha256.HexDigest();
Console.WriteLine("Sha256(1M x 'a')={0}", s);
okhex = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
Debug.Assert(String.Compare(okhex, s, true)==0, "Sha256(1M x 'a') failed");
}
static void test_MD5()
{
string s;
int n;
byte[] b;
string okhex;
bool isok;
int i;
string fnameData;
byte[] a1000;
//************************
// MD5 HASH DIGEST TESTS *
//************************
Console.WriteLine("\nTESTING MD5:");
// Ansi string input
s = Md5.HexHash("abc");
Console.WriteLine("Md5('abc')={0}", s);
// Correct answers from RFC 1321
okhex = "900150983cd24fb0d6963f7d28e17f72";
Debug.Assert(String.Compare(okhex, s, true) == 0, "Md5('abc') failed");
// byte data input, hex output
b = new byte[] { 0x61, 0x62, 0x63 };
s = Md5.HexHash(b);
Console.WriteLine("Md5('abc')={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "Md5('abc') failed");
// byte data input, byte output
b = Md5.BytesHash(b);
Console.WriteLine("Md5('abc')={0}", Cnv.ToHex(b));
Debug.Assert(String.Compare(okhex, Cnv.ToHex(b), true) == 0, "Md5('abc') failed");
// file input
fnameData = "abc.txt";
File.WriteAllText(fnameData, "abc");
s = Md5.FileHexHash(fnameData);
Console.WriteLine("Md5('abc')={0}", s);
// Get digest of core DLL file
// See http://cryptosys.net/integrity.html
fnameData = General.ModuleName();
s = Md5.FileHexHash(fnameData);
Console.WriteLine("Md5(DLL module)={0}", s);
// Instantiate a new object
Md5 oMd5 = Md5.Instance();
isok = oMd5.Init();
Console.WriteLine("oMd5.Init returned {0}", isok);
Debug.Assert(isok, "Md5.Init failed");
n = oMd5.AddData("a");
n = oMd5.AddData("bc");
s = oMd5.HexDigest();
Console.WriteLine("Md5('abc')={0}", s);
// Compute MD5(one million repetitions of 'a')
oMd5.Init();
a1000 = new byte[1000];
for (i = 0; i < 1000; i++)
a1000[i] = 0x61; // 'a' in ascii form
for (i = 0; i < 1000; i++)
{
n = oMd5.AddData(a1000);
Debug.Assert(0 == n, "Md5.Adddata failed");
}
s = oMd5.HexDigest();
Console.WriteLine("Md5(1M x 'a')={0}", s);
okhex = "7707d6ae4e027c70eea2a935c2296f21";
Debug.Assert(String.Compare(okhex, s, true) == 0, "Md5(1M x 'a') failed");
}
static void test_Hash()
{
string s;
string fnameInput;
//*************
// HASH TESTS *
//*************
Console.WriteLine("HASH DIGEST TESTS:");
// Known test vectors for Hash('abc')
const string OK_MD5_ABC = "900150983cd24fb0d6963f7d28e17f72";
const string OK_MD2_ABC = "da853b0d3f88d99b30283a69e6ded6bb";
const string OK_SHA1_ABC = "a9993e364706816aba3e25717850c26c9cd0d89d";
const string OK_SHA256_ABC = "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad";
const string OK_SHA384_ABC = "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7";
const string OK_SHA512_ABC = "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f";
const string OK_SHA224_ABC = "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7";
const string OK_RMD160_ABC = "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc";
//----
s = Hash.HexFromString("abc", HashAlgorithm.Sha1);
Console.WriteLine("SHA-1('abc') ={0}", s);
Debug.Assert(String.Compare(OK_SHA1_ABC, s, true) == 0, "SHA-1('abc')");
s = Hash.HexFromString("abc", HashAlgorithm.Md5);
Console.WriteLine("MD5('abc') ={0}", s);
Debug.Assert(String.Compare(OK_MD5_ABC, s, true) == 0, "MD5('abc')");
s = Hash.HexFromString("abc", HashAlgorithm.Md2);
Console.WriteLine("MD2('abc') ={0}", s);
Debug.Assert(String.Compare(OK_MD2_ABC, s, true) == 0, "MD2('abc')");
s = Hash.HexFromString("abc", HashAlgorithm.Ripemd160);
Console.WriteLine("RIPEMD-160('abc') ={0}", s);
Debug.Assert(String.Compare(OK_RMD160_ABC, s, true) == 0, "RIPEMD-160('abc')");
s = Hash.HexFromString("abc", HashAlgorithm.Sha224);
Console.WriteLine("SHA-224('abc')=\n{0}", s);
Debug.Assert(String.Compare(OK_SHA224_ABC, s, true) == 0, "SHA-224('abc')");
s = Hash.HexFromString("abc", HashAlgorithm.Sha256);
Console.WriteLine("SHA-256('abc')=\n{0}", s);
Debug.Assert(String.Compare(OK_SHA256_ABC, s, true) == 0, "SHA-256('abc')");
s = Hash.HexFromString("abc", HashAlgorithm.Sha384);
Console.WriteLine("SHA-384('abc')=\n{0}", s);
Debug.Assert(String.Compare(OK_SHA384_ABC, s, true) == 0, "SHA-384('abc')");
s = Hash.HexFromString("abc", HashAlgorithm.Sha512);
Console.WriteLine("SHA-512('abc')=\n{0}", s);
Debug.Assert(String.Compare(OK_SHA512_ABC, s, true) == 0, "SHA-512('abc')");
// Hex input
s = Hash.HexFromHex("616263", HashAlgorithm.Sha1);
Console.WriteLine("SHA-1(0x616263) ={0}", s);
Debug.Assert(String.Compare(OK_SHA1_ABC, s, true) == 0, "SHA-1(0x616263)");
s = Hash.HexFromHex("616263", HashAlgorithm.Sha512);
Console.WriteLine("SHA-512(0x616263)=\n{0}", s);
Debug.Assert(String.Compare(OK_SHA512_ABC, s, true) == 0, "SHA-512(0x616263)");
// Create a test file
fnameInput = "hello.txt";
File.WriteAllText(fnameInput, "hello world\r\n");
// get digest from binary file
s = Hash.HexFromFile(fnameInput, HashAlgorithm.Sha1);
Console.WriteLine("SHA1('hello world+CR+LF')={0}", s);
// and again treating CR-LF as a single LF
// (we use this when moving between Unix and Windows systems)
s = Hash.HexFromTextFile(fnameInput, HashAlgorithm.Sha1);
Console.WriteLine("SHA1('hello world+LF')= {0}", s);
}
static void test_HashBit()
{
string s;
int nbitlen;
byte[] msg;
string msgHex;
//**************************
// BIT-ORIENTED HASH TESTS *
//**************************
// New in v4.6
Console.WriteLine("\nBIT-ORIENTED HASH TESTS:");
nbitlen = 9;
msgHex = "5180";
msg = Cnv.FromHex(msgHex);
Console.WriteLine("[SHA-1]");
Console.WriteLine("[L = {0}]", Hash.LengthInBytes(HashAlgorithm.Sha1));
Console.WriteLine("Len = {0}", nbitlen);
Console.WriteLine("Msg = {0}", Cnv.ToHex(msg));
s = Hash.HexFromBits(msg, nbitlen, HashAlgorithm.Sha1);
Console.WriteLine("MD = {0}", s);
Debug.Assert(String.Compare("0f582fa68b71ecdf1dcfc4946019cf5a18225bd2", s, true) == 0, "Hash.HexFromBits failed");
}
static void test_HMAC()
{
string s;
byte[] b;
int i;
byte[] arrKey;
byte[] msg;
string strCheck;
//*************
// HMAC TESTS *
//*************
Console.WriteLine("\nHMAC TESTS:");
// Test case 2 from RFC 2202 and RFC 4231
// key = "Jefe"
// key_len 4
// data = "what do ya want for nothing?"
// data_len = 28
Console.WriteLine("Test case 2 from RFC 2202 and RFC 4231...");
// Convert strings to byte arrays
arrKey = System.Text.Encoding.Default.GetBytes("Jefe");
msg = System.Text.Encoding.Default.GetBytes("what do ya want for nothing?");
// Compute HMAC-SHA-1 then check against known test vector
s = Mac.HexFromBytes(msg, arrKey, MacAlgorithm.HmacSha1);
Console.WriteLine("HMAC-SHA-1('WDYWFN?','Jefe')={0}", s);
strCheck = "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79";
Console.WriteLine("CORRECT= {0}", strCheck);
Debug.Assert(String.Compare(strCheck, s, true)==0, "HMAC does not match test vector");
// Compute HMAC-SHA-256 then check against known test vector
s = Mac.HexFromBytes(msg, arrKey, MacAlgorithm.HmacSha256);
Console.WriteLine("HMAC-SHA-256('WDYWFN?','Jefe')=\n{0}", s);
strCheck = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, s, true)==0, "HMAC does not match test vector");
// Test case 4 from RFC 2202 and RFC 4231
// key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819
// key_len 25
// data = 0xcd repeated 50 times
// data_len = 50
Console.WriteLine("Test case 4 from RFC 2202 and RFC 4231...");
arrKey = new byte[25];
for (i = 0; i < 25; i++)
arrKey[i] = (byte)(i+1);
Console.WriteLine("Key={0}", Cnv.ToHex(arrKey));
msg = new byte[50];
for (i = 0; i < 50; i++)
msg[i] = 0xcd;
Console.WriteLine("Msg={0}", Cnv.ToHex(msg));
// Output in byte format
// Compute HMAC-SHA-1 then check against known test vector
b = Mac.BytesFromBytes(msg, arrKey, MacAlgorithm.HmacSha1);
Console.WriteLine("HMAC-SHA-1(50(0xcd), 0x0102..19)={0}", Cnv.ToHex(b));
strCheck = "4c9007f4026250c6bc8414f9bf50c86c2d7235da";
Console.WriteLine("CORRECT= {0}", strCheck);
Debug.Assert(String.Compare(strCheck, Cnv.ToHex(b), true)==0, "HMAC does not match test vector");
// Compute HMAC-SHA-224 then check against known test vector
b = Mac.BytesFromBytes(msg, arrKey, MacAlgorithm.HmacSha224);
Console.WriteLine("HMAC-SHA-224(50(0xcd), 0x0102..19)=\n{0}", Cnv.ToHex(b));
strCheck = "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, Cnv.ToHex(b), true) == 0, "HMAC does not match test vector");
// Compute HMAC-SHA-256 then check against known test vector
b = Mac.BytesFromBytes(msg, arrKey, MacAlgorithm.HmacSha256);
Console.WriteLine("HMAC-SHA-256(50(0xcd), 0x0102..19)=\n{0}", Cnv.ToHex(b));
strCheck = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, Cnv.ToHex(b), true)==0, "HMAC does not match test vector");
// Compute HMAC-SHA-512 then check against known test vector
b = Mac.BytesFromBytes(msg, arrKey, MacAlgorithm.HmacSha512);
Console.WriteLine("HMAC-SHA-512(50(0xcd), 0x0102..19)=\n{0}", Cnv.ToHex(b));
strCheck = "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, Cnv.ToHex(b), true) == 0, "HMAC does not match test vector");
// Compute HMAC-RIPEMD-160 then check against known test vector (RFC2286)
b = Mac.BytesFromBytes(msg, arrKey, MacAlgorithm.HmacRipemd160);
Console.WriteLine("HMAC-RIPEMD-160(50(0xcd), 0x0102..19)=\n{0}", Cnv.ToHex(b));
strCheck = "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, Cnv.ToHex(b), true) == 0, "HMAC does not match test vector");
}
static void test_CMAC()
{
string s;
string strCheck;
string keyHex;
string msgHex;
//*************
// CMAC TESTS *
//*************
Console.WriteLine("\nCMAC TESTS:");
Console.WriteLine("Test cases from SP800-38B...");
keyHex = "2b7e151628aed2a6abf7158809cf4f3c";
// CMAC-AES-128 on the empty string
msgHex = "";
s = Mac.HexFromHex(msgHex, keyHex, MacAlgorithm.CmacAes128);
Console.WriteLine("CMAC-AES-128(K128, '')=\n{0}", s);
strCheck = "bb1d6929e95937287fa37d129b756746";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, s, true) == 0, "CMAC does not match test vector");
msgHex = "6bc1bee22e409f96e93d7e117393172a";
s = Mac.HexFromHex(msgHex, keyHex, MacAlgorithm.CmacAes128);
Console.WriteLine("CMAC-AES-128(K128, M128)=\n{0}", s);
strCheck = "070a16b46b4d4144f79bdd9dd04a287c";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, s, true) == 0, "CMAC does not match test vector");
/* CMAC_AES-256 on Example 12: Mlen = 512 */
keyHex = "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4";
msgHex = "6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51" +
"30c81c46a35ce411e5fbc1191a0a52ef" +
"f69f2445df4f9b17ad2b417be66c3710";
s = Mac.HexFromHex(msgHex, keyHex, MacAlgorithm.CmacAes256);
Console.WriteLine("CMAC-AES-256(K256, M512)=\n{0}", s);
strCheck = "e1992190549f6ed5696a2c056c315410";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, s, true) == 0, "CMAC does not match test vector");
/* CMAC_TDEA on Example 16: Mlen = 256 */
keyHex = "8aa83bf8cbda10620bc1bf19fbb6cd58bc313d4a371ca8b5";
msgHex = "6bc1bee22e409f96e93d7e117393172a" +
"ae2d8a571e03ac9c9eb76fac45af8e51";
s = Mac.HexFromHex(msgHex, keyHex, MacAlgorithm.CmacTdea);
Console.WriteLine("CMAC-DES-EDE(K192, M256)=\n{0}", s);
strCheck = "33e6b1092400eae5";
Console.WriteLine("CORRECT=\n{0}", strCheck);
Debug.Assert(String.Compare(strCheck, s, true) == 0, "CMAC does not match test vector");
}
static void test_PBKDF2()
{
int n;
string keyStr;
string saltHex;
byte[] arrKey;
byte[] salt;
byte[] arrPwd;
string strCheck;
//***************
// PBKDF2 TESTS *
//***************
Console.WriteLine("\nTESTING PBKDF2...");
// convert password string to bytes
arrPwd = System.Text.Encoding.Default.GetBytes("password");
// make a salt
salt = new byte[] { 0x78, 0x57, 0x8e, 0x5a, 0x5d, 0x63, 0xcb, 0x06 };
// create a 24-byte (192-bit) key
n = 24;
arrKey = Pbe.Kdf2(n, arrPwd, salt, 2048);
Debug.Assert(arrKey.Length > 0, "ERROR with Pbe.Kdf2");
Console.WriteLine("Key({0})={1}", n * 8, Cnv.ToHex(arrKey));
// and again for a 64-byte (512-bit) key
n = 64;
arrKey = Pbe.Kdf2(n, arrPwd, salt, 2048);
Debug.Assert(arrKey.Length > 0, "ERROR with Pbe.Kdf2");
Console.WriteLine("Key({0})={1}", n * 8, Cnv.ToHex(arrKey));
// Same example using hex format
saltHex = "78578e5a5d63cb06";
n = 24;
strCheck = "BFDE6BE94DF7E11DD409BCE20A0255EC327CB936FFE93643";
keyStr = Pbe.Kdf2(n, "password", saltHex, 2048);
Debug.Assert(keyStr.Length > 0, "ERROR with PbeKdf2/Hex");
Console.WriteLine("Key({0})={1}", n * 8, keyStr);
// Compare with known test vector
Debug.Assert(String.Compare(strCheck, keyStr, true) == 0, "PBKDF Derived key {HMAC-SHA-1} does not match test vector");
// Use different hash function (SHA-256) in KDF
Console.WriteLine("Using SHA-256 in KDF...");
n = 24;
arrKey = Pbe.Kdf2(n, arrPwd, salt, 2048, HashAlgorithm.Sha256);
Debug.Assert(arrKey.Length > 0, "ERROR with Pbe.Kdf2");
Console.WriteLine("Key({0})={1}", n * 8, Cnv.ToHex(arrKey));
// using hex format
saltHex = "78578e5a5d63cb06";
n = 24;
strCheck = "97B5A91D35AF542324881315C4F849E327C4707D1BC9D322";
keyStr = Pbe.Kdf2(n, "password", saltHex, 2048, HashAlgorithm.Sha256);
Debug.Assert(keyStr.Length > 0, "ERROR with PbeKdf2/Hex");
Console.WriteLine("Key({0})={1}", n * 8, keyStr);
// Compare with known test vector
Debug.Assert(String.Compare(strCheck, keyStr, true) == 0, "PBKDF Derived key {HMAC-SHA-256} does not match test vector");
// And again using SHA-224 in KDF
Console.WriteLine("Using SHA-224 in KDF...");
n = 24;
arrKey = Pbe.Kdf2(n, arrPwd, salt, 2048, HashAlgorithm.Sha224);
Debug.Assert(arrKey.Length > 0, "ERROR with Pbe.Kdf2");
Console.WriteLine("Key({0})={1}", n * 8, Cnv.ToHex(arrKey));
// using hex format
saltHex = "78578e5a5d63cb06";
n = 24;
strCheck = "10CFFEDFB13503519969151E466F587028E0720B387F9AEF";
keyStr = Pbe.Kdf2(n, "password", saltHex, 2048, HashAlgorithm.Sha224);
Debug.Assert(keyStr.Length > 0, "ERROR with PbeKdf2/Hex");
Console.WriteLine("Key({0})={1}", n * 8, keyStr);
// Compare with known test vector
Debug.Assert(String.Compare(strCheck, keyStr, true) == 0, "PBKDF Derived key {HMAC-SHA-224} does not match test vector");
}
static void test_scrypt()
{
int dkLen;
byte[] key;
byte[] salt;
byte[] pwd;
string checkHex;
int N, r, p;
string P, S;
string keyHex, saltHex;
//***************
// SCRYPT TESTS *
//***************
Console.WriteLine("\nTESTING SCRYPT...");
// Test vectors from [RFC7914]
// scrypt (P="password", S="NaCl", N=1024, r=8, p=16, dkLen=64)
P = "password";
S = "NaCl";
N = 1024;
r = 8;
p = 16;
dkLen = 64;
// Convert password and salt strings to bytes
pwd = System.Text.Encoding.Default.GetBytes(P);
salt = System.Text.Encoding.Default.GetBytes(S);
checkHex = "FDBABE1C9D3472007856E7190D01E9FE7C6AD7CBC8237830E77376634B3731622EAF30D92E22A3886FF109279D9830DAC727AFB94A83EE6D8360CBDFA2CC0640";
key = Pbe.Scrypt(dkLen, pwd, salt, N, r, p);
Debug.Assert(key.Length > 0, "ERROR with Pbe.Scrypt");
Console.WriteLine("scrypt(P='{0}',S='{1}',N={2},r={3},p={4})=\n{5}", P, S, N, r, p, Cnv.ToHex(key));
// Compare with known test vector
Debug.Assert(String.Compare(checkHex, Cnv.ToHex(key), true) == 0, "SCRYPT derived key does not match test vector");
// scrypt (P="", S="", N=16, r=1, p=1, dkLen=64)
P = "";
S = "";
N = 16;
r = 1;
p = 1;
dkLen = 64;
// Convert password and salt strings to bytes
pwd = System.Text.Encoding.Default.GetBytes(P);
salt = System.Text.Encoding.Default.GetBytes(S);
checkHex = "77D6576238657B203B19CA42C18A0497F16B4844E3074AE8DFDFFA3FEDE21442FCD0069DED0948F8326A753A0FC81F17E8D3E0FB2E0D3628CF35E20C38D18906";
key = Pbe.Scrypt(dkLen, pwd, salt, N, r, p);
Debug.Assert(key.Length > 0, "ERROR with Pbe.Scrypt");
Console.WriteLine("scrypt(P='{0}',S='{1}',N={2},r={3},p={4})=\n{5}", P, S, N, r, p, Cnv.ToHex(key));
// Compare with known test vector
Debug.Assert(String.Compare(checkHex, Cnv.ToHex(key), true) == 0, "SCRYPT derived key does not match test vector");
// Work with hex salt and key but plaintext password
keyHex = Pbe.Scrypt(64, "password", "4E61436C", 1024, 8, 16);
Console.WriteLine("scrypt='{0}'", keyHex);
checkHex = "FDBABE1C9D3472007856E7190D01E9FE7C6AD7CBC8237830E77376634B3731622EAF30D92E22A3886FF109279D9830DAC727AFB94A83EE6D8360CBDFA2CC0640";
Debug.Assert(String.Compare(checkHex, keyHex, true) == 0, "SCRYPT derived key does not match test vector");
// scrypt (P="pleaseletmein", S="SodiumChloride", N=16384, r=8, p=1, dkLen=64)
P = "pleaseletmein";
saltHex = Cnv.ToHex("SodiumChloride");
N = 16384;
r = 8;
p = 1;
dkLen = 64;
keyHex = Pbe.Scrypt(dkLen, P, saltHex, N, r, p);
Console.WriteLine("scrypt(P='{0}',S='{1}',N={2},r={3},p={4})=\n{5}", P, Cnv.StringFromHex(saltHex), N, r, p, keyHex);
checkHex = "7023BDCB3AFD7348461C06CD81FD38EBFDA8FBBA904F8E3EA9B543F6545DA1F2D5432955613F0FCF62D49705242A9AF9E61E85DC0D651E40DFCF017B45575887";
Debug.Assert(String.Compare(checkHex, keyHex, true) == 0, "SCRYPT derived key does not match test vector");
}
static void test_ZLIB()
{
string s;
int n;
byte[] b;
string excontent;
//*************************
// ZLIB COMPRESSION TESTS *
//*************************
Console.WriteLine("\nTESTING ZLIB COMPRESSION...");
// Some sample text to compress
excontent = "hello, hello, hello. This is a 'hello world' message for the world, repeat, for the world.";
// Convert to bytes
b = System.Text.Encoding.Default.GetBytes(excontent);
// Remember uncompressed len for later
n = b.Length;
// Compress
b = Zlib.Deflate(b);
Debug.Assert(b.Length > 0, "ERROR with Zlib.Deflate");
Console.WriteLine("Compressed {0} to {1} bytes", n, b.Length);
Console.WriteLine("DEFL={0}", Cnv.ToHex(b));
// Now inflate back (note we need the original uncompressed length here)
b = Zlib.Inflate(b, n);
Debug.Assert(b.Length > 0, "ERROR with Zlib.Deflate");
s = System.Text.ASCIIEncoding.Default.GetString(b);
Console.WriteLine("INFL={0}", s);
}
static void test_Random()
{
string s;
int n;
byte[] b;
string filename, fname;
string keyStr;
byte[] arrKey;
int i;
bool isok;
//**********************
// RANDOM NUMBER TESTS *
//**********************
Console.WriteLine("\nSOME RANDOM NUMBERS...");
for (i = 0; i < 3; i++)
{
s = Rng.NonceHex(8);
Console.WriteLine("NonceHex={0}", s);
}
for (i = 0; i < 3; i++)
{
s = Rng.KeyHex(24, "");
Console.WriteLine("KeyHex={0}", s);
}
for (i = 0; i < 3; i++)
{
b = Rng.KeyBytes(16, "");
Console.WriteLine("KeyBytes={0}", Cnv.ToHex(b));
}
for (i = 0; i < 3; i++)
{
b = Rng.NonceBytes(8);
Console.WriteLine("NonceBytes={0}", Cnv.ToHex(b));
}
for (i = 0; i < 3; i++)
{
n = Rng.Number(-100, +200);
Console.WriteLine("Rng.Number(-100,+200)={0}", n);
}
for (i = 0; i < 3; i++)
{
n = Rng.Number(-2147483648, +2147483647);
Console.WriteLine("Rng.Number(-2147483648,+2147483647)={0}", n);
}
for (i = 0; i < 3; i++)
{
n = Rng.Octet();
Console.WriteLine("Rng.Octet={0:X2}", n);
}
// Initialize with a seed file
fname = "seed.dat";
if (!FileExists(fname) && doPrompt)
{ // No seed file yet, so we'll make one and prompt the user for keyboard entropy
Console.WriteLine("Creating a new seed file...");
isok = Rng.MakeSeedFile(fname, "Please type some random keystrokes to create a new seedfile", Rng.Strength.Bits_128);
Console.WriteLine("Rng.MakeSeedFile('{0}') returns {1} (expecting True)", fname, isok);
Debug.Assert(true == isok, "Rng.MakeSeedFile failed");
}
// If seed file has not been created, Initialize() will create one anyway
isok = Rng.Initialize(fname);
Console.WriteLine("Rng.Initialize('{0}') returns {1} (expecting True)", fname, isok);
Debug.Assert(true == isok, "Rng.Initialize failed");
// Update the seedfile
isok = Rng.UpdateSeedFile(fname);
Console.WriteLine("Rng.UpdateSeedFile('{0}') returns {1} (expecting True)", fname, isok);
Debug.Assert(true == isok, "Rng.UpdateSeedFile failed");
if (doPrompt)
{
Console.WriteLine("Ask user to type some random keystrokes to add entropy...");
b = Rng.BytesWithPrompt(16);
Console.WriteLine("RNG=0x{0}", Cnv.ToHex(b));
Console.WriteLine("And again with specified strength and custom prompt...");
b = Rng.BytesWithPrompt(16, "Type until we reach 128 bits...", Rng.Strength.Bits_128);
Console.WriteLine("RNG=0x{0}", Cnv.ToHex(b));
Console.WriteLine("And again with output in hex format...");
keyStr = Rng.HexWithPrompt(16);
Console.WriteLine("RNG='{0}'", keyStr);
Console.WriteLine("And again in hex with specified strength and custom prompt...");
keyStr = Rng.HexWithPrompt(16, "Type until we reach 128 bits...", Rng.Strength.Bits_128);
Console.WriteLine("RNG='{0}'", keyStr);
}
// Test the ability to add "user-entropy"...
// ... as a string ...
s = "this is some user entropy in a string, well it should be!";
arrKey = Rng.KeyBytes(16, s);
Console.WriteLine("RNG(seeded)=0x{0}", Cnv.ToHex(arrKey));
keyStr = Rng.KeyHex(16, s);
Console.WriteLine("RNG(seeded)='{0}'", keyStr);
// and with some bytes as a "seed"...
b = new byte[] { 0xde, 0xad, 0xbe, 0xef };
Console.WriteLine("seed=0x{0}", Cnv.ToHex(b));
arrKey = Rng.KeyBytes(16, b);
Console.WriteLine("RNG(seeded)=0x{0}", Cnv.ToHex(arrKey));
keyStr = Rng.KeyHex(16, b);
Console.WriteLine("RNG(seeded)='{0}'", keyStr);
// Do a health check and FIPS-140 stat test on the RNG function
// NB As of [v4.0.0] Rng.Test now returns true/false, not an int.
filename = "Fips140.txt";
isok = Rng.Test(filename);
Console.WriteLine("Rng.Test('{0}') returns {1} (expecting True)", filename, isok);
Debug.Assert(isok, "Rng.Test Failed");
// Test without creating a file
isok = Rng.Test(null);
Console.WriteLine("Rng.Test('{0}') returns {1} (expecting True)", null, isok);
Debug.Assert(isok, "Rng.Test Failed");
// New in [v4.6]...
Console.WriteLine("CARRY OUT TESTS AS PER DRBGVS...");
// Carry out tests as per DRBGVS...
// DRBG mechanism = HMAC_DRBG SHA1
// [SHA-1]
// [PredictionResistance = False]
// [ReturnedBitsLen = 160]
// COUNT = 0
// EntropyInput = d949a64fcf4cd79958e1eb025e750f0b
// Nonce = ad67cdcbadd17e5e
// PersonalizationString =
// AdditionalInput =
// EntropyInputReseed = f86c2fcc9e74102f591f9f276311a0af
// AdditionalInputReseed =
// AdditionalInput =
// ReturnedBits = c8d171e7fdd084fc739275fa1e79bd3038857f37
s = Rng.TestDrbgvs(160, "d949a64fcf4cd79958e1eb025e750f0b", "ad67cdcbadd17e5e", "", "",
"f86c2fcc9e74102f591f9f276311a0af", "", "");
Console.WriteLine("ReturnedBits = {0}", s);
Debug.Assert((String.Compare(s, "c8d171e7fdd084fc739275fa1e79bd3038857f37", true) == 0), "Rng.TestDrbgvs failed");
// COUNT = 0
// EntropyInput = 329a2a877b897cf6cb95d54017fe4770
// Nonce = 16d8e0c752cf4a25
// PersonalizationString = 3535a9a540be9bd156dd440072f7d35e
// AdditionalInput = 1b2c842d4a898f6919f1f3dbbbe3aaea
// EntropyInputReseed = 9075150495f1ba810c37946f86526d9c
// AdditionalInputReseed = 5b40ba5f1770f04bdfc9979279c58228
// AdditionalInput = 97c88090b3aa6e60ea837ae38acaa47f
// ReturnedBits = 90bd05566db522d5b95a292de90be1acde270bb0
s = Rng.TestDrbgvs(160, "329a2a877b897cf6cb95d54017fe4770", "16d8e0c752cf4a25",
"3535a9a540be9bd156dd440072f7d35e", "1b2c842d4a898f6919f1f3dbbbe3aaea",
"9075150495f1ba810c37946f86526d9c", "5b40ba5f1770f04bdfc9979279c58228",
"97c88090b3aa6e60ea837ae38acaa47f");
Console.WriteLine("ReturnedBits = {0}", s);
Debug.Assert((String.Compare(s, "90bd05566db522d5b95a292de90be1acde270bb0", true) == 0), "Rng.TestDrbgvs failed");
}
static void test_Wipe()
{
byte[] b;
bool isok;
string excontent;
string fnameData;
//******************
// WIPE DATA TESTS *
//******************
Console.WriteLine("\nTESTING WIPE DATA...");
// Create a test text file
excontent = "This is some very secret data.";
fnameData = "todelete.txt";
File.WriteAllText(fnameData, excontent);
isok = Wipe.File(fnameData);
Console.WriteLine("Wipe.File returns {0}", isok);
Debug.Assert(isok, "ERROR with Wipe.File");
Debug.Assert(!FileExists(fnameData), "ERROR: Wipe.File did not delete file");
// Again, but with simple wipe (one pass, all zeros)
excontent = "This is some very secret data.";
fnameData = "todelete.txt";
File.WriteAllText(fnameData, excontent);
isok = Wipe.File(fnameData, Wipe.Options.Simple);
Console.WriteLine("Wipe.File(Simple) returns {0}", isok);
Debug.Assert(isok, "ERROR with Wipe.File");
Debug.Assert(!FileExists(fnameData), "ERROR: Wipe.File did not delete file");
// Copy the string into a byte array
b = System.Text.Encoding.Default.GetBytes(excontent);
// Wipe the byte data
Console.WriteLine("Before={0}", Cnv.ToHex(b));
isok = Wipe.Data(b);
Console.WriteLine("Wipe.Data returns {0}", isok);
Console.WriteLine("After ={0}", Cnv.ToHex(b));
Debug.Assert(isok, "ERROR with Wipe.Data");
// Copy to a StringBuilder (we can't wipe a ptStr string)
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append(excontent);
Console.WriteLine("Before=[{0}]", sb.ToString());
isok = Wipe.String(sb);
Console.WriteLine("Wipe.String returns {0}", isok);
Console.WriteLine("After =[{0}]", sb.ToString());
Debug.Assert(isok, "ERROR with Wipe.String");
}
static void test_CRC()
{
string s;
int n;
byte[] b;
string excontent;
string fnameData;
//************
// CRC TESTS *
//************
Console.WriteLine("\nTESTING CRC CHECKSUMS...");
// Create a test text file
excontent = "hello world\r\n";
fnameData = "hello.txt";
File.WriteAllText(fnameData, excontent);
n = Crc.File(fnameData);
Console.WriteLine("CRC32('{0}')={1:x}", fnameData, n);
s = "123456789";
n = Crc.Data(s);
Console.WriteLine("CRC32('{0}')={1:x}", s, n);
// Convert to bytes
b = System.Text.Encoding.Default.GetBytes(s);
n = Crc.Data(b);
Console.WriteLine("CRC32(0x{0})={1:x}", Cnv.ToHex(b), n);
}
static void test_GCM()
{
int n;
string ctStr;
byte[] arrPlain;
byte[] arrCipher;
byte[] arrKey;
byte[] arrIV;
byte[] arrTag;
byte[] arrAAD;
byte[] bcheck;
// ******************************
// GCM AUTHENTICATED ENCRYPTION *
// ******************************
Console.WriteLine("\nGCM AUTHENTICATED ENCRYPTION (AES-GCM) AND GMAC:");
// Ref: McGrew & Viega, The Galois/Counter Mode of Operation (GCM), May, 31 2005
Console.WriteLine("AES-GCM Test case 2:");
arrKey = Cnv.FromHex("00000000000000000000000000000000");
arrPlain = Cnv.FromHex("00000000000000000000000000000000");
arrIV = Cnv.FromHex("000000000000000000000000");
Console.WriteLine("K ={0}", Cnv.ToHex(arrKey));
Console.WriteLine("P ={0}", Cnv.ToHex(arrPlain));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
arrTag = new byte[16]; // Add this to avoid "before it has been assigned a value" error
arrCipher = Gcm.Encrypt(out arrTag, arrPlain, arrKey, arrIV, null);
Console.WriteLine("C ={0}", Cnv.ToHex(arrCipher));
Console.WriteLine("T ={0}", Cnv.ToHex(arrTag));
Debug.Assert(String.Compare(Cnv.ToHex(arrCipher), "0388dace60b6a392f328c2b971b2fe78", true) == 0, "Gcm.Encrypt failed");
Debug.Assert(String.Compare(Cnv.ToHex(arrTag), "ab6e47d42cec13bdf53a67b21257bddf", true) == 0, "Gcm.Encrypt failed");
// Decrypt and check against original plain text
bcheck = Gcm.Decrypt(arrCipher, arrKey, arrIV, null, arrTag);
Console.WriteLine("P'={0}", Cnv.ToHex(bcheck));
Debug.Assert(ByteArraysEqual(bcheck, arrPlain), "Gcm.Decrypt failed");
// Try shorter tag value
byte[] tag2 = new byte[4];
Array.Copy(arrTag, tag2, tag2.Length);
bcheck = Gcm.Decrypt(arrCipher, arrKey, arrIV, null, tag2);
Console.WriteLine("T2={0}", Cnv.ToHex(tag2));
Console.WriteLine("P2={0}", Cnv.ToHex(bcheck));
Debug.Assert(ByteArraysEqual(bcheck, arrPlain), "Gcm.Decrypt (short tag) failed");
Console.WriteLine("AES-GCM Test case 17:");
arrKey = Cnv.FromHex("feffe9928665731c6d6a8f9467308308" +
"feffe9928665731c6d6a8f9467308308");
arrPlain = Cnv.FromHex("d9313225f88406e5a55909c5aff5269a" +
"86a7a9531534f7da2e4c303d8a318a72" +
"1c3c0c95956809532fcf0e2449a6b525" +
"b16aedf5aa0de657ba637b39");
arrAAD = Cnv.FromHex("feedfacedeadbeeffeedfacedeadbeef" +
"abaddad2");
arrIV = Cnv.FromHex("cafebabefacedbad");
ctStr = "c3762df1ca787d32ae47c13bf19844cb" +
"af1ae14d0b976afac52ff7d79bba9de0" +
"feb582d33934a4f0954cc2363bc73f78" +
"62ac430e64abe499f47c9b1f";
Console.WriteLine("K ={0}", Cnv.ToHex(arrKey));
Console.WriteLine("P ={0}", Cnv.ToHex(arrPlain));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
arrCipher = Gcm.Encrypt(out arrTag, arrPlain, arrKey, arrIV, arrAAD);
Console.WriteLine("C ={0}", Cnv.ToHex(arrCipher));
Console.WriteLine("T ={0}", Cnv.ToHex(arrTag));
Debug.Assert(String.Compare(Cnv.ToHex(arrCipher), ctStr, true) == 0, "Gcm.Encrypt failed");
Debug.Assert(String.Compare(Cnv.ToHex(arrTag), "3a337dbf46a792c45e454913fe2ea8f2", true) == 0, "Gcm.Encrypt failed");
// Decrypt and check against original plain text
bcheck = Gcm.Decrypt(arrCipher, arrKey, arrIV, arrAAD, arrTag);
Console.WriteLine("P'={0}", Cnv.ToHex(bcheck));
Debug.Assert(ByteArraysEqual(bcheck, arrPlain), "Gcm.Decrypt failed");
Console.WriteLine("GMAC test vectors:");
arrKey = Cnv.FromHex("feffe9928665731c6d6a8f9467308308");
arrIV = Cnv.FromHex("cafebabefacedbaddecaf888");
arrAAD = Cnv.FromHex("feedfacedeadbeeffeedfacedeadbeef");
Console.WriteLine("K ={0}", Cnv.ToHex(arrKey));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
Console.WriteLine("A ={0}", Cnv.ToHex(arrAAD));
arrTag = Gcm.Gmac(arrKey, arrIV, arrAAD);
Console.WriteLine("T ={0}", Cnv.ToHex(arrTag));
Debug.Assert(String.Compare(Cnv.ToHex(arrTag), "54df474f4e71a9ef8a09bf30da7b1a92", true) == 0, "Gcm.Gmac failed");
Console.WriteLine("Use stateful InitKey-NextEncrypt-Dispose methods:");
Gcm oGcm = Gcm.Instance();
Console.WriteLine("First, try InitKey with bad key (too short)...");
arrKey = Cnv.FromHex("badace");
Console.WriteLine("K ={0}", Cnv.ToHex(arrKey));
n = oGcm.InitKey(arrKey);
Console.WriteLine("Gcm.InitKey returns {0}", n);
Console.WriteLine("Error={0}", General.ErrorLookup(oGcm.ErrCode));
Console.WriteLine("...line above should be an error.");
// Do Test Case 3 then 4. Same key.
Console.WriteLine("Setup AES-GCM key for continued use...");
arrKey = Cnv.FromHex("feffe9928665731c6d6a8f9467308308");
Console.WriteLine("K ={0}", Cnv.ToHex(arrKey));
n = oGcm.InitKey(arrKey);
Debug.Assert(0 == n, "oGcm.InitKey failed");
Console.WriteLine("AES-GCM Test case 3:");
arrPlain = Cnv.FromHex(
"d9313225f88406e5a55909c5aff5269a" +
"86a7a9531534f7da2e4c303d8a318a72" +
"1c3c0c95956809532fcf0e2449a6b525" +
"b16aedf5aa0de657ba637b391aafd255");
arrAAD = null;
arrIV = Cnv.FromHex("cafebabefacedbaddecaf888");
ctStr = "42831ec2217774244b7221b784d0d49c" +
"e3aa212f2c02a4e035c17e2329aca12e" +
"21d514b25466931c7d8f6a5aac84aa05" +
"1ba30b396a0aac973d58e091473f5985";
Console.WriteLine("P ={0}", Cnv.ToHex(arrPlain));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
arrCipher = oGcm.NextEncrypt(out arrTag, arrPlain, arrIV, arrAAD);
Console.WriteLine("C ={0}", Cnv.ToHex(arrCipher));
Console.WriteLine("T ={0}", Cnv.ToHex(arrTag));
Debug.Assert(String.Compare(Cnv.ToHex(arrCipher), ctStr, true) == 0, "Gcm.Encrypt failed");
Debug.Assert(String.Compare(Cnv.ToHex(arrTag), "4d5c2af327cd64a62cf35abd2ba6fab4", true) == 0, "Gcm.NextEncrypt failed");
// Decrypt and check against original plain text
bcheck = oGcm.NextDecrypt(arrCipher, arrIV, arrAAD, arrTag);
Console.WriteLine("P'={0}", Cnv.ToHex(bcheck));
Debug.Assert(ByteArraysEqual(bcheck, arrPlain), "Gcm.NextDecrypt failed");
Console.WriteLine("AES-GCM Test case 4:");
arrPlain = Cnv.FromHex(
"d9313225f88406e5a55909c5aff5269a" +
"86a7a9531534f7da2e4c303d8a318a72" +
"1c3c0c95956809532fcf0e2449a6b525" +
"b16aedf5aa0de657ba637b39");
arrAAD = Cnv.FromHex("feedfacedeadbeeffeedfacedeadbeefabaddad2");
arrIV = Cnv.FromHex("cafebabefacedbaddecaf888");
ctStr = "42831ec2217774244b7221b784d0d49c" +
"e3aa212f2c02a4e035c17e2329aca12e" +
"21d514b25466931c7d8f6a5aac84aa05" +
"1ba30b396a0aac973d58e091";
Console.WriteLine("P ={0}", Cnv.ToHex(arrPlain));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
arrCipher = oGcm.NextEncrypt(out arrTag, arrPlain, arrIV, arrAAD);
Console.WriteLine("C ={0}", Cnv.ToHex(arrCipher));
Console.WriteLine("T ={0}", Cnv.ToHex(arrTag));
Debug.Assert(String.Compare(Cnv.ToHex(arrCipher), ctStr, true) == 0, "Gcm.Encrypt failed");
Debug.Assert(String.Compare(Cnv.ToHex(arrTag), "5bc94fbc3221a5db94fae95ae7121a47", true) == 0, "Gcm.NextEncrypt failed");
// Decrypt and check against original plain text
bcheck = oGcm.NextDecrypt(arrCipher, arrIV, arrAAD, arrTag);
Console.WriteLine("P'={0}", Cnv.ToHex(bcheck));
Debug.Assert(ByteArraysEqual(bcheck, arrPlain), "Gcm.NextDecrypt failed");
// Destroy the key we set up
oGcm.Dispose();
Console.WriteLine("...Key has been destroyed.");
}
static void test_AEAD()
{
byte[] pt;
byte[] ct;
byte[] key;
byte[] nonce;
byte[] tag;
byte[] aad;
byte[] check;
byte[] ctok;
byte[] tagok;
bool isok;
// ***********************************************
// AUTHENTICATED ENCRYPTION WITH ASSOCIATED DATA *
// ***********************************************
Console.WriteLine("\nAUTHENTICATED ENCRYPTION WITH ASSOCIATED DATA:");
Console.WriteLine("NIST 800-38D AES-GCM Test case 2:");
key = Cnv.FromHex("00000000000000000000000000000000");
pt = Cnv.FromHex("00000000000000000000000000000000");
nonce = Cnv.FromHex("000000000000000000000000");
ctok = Cnv.FromHex("0388dace60b6a392f328c2b971b2fe78");
tagok = Cnv.FromHex("ab6e47d42cec13bdf53a67b21257bddf");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
Console.WriteLine("P: " + Cnv.ToHex(pt));
tag = new byte[0]; // Do this to avoid "before it has been assigned a value" error
ct = Aead.Encrypt(out tag, pt, key, nonce, null, Aead.Algorithm.Aes_128_Gcm);
Console.WriteLine("C: " + Cnv.ToHex(ct));
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Encrypt failed");
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
// Decrypt and check against original plain text
check = Aead.Decrypt(ct, key, nonce, null, tag, Aead.Algorithm.Aes_128_Gcm);
Console.WriteLine("P':" + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(check, pt), "Aead.Decrypt failed");
// Try shorter tag value
byte[] tag2 = new byte[4];
Array.Copy(tag, tag2, tag2.Length);
check = Gcm.Decrypt(ct, key, nonce, null, tag2);
Console.WriteLine("T2:" + Cnv.ToHex(tag2));
Console.WriteLine("P2:" + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(check, pt), "Aead.Decrypt (short tag) failed");
Console.WriteLine("\nIEEE P802.1 MACsec 2.4.1 54-byte Packet Encryption Using GCM-AES-128:");
key = Cnv.FromHex("071b113b 0ca743fe cccf3d05 1f737382");
nonce = Cnv.FromHex("f0761e8d cd3d0001 76d457ed");
aad = Cnv.FromHex("e20106d7 cd0df076 1e8dcd3d 88e54c2a 76d457ed");
pt = Cnv.FromHex("08000f10 11121314 15161718 191a1b1c 1d1e1f20 21222324 25262728 292a2b2c 2d2e2f30 31323334 0004");
ctok = Cnv.FromHex("13b4c72b 389dc501 8e72a171 dd85a5d3 752274d3 a019fbca ed09a425 cd9b2e1c 9b72eee7 c9de7d52 b3f3");
tagok = Cnv.FromHex("d6a5284f 4a6d3fe2 2a5d6c2b 960494c3");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
Console.WriteLine("P: " + Cnv.ToHex(pt));
tag = new byte[0]; // Do this to avoid "before it has been assigned a value" error
ct = Aead.Encrypt(out tag, pt, key, nonce, aad, Aead.Algorithm.Aes_128_Gcm);
Console.WriteLine("C: " + Cnv.ToHex(ct));
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Encrypt failed");
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
// Decrypt and check against original plain text
check = Aead.Decrypt(ct, key, nonce, aad, tag, Aead.Algorithm.Aes_128_Gcm);
Console.WriteLine("P':" + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(check, pt), "Aead.Decrypt failed");
Console.WriteLine("\nIEEE P802.1 MACsec 2.6.2 61-byte Packet Encryption Using GCM-AES-256:");
key = Cnv.FromHex("83c093b5 8de7ffe1 c0da926a c43fb360 9ac1c80f ee1b6244 97ef942e 2f79a823");
nonce = Cnv.FromHex("7cfde9f9 e33724c6 8932d612");
aad = Cnv.FromHex("84c5d513 d2aaf6e5 bbd27277 88e52f00 8932d612 7cfde9f9 e33724c6");
pt = Cnv.FromHex("08000f10 11121314 15161718 191a1b1c 1d1e1f20 21222324 25262728 292a2b2c 2d2e2f30 31323334 35363738 393a3b00 06");
ctok = Cnv.FromHex("110222ff 8050cbec e66a813a d09a73ed 7a9a089c 106b9593 89168ed6 e8698ea9 02eb1277 dbec2e68 e473155a 15a7daee d4");
tagok = Cnv.FromHex("a10f4e05 139c23df 00b3aadc 71f0596a");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
Console.WriteLine("P: " + Cnv.ToHex(pt));
tag = new byte[0]; // Do this to avoid "before it has been assigned a value" error
ct = Aead.Encrypt(out tag, pt, key, nonce, aad, Aead.Algorithm.Aes_256_Gcm);
Console.WriteLine("C: " + Cnv.ToHex(ct));
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Encrypt failed");
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
// Decrypt and check against original plain text
check = Aead.Decrypt(ct, key, nonce, aad, tag, Aead.Algorithm.Aes_256_Gcm);
Console.WriteLine("P':" + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(check, pt), "Aead.Decrypt failed");
Console.WriteLine("\nIEEE P802.1 MACsec 2.1.1 54-byte Packet Authentication Using GCM-AES-128:");
key = Cnv.FromHex("ad7a2bd0 3eac835a 6f620fdc b506b345");
nonce = Cnv.FromHex("12153524 c0895e81 b2c28465");
aad = Cnv.FromHex("d609b1f0 56637a0d 46df998d 88e5222a b2c28465 12153524 c0895e81 08000f10 11121314 15161718 191a1b1c 1d1e1f20 21222324 25262728 292a2b2c 2d2e2f30 31323334 0001");
tagok = Cnv.FromHex("f09478a9 b09007d0 6f46e9b6 a1da25dd");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
// Compute MAC over AAD
tag = Aead.Mac(key, nonce, aad, Aead.Algorithm.Aes_128_Gcm);
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Mac failed");
// Authenticate over AAD
isok = Aead.Authenticate(key, nonce, aad, tag, Aead.Algorithm.Aes_128_Gcm);
Console.WriteLine("Aead.Authenticate returns " + isok);
Debug.Assert(isok, "Aead.Authenticate failed");
Console.WriteLine("\nRFC7739 ChaCha20_Poly1305 Sunscreen test:");
key = Cnv.FromHex("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f");
nonce = Cnv.FromHex("070000004041424344454647");
aad = Cnv.FromHex("50515253c0c1c2c3c4c5c6c7");
pt = Cnv.FromHex("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e");
ctok = Cnv.FromHex("d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116");
tagok = Cnv.FromHex("1ae10b594f09e26a7e902ecbd0600691");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
Console.WriteLine("A: " + Cnv.ToHex(aad));
Console.WriteLine("P: " + Cnv.ToHex(pt));
tag = new byte[0]; // Do this to avoid "before it has been assigned a value" error
ct = Aead.Encrypt(out tag, pt, key, nonce, aad, Aead.Algorithm.Chacha20_Poly1305);
Console.WriteLine("C: " + Cnv.ToHex(ct));
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Encrypt failed");
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
// Decrypt and check against original plain text
check = Aead.Decrypt(ct, key, nonce, aad, tag, Aead.Algorithm.Chacha20_Poly1305);
Console.WriteLine("P':" + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(check, pt), "Aead.Decrypt failed");
Console.WriteLine("\nChaCha20_Poly1305 empty PT and AAD strings:");
key = Cnv.FromHex("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f");
nonce = Cnv.FromHex("070000004041424344454647");
aad = Cnv.FromHex("");
pt = Cnv.FromHex("");
ctok = Cnv.FromHex("");
tagok = Cnv.FromHex("A0784D7A4716F3FEB4F64E7F4B39BF04");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
Console.WriteLine("A: " + Cnv.ToHex(aad));
Console.WriteLine("P: " + Cnv.ToHex(pt));
tag = new byte[0]; // Do this to avoid "before it has been assigned a value" error
ct = Aead.Encrypt(out tag, pt, key, nonce, aad, Aead.Algorithm.Chacha20_Poly1305);
Console.WriteLine("C: " + Cnv.ToHex(ct));
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Encrypt failed");
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
// Decrypt and check against original plain text
check = Aead.Decrypt(ct, key, nonce, aad, tag, Aead.Algorithm.Chacha20_Poly1305);
Console.WriteLine("P':" + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(check, pt), "Aead.Decrypt failed");
Console.WriteLine("Check we get same tag using .Mac() method");
tag = Aead.Mac(key, nonce, aad, Aead.Algorithm.Chacha20_Poly1305);
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
Console.WriteLine("\nipsecme-chacha20-poly1305 Appendix B IKEv2 Example:");
key = Cnv.FromHex("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f");
nonce = Cnv.FromHex("a0 a1 a2 a3 10 11 12 13 14 15 16 17");
aad = Cnv.FromHex("c0c1c2c3c4c5c6c7d0d1d2d3d4d5d6d72e202500000000090000004529000029");
pt = Cnv.FromHex("00 00 00 0c 00 00 40 01 00 00 00 0a 00");
ctok = Cnv.FromHex("61 03 94 70 1f 8d 01 7f 7c 12 92 48 89");
tagok = Cnv.FromHex("6b 71 bf e2 52 36 ef d7 cd c6 70 66 90 63 15 b2");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
Console.WriteLine("A: " + Cnv.ToHex(aad));
Console.WriteLine("P: " + Cnv.ToHex(pt));
tag = new byte[0]; // Do this to avoid "before it has been assigned a value" error
ct = Aead.Encrypt(out tag, pt, key, nonce, aad, Aead.Algorithm.Chacha20_Poly1305);
Console.WriteLine("C: " + Cnv.ToHex(ct));
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Encrypt failed");
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
// Compute tags for all empty strings for all algorithms
Console.WriteLine("\nUse Aead.Mac() to compute tags for empty PT and AAD strings:");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
tag = Aead.Mac(key, nonce, aad, Aead.Algorithm.Chacha20_Poly1305);
Console.WriteLine("T (e, Chacha20_Poly1305): " + Cnv.ToHex(tag));
//Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.Encrypt failed");
tag = Aead.Mac(key, nonce, aad, Aead.Algorithm.Aes_256_Gcm);
Console.WriteLine("T (e, Aes_256_Gcm): " + Cnv.ToHex(tag));
// Shorten the 256-bit key to 128 bits
Array.Resize(ref key, 16);
Console.WriteLine("K: " + Cnv.ToHex(key));
tag = Aead.Mac(key, nonce, aad, Aead.Algorithm.Aes_128_Gcm);
Console.WriteLine("T (e, Aes_128_Gcm): " + Cnv.ToHex(tag));
}
static void test_AEAD_incremental()
{
byte[] pt;
byte[] ct;
byte[] key;
byte[] nonce;
byte[] tag;
byte[] aad;
byte[] check;
byte[] ctok;
byte[] tagok;
int r;
byte[] chunk;
bool isok;
int offset, len, nleft, chunklen;
Aead o;
// *************************************************************
// AUTHENTICATED ENCRYPTION WITH ASSOCIATED DATA - INCREMENTAL *
// *************************************************************
Console.WriteLine("\nAUTHENTICATED ENCRYPTION WITH ASSOCIATED DATA - INCREMENTAL:");
Console.WriteLine("\nIEEE P802.1 MACsec 2.6.2 61-byte Packet Encryption Using GCM-AES-256:");
key = Cnv.FromHex("83c093b5 8de7ffe1 c0da926a c43fb360 9ac1c80f ee1b6244 97ef942e 2f79a823");
nonce = Cnv.FromHex("7cfde9f9 e33724c6 8932d612");
pt = Cnv.FromHex("08000f10 11121314 15161718 191a1b1c 1d1e1f20 21222324 25262728 292a2b2c 2d2e2f30 31323334 35363738 393a3b00 06");
ctok = Cnv.FromHex("110222ff 8050cbec e66a813a d09a73ed 7a9a089c 106b9593 89168ed6 e8698ea9 02eb1277 dbec2e68 e473155a 15a7daee d4");
tagok = Cnv.FromHex("a10f4e05 139c23df 00b3aadc 71f0596a");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
// Setup a new Aead object, initialize the key and nonce
o = Aead.Instance();
r = o.InitKey(key, Aead.Algorithm.Aes_256_Gcm);
Debug.Assert(0 == r, "Aead.InitKey failed");
r = o.SetNonce(nonce);
Debug.Assert(0 == r, "Aead.SetNonce failed");
// Add the AAD in chunks
aad = Cnv.FromHex("84c5d513 d2aaf6e5 bbd27277 88e52f00 8932d612 7cfde9f9 e33724c6");
Console.WriteLine("A: " + Cnv.ToHex(aad));
chunk = Cnv.FromHex("84c5d513 d2aaf6e5 bb");
r = o.AddAAD(chunk);
Debug.Assert(0 == r, "Aead.AddAAD failed");
chunk = Cnv.FromHex("d27277 88e52f00 8932d612 7cfde9f9 e337");
r = o.AddAAD(chunk);
Debug.Assert(0 == r, "Aead.AddAAD failed");
chunk = Cnv.FromHex("24c6");
r = o.AddAAD(chunk);
Debug.Assert(0 == r, "Aead.AddAAD failed");
Console.WriteLine("ENCRYPTING IN CHUNKS...");
r = o.StartEncrypt();
Debug.Assert(0 == r, "Aead.StartEncrypt failed");
Console.WriteLine("P-all: " + Cnv.ToHex(pt));
// Encrypt PT in chunks
chunklen = 17;
nleft = pt.Length;
ct = new byte[pt.Length];
for (offset = 0, len = chunklen; nleft > 0; offset += len, nleft -= len)
{
if (nleft < len) len = nleft;
chunk = new byte[len];
Array.Copy(pt, offset, chunk, 0, len);
Console.WriteLine("P-chunk: " + Cnv.ToHex(chunk));
chunk = o.Update(chunk);
Console.WriteLine("C-chunk: " + Cnv.ToHex(chunk));
Array.Copy(chunk, 0, ct, offset, len);
}
Console.WriteLine("C-all: " + Cnv.ToHex(ct));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Update failed");
tag = o.FinishEncrypt();
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.FinishEncrypt failed");
// DECRYPT:
Console.WriteLine("DECRYPTING IN CHUNKS...");
// Key is set above, reset the nonce to decrypt
r = o.SetNonce(nonce);
Debug.Assert(0 == r, "Aead.SetNonce failed");
// Add the AAD in toto
aad = Cnv.FromHex("84c5d513 d2aaf6e5 bbd27277 88e52f00 8932d612 7cfde9f9 e33724c6");
Console.WriteLine("A: " + Cnv.ToHex(aad));
r = o.AddAAD(aad);
r = o.StartDecrypt(tag);
Debug.Assert(0 == r, "Aead.StartDecrypt failed");
// Decrypt CT in chunks
chunklen = 13;
nleft = ct.Length;
check = new byte[ct.Length];
for (offset = 0, len = chunklen; nleft > 0; offset += len, nleft -= len)
{
if (nleft < len) len = nleft;
chunk = new byte[len];
Array.Copy(ct, offset, chunk, 0, len);
Console.WriteLine("C-chunk: " + Cnv.ToHex(chunk));
chunk = o.Update(chunk);
Console.WriteLine("P-chunk: " + Cnv.ToHex(chunk));
Array.Copy(chunk, 0, check, offset, len);
}
Console.WriteLine("P-all: " + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(pt, check), "Aead.Update failed");
isok = o.FinishDecrypt();
Console.WriteLine("FinishDecrypt: " + isok);
Debug.Assert(isok, "Aead.FinishDecrypt failed");
o.Dispose();
//************************************
// DO THE SAME USING CHACHA20_POLY1305
//************************************
Console.WriteLine("\nRFC7739 ChaCha20_Poly1305 Sunscreen test:");
key = Cnv.FromHex("808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f");
nonce = Cnv.FromHex("070000004041424344454647");
aad = Cnv.FromHex("50515253c0c1c2c3c4c5c6c7");
pt = Cnv.FromHex("4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e");
ctok = Cnv.FromHex("d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116");
tagok = Cnv.FromHex("1ae10b594f09e26a7e902ecbd0600691");
Console.WriteLine("K: " + Cnv.ToHex(key));
Console.WriteLine("N: " + Cnv.ToHex(nonce));
// Setup a new Aead object, initialize the key and nonce
o = Aead.Instance();
r = o.InitKey(key, Aead.Algorithm.Chacha20_Poly1305);
Debug.Assert(0 == r, "Aead.InitKey failed");
r = o.SetNonce(nonce);
Debug.Assert(0 == r, "Aead.SetNonce failed");
// Add the AAD in one go
Console.WriteLine("A: " + Cnv.ToHex(aad));
r = o.AddAAD(aad);
Debug.Assert(0 == r, "Aead.AddAAD failed");
Console.WriteLine("ENCRYPTING IN CHUNKS...");
r = o.StartEncrypt();
Debug.Assert(0 == r, "Aead.StartEncrypt failed");
Console.WriteLine("P-all: " + Cnv.ToHex(pt));
// Encrypt PT in chunks
chunklen = 19;
nleft = pt.Length;
ct = new byte[pt.Length];
for (offset = 0, len = chunklen; nleft > 0; offset += len, nleft -= len)
{
if (nleft < len) len = nleft;
chunk = new byte[len];
Array.Copy(pt, offset, chunk, 0, len);
Console.WriteLine("P-chunk: " + Cnv.ToHex(chunk));
chunk = o.Update(chunk);
Console.WriteLine("C-chunk: " + Cnv.ToHex(chunk));
Array.Copy(chunk, 0, ct, offset, len);
}
Console.WriteLine("C-all: " + Cnv.ToHex(ct));
Debug.Assert(ByteArraysEqual(ct, ctok), "Aead.Update failed");
tag = o.FinishEncrypt();
Console.WriteLine("T: " + Cnv.ToHex(tag));
Debug.Assert(ByteArraysEqual(tag, tagok), "Aead.FinishEncrypt failed");
// DECRYPT:
Console.WriteLine("DECRYPTING IN CHUNKS...");
// Key is set above, reset the nonce and AAD to decrypt
r = o.SetNonce(nonce);
Debug.Assert(0 == r, "Aead.SetNonce failed");
r = o.AddAAD(aad);
Debug.Assert(0 == r, "Aead.AddAAD failed");
r = o.StartDecrypt(tag);
Debug.Assert(0 == r, "Aead.StartDecrypt failed");
// Decrypt CT in chunks
chunklen = 7;
nleft = ct.Length;
check = new byte[ct.Length];
for (offset = 0, len = chunklen; nleft > 0; offset += len, nleft -= len)
{
if (nleft < len) len = nleft;
chunk = new byte[len];
Array.Copy(ct, offset, chunk, 0, len);
Console.WriteLine("C-chunk: " + Cnv.ToHex(chunk));
chunk = o.Update(chunk);
Console.WriteLine("P-chunk: " + Cnv.ToHex(chunk));
Array.Copy(chunk, 0, check, offset, len);
}
Console.WriteLine("P-all: " + Cnv.ToHex(check));
Debug.Assert(ByteArraysEqual(pt, check), "Aead.Update failed");
isok = o.FinishDecrypt();
Console.WriteLine("FinishDecrypt: " + isok);
Debug.Assert(isok, "Aead.FinishDecrypt failed");
o.Dispose();
}
static void test_CipherFileExtended()
{
int n;
byte[] arrKey;
byte[] arrIV;
string excontent;
string fnameData;
string fnameEnc;
string fnameCheck;
string fnameChk1;
// *********************************
// EXTENDED FILE CIPHER OPERATIONS *
// *********************************
Console.WriteLine("\nTESTING EXTENDED FILE CIPHER OPERATIONS:");
// Create a test text file
excontent = "Now is the time for";
fnameData = "nowis19.txt";
File.WriteAllText(fnameData, excontent);
Console.WriteLine("Des.FileEncrypt/Decrypt with CipherFileOption...");
// Encrypt file using DES in CBC mode using byte arrays for key and IV
fnameEnc = "nowis.des-cbc.enc.dat";
fnameCheck = "nowis.des-cbc.chk.txt";
fnameChk1 = "nowis.des-cbc.chk1.txt";
arrKey = Cnv.FromHex("0123456789ABCDEF");
arrIV = Cnv.FromHex("1234567890ABCDEF");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
Console.WriteLine("Input file contents ({0} bytes):\n{1}", FileLength(fnameData), GetFileAsHex(fnameData));
// Use default option
n = Des.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.Default);
Console.WriteLine("Des.FileEncrypt(CBC, Default) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Des.FileEncrypt(CBC, Default) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Use PrefixIV option
n = Des.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.PrefixIV);
Console.WriteLine("Des.FileEncrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Des.FileEncrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Now decrypt using same PrefixIV option
n = Des.FileDecrypt(fnameCheck, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV);
Console.WriteLine("Des.FileDecrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Des.FileDecrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameCheck, FileLength(fnameCheck), GetFileAsHex(fnameCheck));
// Check we got what we started with
Debug.Assert(FilesAreIdentical(fnameData, fnameCheck), "Decrypted file does not match original");
// Now decrypt using LeavePadding option
n = Des.FileDecrypt(fnameChk1, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV | CipherFileOption.LeavePadding);
Console.WriteLine("Des.FileDecrypt(CBC, PrefixIV+LeavePadding) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Des.FileDecrypt(CBC, PrefixIV+LeavePadding) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameChk1, FileLength(fnameChk1), GetFileAsHex(fnameChk1));
Console.WriteLine("");
Console.WriteLine("Aes128.FileEncrypt/Decrypt with CipherFileOption...");
fnameEnc = "nowis.aes128-cbc.enc.dat";
fnameCheck = "nowis.aes128-cbc.chk.txt";
fnameChk1 = "nowis.aes128-cbc.chk1.txt";
arrKey = Cnv.FromHex("0123456789ABCDEFFEDCBA9876543210");
arrIV = Cnv.FromHex("1234567890ABCDEFFEDCBA0987654321");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
Console.WriteLine("Input file contents ({0} bytes):\n{1}", FileLength(fnameData), GetFileAsHex(fnameData));
// Use default option
n = Aes128.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.Default);
Console.WriteLine("Aes128.FileEncrypt(CBC, Default) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes128.FileEncrypt(CBC, Default) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Use PrefixIV option
n = Aes128.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.PrefixIV);
Console.WriteLine("Aes128.FileEncrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes128.FileEncrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Now decrypt using same PrefixIV option
n = Aes128.FileDecrypt(fnameCheck, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV);
Console.WriteLine("Aes128.FileDecrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes128.FileDecrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameCheck, FileLength(fnameCheck), GetFileAsHex(fnameCheck));
// Check we got what we started with
Debug.Assert(FilesAreIdentical(fnameData, fnameCheck), "Decrypted file does not match original");
// Now decrypt using LeavePadding option
n = Aes128.FileDecrypt(fnameChk1, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV | CipherFileOption.LeavePadding);
Console.WriteLine("Aes128.FileDecrypt(CBC, PrefixIV+LeavePadding) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes128.FileDecrypt(CBC, PrefixIV+LeavePadding) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameChk1, FileLength(fnameChk1), GetFileAsHex(fnameChk1));
// Call all other versions at least once
// AES-192
Console.WriteLine("Aes192.FileEncrypt/Decrypt with CipherFileOption...");
fnameEnc = "nowis.aes192-cbc.enc.dat";
fnameCheck = "nowis.aes192-cbc.chk.txt";
arrKey = Cnv.FromHex("0123456789ABCDEFFEDCBA987654321089ABCDEF01234567");
arrIV = Cnv.FromHex("1234567890ABCDEFFEDCBA0987654321");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
// Use PrefixIV option
n = Aes192.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.PrefixIV);
Console.WriteLine("Aes192.FileEncrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes192.FileEncrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Now decrypt using same PrefixIV option
n = Aes192.FileDecrypt(fnameCheck, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV);
Console.WriteLine("Aes192.FileDecrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes192.FileDecrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameCheck, FileLength(fnameCheck), GetFileAsHex(fnameCheck));
// Check we got what we started with
Debug.Assert(FilesAreIdentical(fnameData, fnameCheck), "Decrypted file does not match original");
// AES-256
Console.WriteLine("Aes256.FileEncrypt/Decrypt with CipherFileOption...");
fnameEnc = "nowis.aes256-cbc.enc.dat";
fnameCheck = "nowis.aes256-cbc.chk.txt";
arrKey = Cnv.FromHex("0123456789ABCDEFFEDCBA987654321089ABCDEF0123456776543210FEDCBA98");
arrIV = Cnv.FromHex("1234567890ABCDEFFEDCBA0987654321");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
// Use PrefixIV option
n = Aes256.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.PrefixIV);
Console.WriteLine("Aes256.FileEncrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes256.FileEncrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Now decrypt using same PrefixIV option
n = Aes256.FileDecrypt(fnameCheck, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV);
Console.WriteLine("Aes256.FileDecrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Aes256.FileDecrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameCheck, FileLength(fnameCheck), GetFileAsHex(fnameCheck));
// Check we got what we started with
Debug.Assert(FilesAreIdentical(fnameData, fnameCheck), "Decrypted file does not match original");
// TDEA
Console.WriteLine("Tdea.FileEncrypt/Decrypt with CipherFileOption...");
fnameEnc = "nowis.tdea-cbc.enc.dat";
fnameCheck = "nowis.tdea-cbc.chk.txt";
arrKey = Cnv.FromHex("0123456789ABCDEFFEDCBA987654321089ABCDEF01234567");
arrIV = Cnv.FromHex("1234567890ABCDEF");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
// Use PrefixIV option
n = Tdea.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.PrefixIV);
Console.WriteLine("Tdea.FileEncrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Tdea.FileEncrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Now decrypt using same PrefixIV option
n = Tdea.FileDecrypt(fnameCheck, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV);
Console.WriteLine("Tdea.FileDecrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Tdea.FileDecrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameCheck, FileLength(fnameCheck), GetFileAsHex(fnameCheck));
// Check we got what we started with
Debug.Assert(FilesAreIdentical(fnameData, fnameCheck), "Decrypted file does not match original");
// Blowfish
Console.WriteLine("Blowfish.FileEncrypt/Decrypt with CipherFileOption...");
fnameEnc = "nowis.blf-cbc.enc.dat";
fnameCheck = "nowis.blf-cbc.chk.txt";
arrKey = Cnv.FromHex("0123456789abcdeff0e1d2c3b4a59687");
arrIV = Cnv.FromHex("1234567890ABCDEF");
Console.WriteLine("KY={0}", Cnv.ToHex(arrKey));
Console.WriteLine("IV={0}", Cnv.ToHex(arrIV));
// Use PrefixIV option
n = Blowfish.FileEncrypt(fnameEnc, fnameData, arrKey, Mode.CBC, arrIV, CipherFileOption.PrefixIV);
Console.WriteLine("Blowfish.FileEncrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Blowfish.FileEncrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameEnc, FileLength(fnameEnc), GetFileAsHex(fnameEnc));
// Now decrypt using same PrefixIV option
n = Blowfish.FileDecrypt(fnameCheck, fnameEnc, arrKey, Mode.CBC, null, CipherFileOption.PrefixIV);
Console.WriteLine("Blowfish.FileDecrypt(CBC, PrefixIV) returns {0} (expecting 0)", n);
Debug.Assert(0 == n, "Blowfish.FileDecrypt(CBC, PrefixIV) failed");
Console.WriteLine("...created file {0} ({1} bytes). File contents:\n{2}",
fnameCheck, FileLength(fnameCheck), GetFileAsHex(fnameCheck));
// Check we got what we started with
Debug.Assert(FilesAreIdentical(fnameData, fnameCheck), "Decrypted file does not match original");
}
static void test_CipherPad()
{
string s;
byte[] key, iv, pt, ct, p1, correct;
Console.WriteLine("\nTEST THE CIPHER CLASS WITH PADDING...");
Console.WriteLine("Tdea/CBC/Pkcs5");
key = Cnv.FromHex("737C791F25EAD0E04629254352F7DC6291E5CB26917ADA32");
iv = Cnv.FromHex("B36B6BFB6231084E");
Console.WriteLine("KY=" + Cnv.ToHex(key));
Console.WriteLine("IV=" + Cnv.ToHex(iv));
pt = Cnv.FromHex("5468697320736F6D652073616D706520636F6E74656E742E");
Console.WriteLine("PT=" + Cnv.ToHex(pt));
Console.WriteLine("PT='" + System.Text.Encoding.Default.GetString(pt) + "'");
correct = Cnv.FromHex("d76fd1178fbd02f84231f5c1d2a2f74a4159482964f675248254223daf9af8e4");
ct = Cipher.Encrypt(pt, key, iv, CipherAlgorithm.Tdea, Mode.CBC, Padding.Pkcs5);
Console.WriteLine("CT=" + Cnv.ToHex(ct));
Console.WriteLine("OK=" + Cnv.ToHex(correct));
Debug.Assert(ByteArraysEqual(ct, correct), "Cipher.Encrypt with padding failed");
// Now decrypt
p1 = Cipher.Decrypt(ct, key, iv, CipherAlgorithm.Tdea, Mode.CBC, Padding.Pkcs5);
Console.WriteLine("P'=" + Cnv.ToHex(p1));
Console.WriteLine("P'='" + System.Text.Encoding.Default.GetString(p1) + "'");
Debug.Assert(ByteArraysEqual(p1, pt), "Cipher.Decrypt with padding failed");
Console.WriteLine("Aes128/CBC/pkcs5");
key = Cnv.FromHex("0123456789ABCDEFF0E1D2C3B4A59687");
iv = Cnv.FromHex("FEDCBA9876543210FEDCBA9876543210");
Console.WriteLine("KY=" + Cnv.ToHex(key));
Console.WriteLine("IV=" + Cnv.ToHex(iv));
s = "Now is the time for all good men to";
pt = System.Text.Encoding.Default.GetBytes(s);
Console.WriteLine("PT=" + Cnv.ToHex(pt));
Console.WriteLine("PT='" + System.Text.Encoding.Default.GetString(pt) + "'");
correct = Cnv.FromHex("C3153108A8DD340C0BCB1DFE8D25D2320EE0E66BD2BB4A313FB75C5638E9E17753C7E8DF5975A36677355F5C6584228B");
ct = Cipher.Encrypt(pt, key, iv, CipherAlgorithm.Aes128, Mode.CBC, Padding.Pkcs5);
Console.WriteLine("CT=" + Cnv.ToHex(ct));
Console.WriteLine("OK=" + Cnv.ToHex(correct));
Debug.Assert(ByteArraysEqual(ct, correct), "Cipher.Encrypt with padding failed");
// Now decrypt
p1 = Cipher.Decrypt(ct, key, iv, CipherAlgorithm.Aes128, Mode.CBC, Padding.Pkcs5);
Console.WriteLine("P'=" + Cnv.ToHex(p1));
Console.WriteLine("P'='" + System.Text.Encoding.Default.GetString(p1) + "'");
Debug.Assert(ByteArraysEqual(p1, pt), "Cipher.Decrypt with padding failed");
p1 = Cipher.Decrypt(ct, key, iv, CipherAlgorithm.Aes128, Mode.CBC, Padding.NoPad);
Console.WriteLine("Pn=" + Cnv.ToHex(p1));
Console.WriteLine("Aes128/ECB/OneAndZeroes...");
ct = Cipher.Encrypt(pt, key, iv, CipherAlgorithm.Aes128, Mode.ECB, Padding.OneAndZeroes);
Console.WriteLine("CT=" + Cnv.ToHex(ct));
p1 = Cipher.Decrypt(ct, key, iv, CipherAlgorithm.Aes128, Mode.ECB, Padding.NoPad);
Console.WriteLine("Pn=" + Cnv.ToHex(p1));
p1 = Cipher.Decrypt(ct, key, iv, CipherAlgorithm.Aes128, Mode.ECB, Padding.OneAndZeroes);
Console.WriteLine("P'=" + Cnv.ToHex(p1));
Console.WriteLine("P'='" + System.Text.Encoding.Default.GetString(p1) + "'");
Debug.Assert(ByteArraysEqual(p1, pt));
}
static void test_Poly1305()
{
string msg;
string msgHex;
string keyHex;
string tagHex;
string okhex;
// ***********************************
// POLY1305 AUTHENTICATION ALGORITHM *
// ***********************************
Console.WriteLine("\nPOLY1305 AUTHENTICATION ALGORITHM:");
// Ref: Test vector from `draft-irtf-cfrg-chacha20-poly1305-06.txt`
msg = "Cryptographic Forum Research Group";
keyHex = "85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b";
okhex = "a8061dc1305136c6c22b8baf0c0127a9";
msgHex = Cnv.ToHex(msg);
Console.WriteLine("Message to be authenticated:");
Console.WriteLine("'"+ msg + "'");
Console.WriteLine(msgHex);
Console.WriteLine("Key: " + keyHex);
tagHex = Mac.HexFromHex(msgHex, keyHex, MacAlgorithm.Poly1305);
Console.WriteLine("Tag: " + tagHex);
Debug.Assert(String.Compare(tagHex, okhex, true) == 0, "Mac.HexFromHex(Poly1305) failed");
}
static void test_SHA3_obj()
{
int n;
string s;
bool isok;
string okhex;
//**************************
// SHA-3 HASH DIGEST TESTS *
//**************************
Console.WriteLine("TESTING SHA-3 object:");
int[] bitlengths = { 224, 256, 384, 512 };
foreach (int nbits in bitlengths) {
// Instantiate a new object for SHA-3
Sha3 oSha3 = Sha3.Instance();
isok = oSha3.Init(nbits);
Console.WriteLine("oSha3.Init({1}) returned {0}. LengthInBytes={2}", isok, nbits, oSha3.LengthInBytes);
Debug.Assert(isok, "Sha3.Init failed");
n = oSha3.AddData("a");
n = oSha3.AddData("bc");
s = oSha3.HexDigest();
Console.WriteLine("SHA3-{1}('abc')={0}", s, nbits);
// Correct result
switch (nbits) {
case 224:
okhex = "e642824c3f8cf24ad09234ee7d3c766fc9a3a5168d0c94ad73b46fdf";
break;
case 256:
okhex = "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532";
break;
case 384:
okhex = "ec01498288516fc926459f58e2c6ad8df9b473cb0fc08c2596da7cf0e49be4b298d88cea927ac7f539f1edf228376d25";
break;
case 512:
okhex = "b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0";
break;
default:
okhex = "";
break;
}
Debug.Assert(String.Compare(okhex, s, true) == 0, "SHA-3('abc') failed");
// Compute SHA-3(one million repetitions of 'a')
oSha3.Init(nbits);
byte[] a1000 = new byte[1000];
for (int i = 0; i < 1000; i++)
a1000[i] = 0x61; // 'a' in ascii form
for (int i = 0; i < 1000; i++) {
n = oSha3.AddData(a1000);
Debug.Assert(0 == n, "Sha3.Adddata failed");
}
s = oSha3.HexDigest();
Console.WriteLine("SHA3-{1}(1M x 'a')={0}", s, nbits);
// Correct result
switch (nbits) {
case 224:
okhex = "d69335b93325192e516a912e6d19a15cb51c6ed5c15243e7a7fd653c";
break;
case 256:
okhex = "5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1";
break;
case 384:
okhex = "eee9e24d78c1855337983451df97c8ad9eedf256c6334f8e948d252d5e0e76847aa0774ddb90a842190d2c558b4b8340";
break;
case 512:
okhex = "3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87";
break;
default:
okhex = "";
break;
}
Debug.Assert(String.Compare(okhex, s, true) == 0, "SHA-3(1M x 'a') failed");
// Compute the SHA-3 digest of the empty string
oSha3.Init(nbits);
s = oSha3.HexDigest();
Console.WriteLine("SHA3-{1}('')={0}", s, nbits);
// Correct result
switch (nbits) {
case 224:
okhex = "6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7";
break;
case 256:
okhex = "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a";
break;
case 384:
okhex = "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004";
break;
case 512:
okhex = "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26";
break;
default:
okhex = "";
break;
}
Debug.Assert(String.Compare(okhex, s, true) == 0, "SHA-3(empty) failed");
oSha3.Dispose();
}
}
static void test_SHA3()
{
string s;
byte[] b;
string okhex;
string msghex;
string keyhex;
int bitlen;
Console.WriteLine("TESTING SHA-3:");
// SHA-3-256("abc")
okhex = "3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532";
// Compute digest from string
s = Hash.HexFromString("abc", HashAlgorithm.Sha3_256);
Console.WriteLine("SHA3-256('abc')={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "SHA-3('abc') failed");
// SHA-3-256 of "abc" as byte array
b = new byte[] { 0x61, 0x62, 0x63 }; // "abc" in a byte array
s = Hash.HexFromBytes(b, HashAlgorithm.Sha3_256);
Console.WriteLine("SHA3-256('abc')={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "SHA-3('abc') failed");
// Same again bitwise
s = Hash.HexFromBits(b, 24, HashAlgorithm.Sha3_256);
Console.WriteLine("SHA3-256('abc')={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "SHA-3('abc') failed");
// Ref: SHAVS-SHA3 CAVS 19.0 "SHA3-256 ShortMsg" information for "SHA3AllBits1-28-16"
b = Cnv.FromHex("2590A0"); // NIST "259028"
bitlen = 22;
okhex = "d5863d4b1ff41551c92a9e08c52177e32376c9bd100c611c607db840096eb22f";
s = Hash.HexFromBits(b, bitlen, HashAlgorithm.Sha3_256);
Console.WriteLine("SHA3-256(22bits)={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "SHA-3(22bits) failed");
// HMAC-SHA3-256
// Text is "Sample message for keylen<blocklen"
msghex = "53616D706C65206D65737361676520666F72206B65796C656E3C626C6F636B6C656E";
keyhex = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
okhex = "4fe8e202c4f058e8dddc23d8c34e467343e23555e24fc2f025d598f558f67205";
s = Mac.HexFromHex(msghex, keyhex, MacAlgorithm.HmacSha3_256);
Console.WriteLine("HMAC-SHA3-256()={0}", s);
Debug.Assert(String.Compare(okhex, s, true) == 0, "HMAC-SHA3-256() failed");
}
static void test_KMAC()
{
byte[] b;
string s;
string okhex;
string msghex;
string keyhex;
int noutbits;
Console.WriteLine("TESTING KMAC:");
// Ref: `KMAC_samples.pdf` "Secure Hashing - KMAC-Samples" 2017-02-27
// Sample #1
keyhex = "404142434445464748494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F";
msghex = "00010203";
noutbits = 256;
okhex = "E5780B0D3EA6F7D3A429C5706AA43A00FADBD7D49628839E3187243F456EE14E";
// Compute MAC from hex-encoded strings, fixed "standard" size
s = Mac.HexFromHex(msghex, keyhex, MacAlgorithm.Kmac128);
Console.WriteLine("KMAC128={0}", s);
Console.WriteLine("OK ={0}", okhex);
Debug.Assert(String.Compare(okhex, s, true) == 0, "KMAC failed");
// Compute MAC using Prf class, explicitly specifying size
b = Prf.Bytes(noutbits / 8, Cnv.FromHex(msghex), Cnv.FromHex(keyhex), "", PrfAlgorithm.Kmac128);
Console.WriteLine("KMAC128={0}", Cnv.ToHex(b));
Console.WriteLine("OK ={0}", okhex);
Debug.Assert(String.Compare(okhex, Cnv.ToHex(b), true) == 0, "KMAC failed");
// Request a lot of output (> single KECCAK block)
okhex = "38158A1CAE4E1A25D85F2031246ADE697B3292FEF88B0923A59A02D1D53B704653EE7242662A10796BA20779D300D52D7432018741233D587252D31DC48BDB8233285D4A4ACD65848509B051A448D873649228B6626E5EF817C7AF2DEDC91F120F8CA535A1EE301FAE8186FDEDE5A76181A472A32CFAD1DDD1391E162F124D4A7572AD8A20076601BCF81E4B0391F3E95AEFFA708C33C1217C96BE6A4F02FBBC2D3B3B6FFAEB5BFD3BE4A2E02B75993FCC04DA6FAC4BFCB2A9F05792A1A5CC80CA34186243EFDB31";
noutbits = 1600;
b = Prf.Bytes(noutbits / 8, Cnv.FromHex(msghex), Cnv.FromHex(keyhex), "", PrfAlgorithm.Kmac128);
Console.WriteLine("KMAC128={0}", Cnv.ToHex(b));
Console.WriteLine("OK ={0}", okhex);
Debug.Assert(String.Compare(okhex, Cnv.ToHex(b), true) == 0, "KMAC failed");
}
static void test_XOF()
{
byte[] b;
string okhex;
string msghex;
int noutbits;
Console.WriteLine("TESTING XOF:");
// Ref: "SHA-3 XOF Test Vectors for Byte-Oriented Output"
// File `SHAKE256VariableOut.rsp` COUNT = 1244
msghex = "6ae23f058f0f2264a18cd609acc26dd4dbc00f5c3ee9e13ecaea2bb5a2f0bb6b";
noutbits = 2000;
okhex = "b9b92544fb25cfe4ec6fe437d8da2bbe00f7bdaface3de97b8775a44d753c3adca3f7c6f183cc8647e229070439aa9539ae1f8f13470c9d3527fffdeef6c94f9f0520ff0c1ba8b16e16014e1af43ac6d94cb7929188cce9d7b02f81a2746f52ba16988e5f6d93298d778dfe05ea0ef256ae3728643ce3e29c794a0370e9ca6a8bf3e7a41e86770676ac106f7ae79e67027ce7b7b38efe27d253a52b5cb54d6eb4367a87736ed48cb45ef27f42683da140ed3295dfc575d3ea38cfc2a3697cc92864305407369b4abac054e497378dd9fd0c4b352ea3185ce1178b3dc1599df69db29259d4735320c8e7d33e8226620c9a1d22761f1d35bdff79a";
b = Xof.Bytes(noutbits / 8, Cnv.FromHex(msghex), XofAlgorithm.Shake256);
Console.WriteLine("SHAKE256={0}", Cnv.ToHex(b));
Console.WriteLine("OK ={0}", okhex);
Debug.Assert(String.Compare(okhex, Cnv.ToHex(b), true) == 0, "XOF failed");
}
//*****************
// FILE UTILITIES *
//*****************
static string GetFileAsHex(string fileName)
{
byte[] b = File.ReadAllBytes(fileName);
string s = Cnv.ToHex(b);
return s;
}
static bool FileExists(string filePath)
{
FileInfo fi = new FileInfo(filePath);
return fi.Exists;
}
static int FileLength(string filePath)
{ // Assuming size less than 2 GB
FileInfo fi = new FileInfo(filePath);
return (int)fi.Length;
}
static bool FilesAreIdentical(string file1, string file2)
// Returns true if two binary files are identical, false if they are not
// Ref: http://support.microsoft.com/kb/320348
{
int file1byte;
int file2byte;
FileStream fs1;
FileStream fs2;
// Open the two files.
fs1 = new FileStream(file1, FileMode.Open);
fs2 = new FileStream(file2, FileMode.Open);
// Check the file sizes. If they are not the same, the files
// are not the same.
if (fs1.Length != fs2.Length)
{
// Close the files
fs1.Close();
fs2.Close();
// Return false to indicate files are different
return false;
}
do
{
// Read one byte from each file.
file1byte = fs1.ReadByte();
file2byte = fs2.ReadByte();
}
while ((file1byte == file2byte) && (file1byte != -1));
// Close the files.
fs1.Close();
fs2.Close();
// Return the success of the comparison. "file1byte" is
// equal to "file2byte" at this point only if the files are
// the same.
return ((file1byte - file2byte) == 0);
}
// Incredibly, there isn't a byte compare function in .NET
static bool ByteArraysEqual(byte[] data1, byte[] data2)
{ // Thanks to Jon Skeet http://www.pobox.com/~skeet
// If both are null, they're equal
if (data1 == null && data2 == null)
{
return true;
}
// If either but not both are null, they're not equal
if (data1 == null || data2 == null)
{
return false;
}
if (data1.Length != data2.Length)
{
return false;
}
for (int i = 0; i < data1.Length; i++)
{
if (data1[i] != data2[i])
{
return false;
}
}
return true;
}
/// <summary>
/// Concatenate byte arrays a and b
/// </summary>
/// <param name="a">Array a</param>
/// <param name="b">Array b</param>
/// <returns>a concat b</returns>
static byte[] ByteArraysConcat(byte[] a, byte[] b)
{
int len = a.Length + b.Length;
byte[] c = new byte[len];
a.CopyTo(c, 0);
b.CopyTo(c, a.Length);
return c;
}
//**********************
// HOUSEKEEPING STUFF...
//**********************
static string SetupTestDirectory()
{
string subdir;
//**************************************************
// Check we have required files in local directory *
//**************************************************
string assemblyFile = Assembly.GetExecutingAssembly().Location;
string assemblyDir = Path.GetDirectoryName(assemblyFile);
Console.WriteLine("Local directory is '{0}'.", assemblyDir);
//*************************************************
// Create a test sub-directory with a random name,
// copy these test files to it, and work in that sub-directory
//*************************************************
subdir = "apitest." + Cnv.ToHex(Rng.NonceBytes(4));
Console.WriteLine("Creating test sub-directory '{0}'", subdir);
System.IO.Directory.CreateDirectory(subdir);
// Change current working directory to sub-dir
System.IO.Directory.SetCurrentDirectory(subdir);
Console.WriteLine("CWD is " + System.IO.Directory.GetCurrentDirectory());
return subdir;
}
//*********************************************************
// Put CWD back to parent and offer to remove the test dir
//*********************************************************
static void RestoreDirectory(string subdir, bool askDelete)
{
string s;
System.IO.Directory.SetCurrentDirectory("..");
Console.WriteLine("\nCWD reset to " + System.IO.Directory.GetCurrentDirectory());
if (askDelete)
{
Console.Write("The temp test directory '{0}' was created by this program.\nDo you want to remove it? ([Y]/N) ", subdir);
s = Console.ReadLine();
if ("N" != s && "n" != s)
{
// Remove directory
Console.WriteLine("Removing test directory...");
System.IO.Directory.Delete(subdir, true);
}
else
{
Console.WriteLine("Temp directory '{0}' left in place.", subdir);
}
}
else
{
// Remove directory regardless
Console.WriteLine("Removing test directory '{0}'", subdir);
System.IO.Directory.Delete(subdir, true);
}
}
}
}