Node-fore 无法验证 OPENSSL 的签名

问题描述 投票:0回答:1

我将尝试使用命令验证来自 opensll 生成的签名:

openssl pkeyutl -in mess.txt -out sign.txt -inkey priv.pem -sign
和我的脚本:

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);

错误:字节数太少,无法读取 ASN.1 值。

我该如何解决这个问题

node.js openssl node-forge
1个回答
0
投票

为了验证成功,必须在

verify()
的第一个参数中传递消息本身(而不是消息哈希),并且必须在第三个参数中指定
'NONE'
作为方案(以便使用默认值
RSASSA-PKCS1-V1_5 
未使用),如以下示例代码所示(签名是使用您的 OpenSSL 语句生成的):

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>

完成这些更改后,验证成功。


说明:
OpenSSL 语句直接填充并签署消息,而不是DigestInfo值的 DER 编码(由摘要的 OID 和消息的哈希值组成)。
因此,要验证的消息不得在 JavaScript 代码中进行哈希处理。并且

'NONE'
指定从签名确定的数据代表消息本身,而不是 DigestInfo 值的 DER 编码,并在验证期间进行相应处理。

请注意,在填充和签名之前,通常会对消息进行哈希处理,并将生成的哈希值完成为 DigestInfo 值的 DER 编码,如 RFC8017 中所述。您的 OpenSSL 声明与此不同。如果您想遵守该标准,则必须调整 OpenSSL 声明。
以下是一些可能性(以 SHA256 为例):

  • 使用 SHA256 显式哈希消息 (messHash.txt) 并将
    -pkeyopt digest:sha256
    添加到 OpenSSL 语句中:
    openssl pkeyutl -in messHash.txt -out sign.bin -inkey private.pem -sign -pkeyopt digest:sha256
    
  • -rawin -digest sha256
    添加到 OpenSSL 声明中(从 v3.0 开始):
    openssl pkeyutl -in mess.txt -out sign.bin -inkey private.pem -rawin -digest sha256
    
  • 使用openssl-dgst
    openssl dgst -sha256 -sign private.pem -out sign.bin mess.txt
    

通过这些更改,不需要调整 JavaScript 代码。

© www.soinside.com 2019 - 2024. All rights reserved.