node.js 使用 SHA256 签名与使用 RSA-SHA256 签名之间的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27039489/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:08:55  来源:igfitidea点击:

Difference between signing with SHA256 vs. signing with RSA-SHA256

node.jsrsadigital-signaturesha256

提问by Arim

I play with digital signaturesusing node.js. For test purpose, I created a digital signature of some XML data, first using only SHA256, then using RSA-SHA256.

我使用 node.js玩数字签名。出于测试目的,我创建了一些 XML 数据的数字签名,首先仅使用 SHA256,然后使用 RSA-SHA256。

The thing that puzzles me is that both methods of signing create exactly the same signature. Both signatures are identical. If they're identical, then why two different methods (SHA256 vs. RSA-SHA256)?

令我困惑的是,两种签名方法创建的签名完全相同。两个签名是相同的。如果它们相同,那么为什么要使用两种不同的方法(SHA256 与 RSA-SHA256)?

I include code below:

我在下面包含代码:

var crypto = require('crypto'),
    path   = require('path'),
    fs     = require('fs'),

    pkey_path = path.normalize('private_key.pem'),
    pkey = '';

function testSignature(pkey) {
    var sign1 = crypto.createSign('RSA-SHA256'),
        sign2 = crypto.createSign('SHA256');

    fs.ReadStream('some_document.xml')
        .on('data', function (d) {
            sign1.update(d);
            sign2.update(d);
        })
        .on('end', function () {
            var s1 = sign1.sign(pkey, "base64"),
                s2 = sign2.sign(pkey, "base64");

            console.log(s1);
            console.log(s2);
        });
}

// You need to read private key into a string and pass it to crypto module.
// If the key is password protected, program execution will stop and
// a prompt will appear in console, awaiting input of password.

testSignature(fs.readFileSync(pkey_path));

The code above outputs some string, which is the signature, and then again exactly the same string, which is also a signature of the same data, but created with - supposedly - different algorithm, yet it's identical with previous one...

上面的代码输出一些字符串,它是签名,然后又是完全相同的字符串,它也是相同数据的签名,但使用 - 据说 - 不同的算法创建,但它与前一个相同......

回答by mkl

A signature cannot be created by SHA256 alone.

签名不能单独由 SHA256 创建。

SHA256 is a hashing algorithm; i.e. an algorithm creating a short fingerprint number representing an arbitrary large amount of data. To produce a signature, this fingerprint still has to be treated somehow to allow identification of the holder of some private signature key. One such treatment is to encrypt the fingerprint using the private key of a rsa key pair allowing others to decrypt the result using the associated public key and so verify that the keeper of the private key indeed must have been the signer.

SHA256 是一种哈希算法;即一种创建代表任意大量数据的短指纹编号的算法。为了产生签名,仍然必须以某种方式处理该指纹以允许识别某些私人签名密钥的持有者。一种这样的处理是使用 rsa 密钥对的私钥加密指纹,允许其他人使用关联的公钥解密结果,从而验证私钥的保管者确实必须是签名者。

In the context of your crypto API that RSA encryption scheme either is the default treatment when the treatment is not explicitly named, or the kind of treatment is deduced from the private key you use as parameter in the signcall --- if it is a RSA private key, it uses RSA; if it is a DSA key, it uses DSA; ...

在您的加密 API 的上下文中,当处理未明确命名时,RSA 加密方案是默认处理,或者从您在sign调用中用作参数的私钥推导出处理类型---如果它是 RSA私钥,它使用 RSA;如果是 DSA 密钥,则使用 DSA;...

回答by Maarten Bodewes

What you are looking at is two times a PKCS#1 v1.5 signature. This is a deterministic scheme for signatures, so it always returns the same result (compare this to the PSS scheme, which is randomized, providing better security properties). RSA PKCS#1 v1.5 signature generation and PSS signature generation is defined within RFC 3447(also known as the RSA v2.1 specifications).

您正在查看的是 PKCS#1 v1.5 签名的两倍。这是签名的确定性方案,因此它始终返回相同的结果(将此与随机化的 PSS 方案进行比较,提供更好的安全属性)。RSA PKCS#1 v1.5 签名生成和 PSS 签名生成在RFC 3447(也称为 RSA v2.1 规范)中定义。

If you use your code with RSA 512 bits (testing purposes only, use a key of 2048 bits or over) then you will get the following result:

如果您使用带有 RSA 512 位的代码(仅用于测试目的,请使用 2048 位或以上的密钥),那么您将获得以下结果:

Private key:

私钥:

-----BEGIN RSA PRIVATE KEY-----
MIIBOgIBAAJBALLA/Zk6+4JFJ+XdU6wmUkuEhGa8hLZ+m6J3puZbc9E+DSt7pW09
yMYwHF5MMICxE86cA6BrLjQLUUwvquNSK0ECAwEAAQJAcI/w4e3vdRABWNFvoCcd
iWpwSZWK6LR/YuZ/1e1e2DJw+NXyPXbilSrLvAdxnjlWTsTxUiEy1jFh36pSuvMk
AQIhAO4WtgysOoWkyvIOLIQwD0thWfdHxTpxqfd6flrBJ91hAiEAwDOQqHhnSeET
+N/hwUJQtCkHBJqvMF/kAi4Ry5G+OeECIEg1Exlc0pLdm781lUKx4LGX4NUiKyrC
di3cNJ4JnrGBAiEAi2gbYYbLbDO8F8TTayidfr9PXtCPhyfWKpqdv6i7cCECIH7A
6bh0tDCl6dOXQwbhgqF4hXiMsqe6DaHqIw8+XLnG
-----END RSA PRIVATE KEY-----

signature as base 64 (using your code):

签名为 base 64(使用您的代码):

YY6sur9gkHXH23cUbDMYjCJYqDdBK8GKp4XyRNl8H09cW8H/gKQI9Z6dkLMhNh7oPq1yABCRfTP8yRtfLVj7FA==

and in hexadecimals

和十六进制

618eacbabf609075c7db77146c33188c2258a837412bc18aa785f244d97c1f4f5c5bc1ff80a408f59e9d90b321361ee83ead720010917d33fcc91b5f2d58fb14

decrypted using RAW RSA (i.e. just modular exponentiation with the public exponent):

使用 RAW RSA 解密(即只是使用公共指数进行模幂运算):

0001ffffffffffffffffffff003031300d0609608648016503040201050004202af565b95e5f4479492c520c430f07ae05d2bcff8923322e6f2ef6404d72ac64

This is a very clear example of a PKCS#1 signature, easily recognized by the FFpadding, followed by the ASN.1 structure (starting with 30, SEQUENCE):

这是一个非常清晰的 PKCS#1 签名示例,很容易被FF填充识别,后跟 ASN.1 结构(以30, SEQUENCE开头):

SEQUENCE (2 elem)
  SEQUENCE (2 elem)
  OBJECT IDENTIFIER 2.16.840.1.101.3.4.2.1 {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) sha256(1)}
    NULL
  OCTET STRING(32 byte) 2AF565B95E5F4479492C520C430F07AE05D2BCFF8923322E6F2EF6404D72AC64

So that thing in the end is the hash, in this case over just Test 123\nas I didn't want to type out any XML today.

所以最后就是散列,在这种情况下,就像Test 123\n我今天不想输入任何 XML 一样。

$ sha256sum some_document.xml 
2af565b95e5f4479492c520c430f07ae05d2bcff8923322e6f2ef6404d72ac64  some_document.xml

$ sha256sum some_document.xml 
2af565b95e5f4479492c520c430f07ae05d2bcff8923322e6f2ef6404d72ac64  some_document.xml