TweetNaCl.js 最小 Public-密钥签名示例

TweetNaCl.js minimal Public-key signatures example

我试图了解如何根据位于 here 的演示,使用纯 javascript.

实现最小的基本 Public-密钥签名示例

我的研究还没有产生一个简单的 javascript 示例,我可以用它来理解它的内部工作原理,documentation 目前在我的脑海中。

我试着查看了演示的 source code,但它并没有泄露它的秘密。

图书馆的 examples 也没有这方面的例子。

密码学对我来说是一个非常新的东西,所以任何关于如何在 node.js 中使用纯 javascript 创建他们的 Public-key 示例的基线示例将不胜感激!

伪代码:

const nacl = require('tweetnacl')
let message = "This is my unencrypted message"
let naclPair = nacl.sign.keyPair()
let signedMessage = nacl.sign(message, naclPair.secretKey)
let decrypted = nacl.sign.open(signedMessage, naclPair.publicKey) // is this right?
console.log(decrypted) // should this print the decrypted message?

作为旁注,我对 node.js require 比对 ES6 import 更熟悉,如果这对这里的答案有任何影响并且可以帮助证明如何使用这个库。

TweetNaCl.js is a port to JavaScript of TweetNaCl. TweetNacl in turn is a compact implementation of NaCl, which provides various encryption and signature algorithms essentially based on Curve25519. There are NaCl-compatible implementations or wrappers for many platforms, so that any of these documentations can be used for an introduction, e.g. the clear documentation of the Libsodium叉子。

TweetNaCl.js 的文档还简要概述了功能:nacl.sign(message, secretKey) creates a signed message consisting of the 64 bytes signature with attached message. nacl.sign.open(signedMessage, publicKey) verifies the message using the signature and returns the message if verification is successful. The algorithm used for signing is Ed25519

如评论中所述,您没有明确区分加密(目的:保密)和 signing(目的:身份验证/完整性)。特别是,消息的保密性不是签名的目的。这变得很明显,例如当 nacl.sign() 的 return 包含未加密的消息时(参见下面的代码片段)。不过,签名时确实用私钥加密了(但不是为了保密)。

以下实现是纯 JavaScript 实现:

var keyPair = nacl.sign.keyPair();
var secretKey  = keyPair.secretKey;
var publicKey = keyPair.publicKey;
var msgStr = "The quick brown fox jumps over the lazy dog";
var msg = nacl.util.decodeUTF8(msgStr);
var signature = nacl.sign(msg, secretKey);
var signatureB64 = nacl.util.encodeBase64(signature);
console.log(signatureB64.replace(/(.{64})/g,'\n')); // Display signature plus message (Base64 encoded)
var signatureMsgPart = signature.slice(64); 
console.log(nacl.util.encodeUTF8(signatureMsgPart));  // Display message from nacl.sign() return value: signing is not for encryption!
var verifiedMsg = nacl.sign.open(signature, publicKey);
console.log(nacl.util.encodeUTF8(verifiedMsg));       // Display message after successfull verification
<script src="https://cdn.jsdelivr.net/npm/tweetnacl-util@0.15.0/nacl-util.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tweetnacl@1.0.1/nacl.min.js"></script>

并应用包 tweetnacl-util-js 进行编码。

顺便说一句,在您发布的实现中,只缺少 Utf8 encoding/decoding:

let message = "This is my unencrypted message"
let naclPair = nacl.sign.keyPair()
let signedMessage = nacl.sign(nacl.util.decodeUTF8(message), naclPair.secretKey)
let decrypted = nacl.sign.open(signedMessage, naclPair.publicKey) // is this right? -> Yes
console.log(nacl.util.encodeUTF8(decrypted)) // should this print the decrypted message? -> Yes, but the 'verified' message is printed!
<script src="https://cdn.jsdelivr.net/npm/tweetnacl-util@0.15.0/nacl-util.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/tweetnacl@1.0.1/nacl.min.js"></script>

请参阅以下链接以获取 public key encryption and symmetric encryption 和 TweetNaCl.js。这是关于保密消息。

顺便说一句,使用示例页面(Public-key signatures) 来测试代码需要使用nacl.sign.detached(message, secretKey) 而不是nacl.sign(msg, secretKey)


参考

TweetNaCl.js Public-key signatures example err