So What Is SM2?

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

So What Is SM2?

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. With this SM2 defines public key encryption, SM3 defines a hashing function, and SM4 for encryption. Overall, SM4 was developed by Lü Shuwang in 2007 and became a national standard (GB/T 32907–2016) in 2016 [RFC 8998].

In normal elliptic curve signing, we use secp256k1 (as used in Bitcoin and Ethereum) and NIST P-256. So what’s the equivalent for Chinese ciphers? Well, SM2 is a public key method that is defined by the Chinese Commercial Cryptography Administration Office.

ECC

With elliptic curve cryptography, we start with a definition for the curve, such as:

y²=x³+ax+b (mod p)

This defines values for a, b and p. Next, we select a base point on the curve (G and generates a random scalar value (D). This is the private key, and where the public key is generated from a point multiplication of

Q=D.G

This results in an (x,y) point on the curve.

Code

First we create a folder named “bc_sm02”, and then go into that folder.We can create a Dotnet console project for .NET 8.0 with:

dotnet new console --framework net8.0

Next we can install the Bouncy Castle library with:

dotnet add package BouncyCastle.Crypto.dll --version 1.8.1

We first need to use the “sm2p256v1” curve type:

X9ECParameters x9ECParameters = GMNamedCurves.GetByName("sm2p256v1");

And then generate the key pair with:

ECDomainParameters sm2Parameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters keygenParams = new Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters (sm2Parameters, new SecureRandom());
Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator generator = new Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator();

generator.Init(keygenParams);
var keyPair = generator.GenerateKeyPair();

Next some code [here]:

namespace SM2
{
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Asn1.X9;

using Org.BouncyCastle.Asn1.GM;

class Program
{

static void Main(string[] args)
{
try {
var curvename="sm2p256v1";
if (args.Length >0) curvename=args[0];

X9ECParameters x9ECParameters = GMNamedCurves.GetByName(curvename);

ECDomainParameters sm2Parameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters keygenParams = new Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters (sm2Parameters, new SecureRandom());
Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator generator = new Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator();

generator.Init(keygenParams);
var keyPair = generator.GenerateKeyPair();
var BobprivateKey = (ECPrivateKeyParameters) keyPair.Private;
var BobpublicKey = (ECPublicKeyParameters) keyPair.Public;
Console.WriteLine("Private key {0}",BobprivateKey.D);
Console.WriteLine("Public key {0}, {1}",BobpublicKey.Q.AffineXCoord,BobpublicKey.Q.AffineYCoord);
Console.WriteLine("\n\n== ECC Parameters {0} == ",curvename);
Console.WriteLine("ECC A={0}, B={1}, Order={2}",sm2Parameters.Curve.A,sm2Parameters.Curve.B,sm2Parameters.Curve.Order);
Console.WriteLine("\nECC N={0}, G={1}, H={2}",keygenParams.DomainParameters.N, keygenParams.DomainParameters.G,keygenParams.DomainParameters.H);


} catch (Exception e) {
Console.WriteLine("Error: {0}",e.Message);
}
}
}
}

A sample run for secp2561 gives [here]:

Private key 56172605536492177223661381434107759735851303136376608757534584160917602287750
Public key e0a4cc044cc675d1b9f214bb769ce299e81d34a70b7066ca3b1fb53f100d62df, 6948f25e86f20dee162a4c30f8cb75133acc97e9f4b0da1d870accd58676713a
== ECC Parameters sm2p256v1 ==
ECC A=fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc, B=28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93, Order=115792089210356248756420345214020892766061623724957744567843809356293439045923
ECC N=115792089210356248756420345214020892766061623724957744567843809356293439045923, G=(32c4ae2c1f1981195f9904466a39c9948fe30bbff2660be1715a4589334c74c7,bc3736a2f4f6779c59bdcee36b692153d0a9877cc62a474002df32e52139f0a0,1,fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc), H=1

We can see that A is equal to fffffffeffffffffffffffffffffffffffffffff00000000fffffffffffffffc, B is 28e9fa9e9d9f5e344d5a9e4bcf6509a7f39789f515ab8f92ddbcbd414d940e93 and the order of the curve is 115792089210356248756420345214020892766061623724957744567843809356293439045923.