HC-256 and a Bouncy Castle

Why should you just learn about the most common methods? As a researcher, you should never fully dismiss any method, as methods that might…

HC-256 and a Bouncy Castle

Why should you just learn about the most common methods? As a researcher, you should never fully dismiss any method, as methods that might not be popular now may come back and be ready to take on new challenges. Also, a method will have been created for a purpose, and reading the paper will show how the authors have addressed the challenge. It’s basically a journey of discovery and will typically add your knowledge.

And, so, I’ve been reading this paper [here]:

The HC-256 method was created in 2004 and uses a 256-bit key (K) and a 256-bit nonce (IV) value. Internally, it has two secret tables: P and Q, and where each table has 1,024 32-bit words. Basically, these represent state values, and each change of state will update one of the entries of the table, and which uses a non-linear update function. Thus, after 2,048 state changes, every element of the tables will have been updated. We then derive the final has by taking a SHA-256, but where we use the P and Q tables as S-boxes. Overall, it is a fast-stream cipher with just four CPU cycles per byte.

The basic functions that HC-256 uses are simple and involve either EX-OR, mod, add or bit shift operations:

As we have a stream cipher, we basically take the key and the IV, and expand into a key stream (s). The cipher is then:

c = p ^ s

and where we EX-OR each bit of the plaintext (p) with the bits in the keystream (s), and generate a cipher stream (c ). In order to recover the plaintext, we just EX-OR again with the key stream:

p = c ^ s

Key and IV setup

The initialization phase provides an expansion of the 256-bit key into the P and Q tables. With this, we take the key and the IV, and split them up into eight 32-bit values (K_0 … K_7, and IV_0 … IV_7). Next, we compute W_i and then use these values to fill the P and Q tables:

Figure [Ref]

Keystream expansion

In this stage, we generate the key stream (s). Each step will update one of the entries in either the P table or the Q table:

Figure [Ref]

This will then create the S-box values for the SHA-256 operation. Once generated, the plaintext and cipher stream is just EX-ORed with the expanded key stream.

Coding

The outline code using C# is [here]:



namespace HC256
{

using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
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="00112233445566778899AABBCCDDEEFF";
var size=256;

if (args.Length >0) msg=args[0];
if (args.Length >1) iv=args[1];




try {




var plainTextData=System.Text.Encoding.UTF8.GetBytes(msg);

var cipher = new HC256Engine();


byte[] nonce = new byte[16];
Array.Copy(Convert.FromHexString(iv), nonce, 16);


CipherKeyGenerator keyGen = new CipherKeyGenerator();
keyGen.Init(new KeyGenerationParameters(new SecureRandom(), size));
KeyParameter keyParam = keyGen.GenerateKeyParameter();
ParametersWithIV keyParamIV = new ParametersWithIV(keyParam,nonce);



cipher.Init(true,keyParamIV);
int outputSize = plainTextData.Length;
byte[] cipherTextData = new byte[outputSize];
cipher.ProcessBytes(plainTextData, 0, plainTextData.Length, cipherTextData, 0);
var rtn = cipherTextData;


// Decrypt
cipher.Init(false,keyParamIV);

outputSize = cipherTextData.Length;
plainTextData = new byte[outputSize];

cipher.ProcessBytes(cipherTextData, 0, cipherTextData.Length,plainTextData, 0);

var pln=plainTextData;


Console.WriteLine("=== {0} ==",cipher.AlgorithmName);
Console.WriteLine("Message:\t\t{0}",msg);
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 test run is [here]:

=== HC-256 ==
Message: Hello 123
IV: 00112233445566778899AABBCCDDEEFF00
Key size: 256 bits
Key: 7577573F9B7F0A05E16B8C61CD06261145CD2A9FB0C3C54E60ED53FB2DE6D93E [dXdXP5t/CgXha4xhzQYmEUXNKp+ww8VOYO1T+y3m2T4=]

Cipher (hex): 2EFFE462B2DC4AE106
Cipher (Base64): Lv/kYrLcSuEG

Plain: Hello 123

Conclusions

HC-256 is a great example of a fast and secure cipher. If you have time, please read more [here] and you can discover the practical implementation here:

https://asecuritysite.com/bouncy/bc_ciphers_hc256