When You Just Don’t Trust FIPS 186, There’s GOST R3410

Like it or not; we live in a digital world that is dominated by US companies and standards. For many, that is a good thing, as researchers…

When You Just Don’t Trust FIPS 186, There’s GOST R3410

Like it or not; we live in a digital world that is dominated by US companies and standards. For many, that is a good thing, as researchers and industry experts have generally worked together to produce standards that others can comply with. And, so, in cybersecurity, this is often driven by RFCs the IEEE and by NIST. With digital signatures, this often focuses on the FIPS 186 standard, which defines RSA, ECDSA and EdDSA. But what if you don’t trust NIST?

And so, while many comply with the NIST-defined FIPS 186 standard for digital signatures, there is a Russian Federal standard for digital signatures: GOST R 34.10–2012. This is defined in RFC 7091 [here], and is often just known as R3410 signing.

Although originally defined for DSA, it has been upgraded to support elliptic curves. An example of this is with the Cost 3410–256 parameterA set [here]:

Message: Here
Curve: Tc26-Gost-3410-12-256-paramSetA
=== ECGost Parameters ==
G: (91e38443a5e82c0d880923425712b2bb658b9196932e02c78b2582fe742daa28,32879423ab1a0375895786c4bb46e9565fde0b5344766740af268adb32322e5c,1,c2173f1513981673af4892c23035a27ce25e2013bf95aa33b22c656f277e7335)
N: 28948022309329048855892746252171976963338560298092253442512153408785530358887
A: c2173f1513981673af4892c23035a27ce25e2013bf95aa33b22c656f277e7335
B: 295f9bae7428ed9ccc20e7c359a9d41a22fccd9108e17bf7ba9337a6f8ae9513
Order: 28948022309329048855892746252171976963338560298092253442512153408785530358887

=== ECGost Key ==
Name: ECDSA
Private key: 28552591383538199108967286721909683054617972901923876965459618430127677271246
Public key (x): 8dcd50af2f30c1876655da16c6077dfe359bf93dbc7aaabfe9595808f9003b2
Public key (y): bc93faf938363f7af5ebbf8cfe9e70c86e9ac4ccf0f8c63516260f86422894d1

=== ECGost Signature ==
r=8653876478677873335090094965067968185310085762586087699405025922993549682718, s=21109347980004811843825277752414671128169306358511461548277974689330278109728
Verified: True

Our signature is defined with (r,s). and where the base point is at (91e38443a5e82c0d880923425712b2bb658b9196932e02c78b2582fe742daa28,32879423ab1a0375895786c4bb46e9565fde0b5344766740af268adb32322e5c,1,c2173f1513981673af4892c23035a27ce25e2013bf95aa33b22c656f277e733). The values of A and B are defined for the curve so that:

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

and the order is the total number of points on the curve.

Bouncy Castle is one library which supports GOST 3410, and here is some sample code for generating a random key pair [here]:

