Node js e Firma Digitale

Parliamo ancora di crittografia asimmetrica. Ecco alcuni utili script per la generazione delle chiavi, la firma digitale e la verifica.

Oggi pubblico alcuni semplici programmi, che girano sotto node js. Eccoli qui:

  1. Il file “gen_keys_rsa_dsa.js” che genera una coppia di chiavi, pubblica e privata, con l’algoritmo RSA oppure con il DSA.
  2. Il file “gen_keys_secp256k1.js” che genera una coppia di chiavi, con l’algoritmo ECDSA ( Algoritmo di firma digitale a curva ellittica ) con la curva “secp256k1”.
  3. Il file “sign-file.js” che firma digitalmente un qualsiasi file e “verify-file.js” che verifica la firma.

Prima di pubblicare i sorgenti dei suddetti files, intendo spiegare il procedimento per firmare digitalmente un file.

Firmare digitalmente un file: procedimento.

Ecco il procedimento.

1) Genero una coppia di chiavi ( chiave privata e chiave pubblica ) con il file “gen_keys_rsa_dsa.js” ( per algoritmo RSA oppure DSA ) oppure con il file “gen_keys_secp256k1.js” ( per algoritmo ECDSA, curva secp256k1 )

2) Firmo digitalmente il file “infinito.gif” con “sign-file.js”

3) Verifico la firma digitale con “verify-file.js”

ESEMPIO

Per prima cosa con Blocco Note genero il file “qui.txt” il cui contenuto sarà semplicemente “cmd”. Rinomino “qui.bat”, poi doppio click su “qui.bat” ed entro nel “PROMPT” con CMD.EXE. Poi seguo nell’ordine i punti (1) (2) e (3).

1) PROMPT> node gen_keys_secp256k1.js > chiavi.txt

Apro con NotePad il file “chiavi.txt” e salvo la chiave privata in “privata.pem” e la pubblica in “pubblica.pem”

2) PROMPT> node sign-file.js privata.pem pubblica.pem infinito.gif infinito.gif.firma

3) PROMPT> node verify-file.js pubblica.pem infinito.gif infinito.gif.firma

IL risultato “true” significa: “FIRMA VERIFICATA”.

I sorgenti

File “gen_keys_rsa_dsa.js”

var crittografia = require('crypto');
var algoritmo = 'rsa'; // oppure 'dsa'
var frasesegreta = 'La mia frase segreta';

var lunghezzamodulo = { modulusLength:4096,
                          publicKeyEncoding: {
                                                type: 'spki',
                                              format: 'pem',
                                             },
                         privateKeyEncoding: {
                                                type: 'pkcs8',
                                              format: 'pem',
                                              cipher: 'aes-256-cbc',
                                          passphrase: frasesegreta,
                                             }
                      };


var chiavi = crittografia.generateKeyPairSync(algoritmo, lunghezzamodulo);

console.log("%s\n\n\n",chiavi.privateKey);
console.log("%s\n",chiavi.publicKey);

File “gen_keys_secp256k1.js”

// crypto.generateKeyPairSync( ‘ec’, {namedCurve:'stringa',publicKeyEncoding:'stringa',privateKeyEncoding:Object} )

var crittografia = require('crypto');
var algoritmo = 'ec';
var frasesegreta = 'La mia frase segreta';

        var oggetto = { namedCurve:'secp256k1',
                          publicKeyEncoding: {
                                                type: 'spki',
                                              format: 'pem',
                                             },
                         privateKeyEncoding: {
                                                type: 'pkcs8',
                                              format: 'pem',
                                              cipher: 'aes-256-cbc',
                                          passphrase: frasesegreta,
                                             }
                      };


var chiavi_ec = crittografia.generateKeyPairSync(algoritmo, oggetto);

console.log("%s\n\n\n",chiavi_ec.privateKey);
console.log("%s\n",chiavi_ec.publicKey);

Il codice è molto simile al precedente, ma genera le chiavi con l’algoritmo a “curva ellittica”.

File “sign-file.js”

// > node sign-file.js chiaveprivata chiavepubblica dafirmare firma

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

var frasesegreta = 'La mia frase segreta';

const myArgs = process.argv.slice(2);

const privata = fs.readFileSync(myArgs[0],'utf8');

const pubblica = fs.readFileSync(myArgs[1],'utf8');

const oggetto = {key:privata,format:'pem',type:'pkcs8',passphrase:frasesegreta,encoding:'aes-256-cbc'};

publicKey = crypto.createPublicKey(pubblica);

privateKey = crypto.createPrivateKey(oggetto);

var firmare = fs.readFileSync(myArgs[2],'binary');

const sign = crypto.createSign('SHA256');
sign.update(firmare);
sign.end();
const signature = sign.sign(privateKey);

fs.writeFileSync(myArgs[3], signature.toString('base64'));

Ed infine il file per verificare la firma: “verify-file.js”

// > node verify-file.js chiavepubblica daverificare firma

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

const myArgs = process.argv.slice(2);

const pubblica = fs.readFileSync(myArgs[0],'utf8');

publicKey = crypto.createPublicKey(pubblica);

var verificare = fs.readFileSync(myArgs[1],'binary');

const firma = fs.readFileSync(myArgs[2], 'binary');

console.log(firma);

const verify = crypto.createVerify('SHA256');
verify.update(verificare);
verify.end();
console.log(verify.verify(publicKey, Buffer.from(firma,'base64')));

Ecco il file gif utilizzato per gli esperimenti di firma digitale e di verifica dell’autenticità della firma stessa.

Cliccare col tasto destro e scaricare “download.gif” ( eventualmente rinominare “infinito.gif”, ma non è necessario).

Spero che vi sia piaciuto l’articolo e, soprattutto, che sia stato utile.

Alla prossima.

Andrea Paolini ( Amministratore di questo Blog )