Signing content with GOST algorithms in NodeJS

comments

There is a few difficulties in how to start signing content in NodeJS with GOST algorithms. Let's fight with them.

Configuring OpenSSL

NodeJS uses OpenSSL under the hood and can do all the things that OpenSSL do. OpenSSL has ccgost engine with GOST algorighms, they are turned off by default. But you can turn it on manually.

Open openssl.cnf file in your favorite editor (the path is /etc/ssl/openssl.cnf in Linux and <OpenSSL-Installation-Directory>\bin\openssl.cnf in Windows).

Add following line just in first line of config:

openssl_conf=openssl_def

then add following lines in the end of the file:

      [openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
      
In Windows you'll need additional dynamic_path in gost_section:
      [openssl_def]
engines = engine_section

[engine_section]
gost = gost_section

[gost_section]
dynamic_path=gost
default_algorithms = ALL
CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
      
Note that I'm not specifying full path here, because of gost.dll lying next to openssl.exe and it's enough due to dynamic-link library search order. Anyway, you can specify full path to gost.dll here too.

You can verify OpenSSL configuration:

      > openssl ciphers | tr ':' '\n' | grep GOST
GOST2001-GOST89-GOST89
GOST94-GOST89-GOST89

> openssl list-message-digest-algorithms | grep gost
gost-mac
md_gost94
gost-mac
md_gost94

> openssl list-cipher-algorithms | grep gost
gost89
gost89
gost89-cnt
      
      > openssl list-message-digest-algorithms | findstr gost
gost-mac
md_gost94
gost-mac
md_gost94

> openssl list-cipher-algorithms | findstr gost
gost89
gost89
gost89-cnt
      

Signing with GOST in NodeJS

There is crypto module in NodeJS out of the box. To do signing you should:

const crypto = require('crypto');
const fs = require('fs');

// set engine with GOST support (you need execute it only once on application startup time):
crypto.setEngine('/usr/lib/x86_64-linux-gnu/openssl-1.0.0/engines/libgost.so');

// create Sign class:
const sign = crypto.createSign('md_gost94');

// fill Sign class with the data
sign.update('some data');

// signing the content with private key
var privateKey = fs.readFileSync('privateKey.pem').toString();
var signedContent = sign.sign(privateKey);

Now, signedContent is instance of Buffer class containing signed data.

Note that location of libgost.so may be different in your system. You can find actual location with find / 2> /dev/null | grep libgost command in Linux.

Preparing private and public keys

NodeJS expects private and public keys in PEM format. Usually you can export both keys to PFX container and then convert it to PEM using OpenSSL command line utility:

openssl pkcs12 -in certificate.pfx -out certificate.pem -nodes

After this command, you'll find both keys in the certificate.pem file in base64 encoding.

Signing verification in NodeJS

Verification in NodeJS is very similar to signing:

// create Verify class
var verify = crypto.createVerify('md_gost94');

// fill it with data
verify.update('some data');

// verify signature with public key
var publicKey = fs.readFileSync("publicKey.pem").toString();
var verificationResult = verify.verify(publicKey, signature);

Now, verificationResult will contain true if signature is valid and false in other cases.

Summary

To start signing you should turn on GOST support in OpenSSL, use GOST engine in NodeJS and use private key in PEM format.

Happy signing!

Comments