namespace DSA
{
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.Crypto.Generators;
using System.Text;
using Org.BouncyCastle.Crypto.Signers;
using Microsoft.VisualBasic;
using Org.BouncyCastle.Asn1.CryptoPro;

class Program
{
static void Main(string[] args)
{

string str="Hello";
string curvename="GostR3410-2001-CryptoPro-A";

if (args.Length >0) str=args[0];
if (args.Length >1) curvename=args[1];

byte[] data = Encoding.ASCII.GetBytes(str);



var ecParams = ECGost3410NamedCurves.GetByName(curvename);
/*
GostR3410-2001-CryptoPro-A
GostR3410-2001-CryptoPro-B
GostR3410-2001-CryptoPro-C
GostR3410-2001-CryptoPro-XchA
GostR3410-2001-CryptoPro-XchB
Tc26-Gost-3410-12-256-paramSetA
Tc26-Gost-3410-12-512-paramSetA
Tc26-Gost-3410-12-512-paramSetB
Tc26-Gost-3410-12-512-paramSetC
*/




var curveparam = new ECDomainParameters(ecParams.Curve, ecParams.G, ecParams.N, ecParams.H, ecParams.GetSeed());


Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters keygenParams = new Org.BouncyCastle.Crypto.Parameters.ECKeyGenerationParameters (curveparam, new SecureRandom());

Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator generator = new Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator("ECDSA");
generator.Init(keygenParams);

var keyPair = generator.GenerateKeyPair();


AsymmetricCipherKeyPair pair = generator.GenerateKeyPair();


var signEng = new ECGost3410Signer ();


signEng.Init(true, pair.Private);

var sig = signEng.GenerateSignature(data);

signEng.Init(false, pair.Public);

var rtn = signEng.VerifySignature(data,sig[0],sig[1]);

var priv =(ECPrivateKeyParameters)pair.Private;
var pub =(ECPublicKeyParameters)pair.Public;

Console.WriteLine ("Message: {0}",str);
Console.WriteLine ("Curve: {0}",curvename);

Console.WriteLine ("=== ECGost Parameters ==");
Console.WriteLine ("G: {0}",keygenParams.DomainParameters.G);
Console.WriteLine ("N: {0}",keygenParams.DomainParameters.N);
Console.WriteLine ("A: {0}",keygenParams.DomainParameters.Curve.A);
Console.WriteLine ("B: {0}",keygenParams.DomainParameters.Curve.B);
Console.WriteLine ("Order: {0}",keygenParams.DomainParameters.Curve.Order);



Console.WriteLine ("\n=== ECGost Key ==");
Console.WriteLine ("Name: {0}",priv.AlgorithmName);
Console.WriteLine ("Private key: {0}",priv.D);
Console.WriteLine ("Public key (x): {0}",pub.Q.AffineXCoord);
Console.WriteLine ("Public key (y): {0}",pub.Q.AffineYCoord);


Console.WriteLine ("\n=== ECGost Signature ==");
Console.WriteLine ("r={0}, s={1}",sig[0],sig[1]);
Console.WriteLine ("Verified: {0}",rtn);

}
}
}

and a sample run for 512 bit keys [here]:

Message: Here
Curve: Tc26-Gost-3410-12-512-paramSetA
=== ECGost Parameters ==
G: (3,7503cfe87a836ae3a61b8816e25450e6ce5e1c93acf1abc1778064fdcbefa921df1626be4fd036e93d75e6a50e3a41e98028fe5fc235f5b889a589cb5215f2a4,1,fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc4)
N: 13407807929942597099574024998205846127479365820592393377723561443721764030073449232318290585817636498049628612556596899500625279906416653993875474742293109
A: fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc4
B: e8c2505dedfc86ddc1bd0b2b6667f1da34b82574761cb0e879bd081cfd0b6265ee3cb090f30d27614cb4574010da90dd862ef9d4ebee4761503190785a71c760
Order: 13407807929942597099574024998205846127479365820592393377723561443721764030073449232318290585817636498049628612556596899500625279906416653993875474742293109

=== ECGost Key ==
Name: ECDSA
Private key: 11363003372185445090903353635761910835767971080783397279289382763561923510463957241476254714337994243043366602732237378342578007047820642243546664003835763
Public key (x): f6f1b20f4f223574de3053a8e157bbc9e8db863b065eccfac7dbb32d9f4b30e86eeaad789266c11a25e12cd1090f9c2bc5cf76568e45e4564e756f2551b8d0c5
Public key (y): 1580b86d2514d04961d2a6e577e0e28685ebaa6309070cf2205c0ad939fcd4e13019403ced2901964ba21aa8d64c11cce6c60b0cd711166c824a1d450f54ad14

=== ECGost Signature ==
r=11223546636990725308706201682625212044666336896397889659525268666940879376601697736460999765134726307283793182708655012151194165136929965718253299540974625, s=8059798906505843230208386458681008096841981080600241846297409143569916935034056728273423311543903512536851965756803317124714590260492933181965997313666712
Verified: True