The ShangMi (SM)4 Cipher

And, so, NIST has defined AES as the standard for symmetric key encryption. But, NIST was pinpointed as possibly pushing a cipher with an…

The ShangMi (SM)4 Cipher

And, so, NIST has defined AES as the standard for symmetric key encryption. But, NIST was pinpointed as possibly pushing a cipher with an NSA backdoor. For companies in China, the ShāngMì (SM) series of ciphers provide one alternative for TLS 1.3 integration and Wireless authentication. SM2 defines authentication, SM3 defines a hashing function, and SM4 for encryption. SM4 was developed by Lü Shuwang in 2007 and became a national standard (GB/T 32907–2016) in 2016. It has also been defined in RFC 8998 [here]:

With the SM4 cipher, we have a block size of 128 bits and a 128-bit encryption key. Each block of data has 32 rounds of processing. Overall, we can add a salt value of 128 bits in an IV (Initialisation Vector).

We can code with [here]:

The following is the coding:

namespace SM4
{
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 SM4Engine();

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

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();

cipherMode.Init(true,keyParam);
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 [here]:

=== SM4 ==
Message: Hello 123
Block size: 128 bits
Mode: ECB
IV: 00112233445566778899AABBCCDDEEFF00
Key size: 128 bits
Key: 4CFA20685BE4D44CE5907C05FDFECC8D [TPogaFvk1EzlkHwF/f7MjQ==]

Cipher (hex): 3A0D96CCE2D782DFF832F5D09C0FA7F2
Cipher (Base64): Og2WzOLXgt/4MvXQnA+n8g==

Plain: Hello 123

SM4 is also a core part of OpenSSL 3.x:

https://asecuritysite.com/openssl/openssl3

Conclusions

While mandatory in China, SM4 provides an alternative to AES and ChaCha20.