Node-fore can't verify signature from OPENSSL

107 Views Asked by At

i'll try verify signature from opensll generate with command : openssl pkeyutl -in mess.txt -out sign.txt -inkey priv.pem -sign and my script:

const fs = require('fs');
const forge = require('node-forge');

function verifySignature(publicKeyPem, message, signatureFile) {
  try {
    const publicKey = forge.pki.publicKeyFromPem(publicKeyPem);
    const signatureBytes = fs.readFileSync(signatureFile,'binary');

    const md = forge.md.sha256.create();
    md.update(message);

    const verified = publicKey.verify(md.digest().getBytes(), signatureBytes);

    if (verified) {
      console.log('Signature is valid. Message is authenticated.');
    } else {
      console.error('Signature is invalid. Message could not be authenticated.');
    }
  } catch (error) {
    console.error('Error during signature verification:', error);
  }
}

const publicKeyPem = fs.readFileSync('pub.pem', 'utf-8');
const messageToSign = fs.readFileSync('mess.txt', 'utf-8');
const signatureFile = 'sign.txt';

verifySignature(publicKeyPem, messageToSign, signatureFile);

Error: Too few bytes to read ASN.1 value.

how can i fix this issued

1

There are 1 best solutions below

0
Topaco On

So that verification is successful, the message itself (and not the message hash) must be passed in the first parameter of verify() and 'NONE' must be specified as scheme in the third parameter (so that the default value RSASSA-PKCS1-V1_5 is not used), as in the following sample code (the signature was generated with your OpenSSL statement):

function verifySignature(publicKeyPem, message, signatureFile) {
    try {
        const publicKey = forge.pki.publicKeyFromPem(publicKeyPem);
        const verified = publicKey.verify(message, signatureBytes, 'NONE');
        if (verified) {
            console.log('Signature is valid. Message is authenticated.');
        } else {
            console.error('Signature is invalid. Message could not be authenticated.');
          }   
    } catch (error) {
        console.error('Error during signature verification:', error);
    }
}

const publicKeyPem = `-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAunF5aDa6HCfLMMI/MZLT
5hDk304CU+ypFMFiBjowQdUMQKYHZ+fklB7GpLxCatxYJ/hZ7rjfHH3Klq20/Y1E
bYDRopyTSfkrTzPzwsX4Ur/l25CtdQldhHCTMgwf/Ev/buBNobfzdZE+Dhdv5lQw
KtjI43lDKvAi5kEet2TFwfJcJrBiRJeEcLfVgWTXGRQn7gngWKykUu5rS83eAU1x
H9FLojQfyia89/EykiOO7/3UWwd+MATZ9HLjSx2/Lf3g2jr81eifEmYDlri/OZp4
OhZu+0Bo1LXloCTe+vmIQ2YCX7EatUOuyQMt2Vwx4uV+d/A3DP6PtMGBKpF8St4i
GwIDAQAB
-----END PUBLIC KEY-----`;
const messageToSign = 'some test data signed without hashing';
const signatureBytes = forge.util.decode64('jmcuQ0vROjdre1S8HkiH/jUYgxQX3n6IR+VsDq99Mq3yewbNxxbrevQ01widgB/iUws1ifavSxNl+Bhyo063ehQVkDfejE1JbdGIzMCqMl8CRK7TpCRSSXzGzL10EpYMK/kaYm0xNc2DH6obG5r7pho+qWmlKFAEolbYNHx70G+GZs0Fr5xnDNEfTKZjDI1X6RT0CPCq7IDVRsjdQJarAj1ngJhYgR3RHY0qdo+7nu5gzGCgpFBCNETafjtMmRs/B5wrS1Hn2ns4m3vjZE0lzbpVVpLEeHIXKokkW7xd9nqo/qmTbtuLcYXpItNEMxMqLLwuUSO+CGcjGiL9Fa9/Ow==');
verifySignature(publicKeyPem, messageToSign, signatureBytes);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/forge.min.js"></script>

With these changes, verification is successful.

Explanation:
The OpenSSL statement pads and signs the message directly and not the DER encoding of the DigestInfo value (consisting of the OID of the digest and the hash value of the message).
For this reason, the message to be verified must not be hashed in the JavaScript code. And 'NONE' specifies that the data determined from the signature represents the message itself and not the DER encoding of the DigestInfo value and is to be processed accordingly during verification.


Comparison with RSASSA-PKCS1-v1_5:
Note that before padding and signing, the message is commonly hashed and the resulting hash is completed to the DER encoding of the DigestInfo value, as described in RFC8017.
Your OpenSSL statement deviates from this. If you want to adhere to the standard, the OpenSSL statement must be adapted.
Here are a few possibilities (using SHA256 as an example):

  • Explicitly hash the message with SHA256 (messHash.txt) and add -pkeyopt digest:sha256 to the OpenSSL statement:
    openssl pkeyutl -in messHash.txt -out sign.bin -inkey private.pem -sign -pkeyopt digest:sha256
    
  • Add -rawin -digest sha256 to the OpenSSL satement (from v3.0):
    openssl pkeyutl -in mess.txt -out sign.bin -inkey private.pem -rawin -digest sha256
    
  • Use openssl-dgst:
    openssl dgst -sha256 -sign private.pem -out sign.bin mess.txt
    

With these changes, it is not required to adapt the JavaScript code.