Bruce Schneier, John Kelsey, Doug Whiting, David Wagner, Chris Hall, and Niels Ferguson created Twofish as a general-purpose private key encryption algorithm and is patent free. It uses either a 128-, 192- or a 256-bit encryption key, and has a block size of 128 bits. Overall, it uses a Feistel structure and pre-computed key-dependent S-boxes. Twofish was one of the finalists for the NIST AES competition, and is related to the Blowfish method. It is also included in the OpenPGP standard (RFC 4880).
Twofish with Bouncy Castle and C# |
Coding
First we create a folder named "bc_skipjack", and then go into that folder.We can create a Dotnet console project for .NET 8.0 with:
dotnet new console --framework net8.0
This produces a Csproject file of:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net8.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> </Project>
We then add the latest Bouncy Castle library:
dotnet add package BouncyCastle.Cryptography --version 2.2.1
The following is the coding:
namespace Serpent { using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Paddings; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; class Program { static void Main(string[] args) { var msg="Hello"; var iv="00112233445566778899AABBCCDDEEFF00"; var size=128; var mode="CBC"; if (args.Length >0) msg=args[0]; if (args.Length >1) iv=args[1]; if (args.Length >2) size=Convert.ToInt32(args[2]); if (args.Length >3) mode=args[3]; try { var plainTextData=System.Text.Encoding.UTF8.GetBytes(msg); var cipher = new Org.BouncyCastle.Crypto.Engines.TwofishEngine(); byte[] nonce = new byte[16]; Array.Copy(Convert.FromHexString(iv), nonce, 16); PaddedBufferedBlockCipher cipherMode = new PaddedBufferedBlockCipher(new CbcBlockCipher(cipher), new Pkcs7Padding()); if (mode=="ECB") cipherMode = new PaddedBufferedBlockCipher(new EcbBlockCipher(cipher), new Pkcs7Padding()); else if (mode=="CFB") cipherMode = new PaddedBufferedBlockCipher(new CfbBlockCipher (cipher,128 ), new Pkcs7Padding()); CipherKeyGenerator keyGen = new CipherKeyGenerator(); keyGen.Init(new KeyGenerationParameters(new SecureRandom(), size)); KeyParameter keyParam = keyGen.GenerateKeyParameter(); ICipherParameters keyParamIV = new ParametersWithIV(keyParam,nonce); if (mode=="ECB") { cipherMode.Init(true,keyParam); } else { cipherMode.Init(true,keyParamIV); } int outputSize = cipherMode.GetOutputSize(plainTextData.Length); byte[] cipherTextData = new byte[outputSize]; int result = cipherMode.ProcessBytes(plainTextData, 0, plainTextData.Length, cipherTextData, 0); cipherMode.DoFinal(cipherTextData, result); var rtn = cipherTextData; // Decrypt cipherMode.Init(false,keyParam); outputSize = cipherMode.GetOutputSize(cipherTextData.Length); plainTextData = new byte[outputSize]; result = cipherMode.ProcessBytes(cipherTextData, 0, cipherTextData.Length,plainTextData, 0); cipherMode.DoFinal(plainTextData, result); var pln=plainTextData; Console.WriteLine("=== {0} ==",cipher.AlgorithmName); Console.WriteLine("Message:\t\t{0}",msg); Console.WriteLine("Block size:\t\t{0} bits",cipher.GetBlockSize()*8); Console.WriteLine("Mode:\t\t\t{0}",mode); Console.WriteLine("IV:\t\t\t{0}",iv); Console.WriteLine("Key size:\t\t{0} bits",size); Console.WriteLine("Key:\t\t\t{0} [{1}]",Convert.ToHexString(keyParam.GetKey()),Convert.ToBase64String(keyParam.GetKey())); Console.WriteLine("\nCipher (hex):\t\t{0}",Convert.ToHexString(rtn)); Console.WriteLine("Cipher (Base64):\t{0}",Convert.ToBase64String(rtn)); Console.WriteLine("\nPlain:\t\t\t{0}",System.Text.Encoding.ASCII.GetString(pln).TrimEnd('\0')); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
A sample run is:
=== Twofish == Message: Hello 123 Block size: 128 bits Mode: ECB IV: 00112233445566778899AABBCCDDEEFF00 Key size: 128 bits Key: B7F207F07FA064D468FCE0E6F73281F5 [t/IH8H+gZNRo/ODm9zKB9Q==] Cipher (hex): CEAEA3047522B2F11EE447572DEEE91B Cipher (Base64): zq6jBHUisvEe5EdXLe7pGw== Plain: Hello 123