ASCON was designed by Christoph Dobraunig, Maria Eichlseder, Florian Mendel and Martin Schläffer from Graz University of Technology, Infineon Technologies, and Radboud University. It is both a light-weight hashing and encryption method. ASCON uses a single lightweight permutation with a Sponge-based modes of operation and a SPN (substitution–permutation network) permutation. Overall it has an easy method of implementing within hardware (2.6 gate equivalents) and software. A 5-bit S-box (as used in Keccak’s S-box core) is used to enable a light weight approach and it has no known side-channel attacks. It can also achieve high throughputs such as throughputs of between 4.9 and 7.3 Gbps. It stores its current state with 320 bits. Overall, ASCON won the NIST competition for a light-weight cryptography standard.This implementation using the Bouncy Castle with C#. With this we must support a 64-bit (or larger) IV and additional data [Download code].
ASCON Encryption with Bouncy Castle and C# |
Coding
First we create a folder named "bc_ascon", 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 ASCON { using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; class Program { static void Main(string[] args) { var msg="Hello"; var add=""; var iv="00112233445566778899AABBCCDDEEFF00"; if (args.Length >0) msg=args[0]; if (args.Length >1) add=args[1]; if (args.Length >2) iv=args[2]; try { var plainTextData=System.Text.Encoding.UTF8.GetBytes(msg); AsconEngine cipher = new AsconEngine(AsconEngine.AsconParameters.ascon128a); int macSize = 8*cipher.GetKeyBytesSize(); byte[] nonce = new byte[cipher.GetIVBytesSize()]; Array.Copy(Convert.FromHexString(iv), nonce, cipher.GetIVBytesSize()); byte[] associatedText =System.Text.Encoding.UTF8.GetBytes(add); CipherKeyGenerator keyGen = new CipherKeyGenerator(); keyGen.Init(new KeyGenerationParameters(new SecureRandom(), 128)); KeyParameter keyParam = keyGen.GenerateKeyParameter(); AeadParameters keyParamAead = new AeadParameters(keyParam, macSize,nonce, associatedText); cipher.Init(true,keyParamAead); int outputSize = cipher.GetOutputSize(plainTextData.Length); byte[] cipherTextData = new byte[outputSize]; int result = cipher.ProcessBytes(plainTextData, 0, plainTextData.Length, cipherTextData, 0); cipher.DoFinal(cipherTextData,result); var rtn = cipherTextData; // Decrypt cipher.Init(false,keyParamAead); outputSize = cipher.GetOutputSize(cipherTextData.Length); byte[] plainRes = new byte[outputSize]; result = cipher.ProcessBytes(cipherTextData, 0, cipherTextData.Length, plainRes, 0); cipher.DoFinal(plainRes,result); var pln = plainRes; Console.WriteLine("=== ASCON Cipher (ASCON 128a) =="); Console.WriteLine("Message: {0}",msg); Console.WriteLine("IV size: {0} bytes",cipher.GetIVBytesSize()); Console.WriteLine("IV: {0}",iv); Console.WriteLine("Key: {0}",Convert.ToHexString(keyParam.GetKey())); Console.WriteLine("Additional data: {0}",add); Console.WriteLine("\nCipher: {0}",Convert.ToHexString(rtn)); Console.WriteLine("Cipher: {0}",Convert.ToBase64String(rtn)); Console.WriteLine("\nPlain: {0}",System.Text.Encoding.UTF8.GetString(pln)); } catch (Exception e) { Console.WriteLine("Error: {0}",e.Message); } } } }
A sample run is:
=== ASCON Cipher (ASCON 128a) == Message: Hello 1234 IV size: 16 IV: 00112233445566778899AABBCCDDEEFF Additional data: test Cipher: 136F482D6BB69062296597109D8313488C149C06DCF93EA1F8F9 Cipher: E29ILWu2kGIpZZcQnYMTSIwUnAbc+T6h+Pk= Plain: Hello 1234
Notice that the cipher stream is the same length as the plaintext stream.