使用 node.js 加密的数字签名
Digital signature with node.js crypto
有人可以提供有关如何使用 node.js 实现数字签名的基本演练吗?我用谷歌搜索但还没有得到它。比如说,我有一个 API,我想签署并验证对它的每个 http 请求和它的响应。这是我目前的想象,不对的地方请指正:
1) 我需要为客户端生成一个足够随机的密钥,用于签署请求;
2) 生成的签名(通过 header 提供)是使用字符串的密钥散列加密的,其中必须包括:
- 请求的哈希值body(防止篡改);
- 时间戳;
- 随机数;
- url;
- HTTP 动词
然后,服务器将能够检查消息的真实性。
问题:
1) 随机数(一些随机值)和时间戳(我读过 post 建议同时使用两者)在这种情况下有什么区别?
2) 我需要在该字符串中包含 eTag header 吗?
3) 上面没有列出的还有什么应该包括的?
4) 我应该在 API 服务器上保留与客户端相同的密钥并使用它解密和检查请求,还是应该将密钥存储在 API 服务器上,以及密钥,存储在服务器上,与 API 通信以获得 private-public 密钥对?如果它们确实需要成为 private-public 密钥密钥对,我如何在节点中使用 public 密钥(反之亦然)解密用私钥加密的内容?
请更正我描述中的错误并添加我遗漏的内容。谢谢。
Amazon REST Authentication 是回答您问题的好例子。 AWS 要求 "sign the request" 使用一组 rules:canonicalization 编码或时间戳对请求数据应用 HMAC 哈希。签名包含在 HTTP 请求
的授权 header 中
HMAC是一种对称算法,客户端和服务器共享密钥,用于双方计算哈希值。如果它们匹配,则请求已发送给授权方
在这种情况下,非对称密钥也很有意义。例如在客户端创建密钥对并在注册期间发送 public 密钥。服务器不需要对响应进行签名。只需使用 TLS 通道,客户端就可以信任服务器验证服务器证书(TLS 还通过加密提供通道隐私)
使用共享密钥,需要考虑如何以安全的方式存储秘密,例如(如您所建议的),使用数据库,或使用 master-key
所有安全解决方案都有风险,即使使用 HSM 硬件也是如此。考虑 risk-benefit。如果您将密钥存储在数据库中,系统管理员或窃取数据库密码的人可以获取所有密钥。在某些情况下,我看到它使用存储在机器中的主加密密钥(实际上一些 HSM 只是管理这个主密钥)
下面的代码示例使用 crypto
库(现在内置在 nodejs 中)为文档生成数字签名。
const crypto = require('crypto');
const fs = require('fs');
// See keys/README.md on how to generate this key
const private_key = fs.readFileSync('keys/privateKey.pem', 'utf-8');
// File/Document to be signed
const doc = fs.readFileSync('sample-doc.txt');
// Signing
const signer = crypto.createSign('RSA-SHA256');
signer.write(doc);
signer.end();
// Returns the signature in output_format which can be 'binary', 'hex' or 'base64'
const signature = signer.sign(private_key, 'base64')
console.log('Digital Signature: ', signature);
这是来自 github 的完整代码示例:digital-signature-for-document-signing
有人可以提供有关如何使用 node.js 实现数字签名的基本演练吗?我用谷歌搜索但还没有得到它。比如说,我有一个 API,我想签署并验证对它的每个 http 请求和它的响应。这是我目前的想象,不对的地方请指正:
1) 我需要为客户端生成一个足够随机的密钥,用于签署请求;
2) 生成的签名(通过 header 提供)是使用字符串的密钥散列加密的,其中必须包括:
- 请求的哈希值body(防止篡改);
- 时间戳;
- 随机数;
- url;
- HTTP 动词
然后,服务器将能够检查消息的真实性。
问题:
1) 随机数(一些随机值)和时间戳(我读过 post 建议同时使用两者)在这种情况下有什么区别?
2) 我需要在该字符串中包含 eTag header 吗?
3) 上面没有列出的还有什么应该包括的?
4) 我应该在 API 服务器上保留与客户端相同的密钥并使用它解密和检查请求,还是应该将密钥存储在 API 服务器上,以及密钥,存储在服务器上,与 API 通信以获得 private-public 密钥对?如果它们确实需要成为 private-public 密钥密钥对,我如何在节点中使用 public 密钥(反之亦然)解密用私钥加密的内容?
请更正我描述中的错误并添加我遗漏的内容。谢谢。
Amazon REST Authentication 是回答您问题的好例子。 AWS 要求 "sign the request" 使用一组 rules:canonicalization 编码或时间戳对请求数据应用 HMAC 哈希。签名包含在 HTTP 请求
的授权 header 中HMAC是一种对称算法,客户端和服务器共享密钥,用于双方计算哈希值。如果它们匹配,则请求已发送给授权方
在这种情况下,非对称密钥也很有意义。例如在客户端创建密钥对并在注册期间发送 public 密钥。服务器不需要对响应进行签名。只需使用 TLS 通道,客户端就可以信任服务器验证服务器证书(TLS 还通过加密提供通道隐私)
使用共享密钥,需要考虑如何以安全的方式存储秘密,例如(如您所建议的),使用数据库,或使用 master-key
所有安全解决方案都有风险,即使使用 HSM 硬件也是如此。考虑 risk-benefit。如果您将密钥存储在数据库中,系统管理员或窃取数据库密码的人可以获取所有密钥。在某些情况下,我看到它使用存储在机器中的主加密密钥(实际上一些 HSM 只是管理这个主密钥)
下面的代码示例使用 crypto
库(现在内置在 nodejs 中)为文档生成数字签名。
const crypto = require('crypto');
const fs = require('fs');
// See keys/README.md on how to generate this key
const private_key = fs.readFileSync('keys/privateKey.pem', 'utf-8');
// File/Document to be signed
const doc = fs.readFileSync('sample-doc.txt');
// Signing
const signer = crypto.createSign('RSA-SHA256');
signer.write(doc);
signer.end();
// Returns the signature in output_format which can be 'binary', 'hex' or 'base64'
const signature = signer.sign(private_key, 'base64')
console.log('Digital Signature: ', signature);
这是来自 github 的完整代码示例:digital-signature-for-document-signing