简体   繁体   English

如何在NodeJ中进行基于X或Y-of-X公钥的加密/解密?

[英]How to do 1-of-X or Y-of-X public key based encrypt/ decrypt in NodeJs?

I would like to be able to encrypt data using public keys, and decrypt the encrypted data using private keys. 我希望能够使用公钥加密数据,并使用私钥解密加密数据。

Encryption essentially needs to accept inputs: 加密本质上需要接受输入:

  1. Clear data to be encrypted 清除要加密的数据
  2. A list of several public keys 几个公钥的列表
  3. The minimum number of private keys corresponding to those public keys that are needed to decrypt the encrypted 与解密加密所需的公钥对应的最小私钥数

How can this be done in NodeJs? 如何在NodeJ中完成?


Scenarios 方案

By way of concrete scenarios, where there are 5 users (A - E) with crypto key pairs in the system. 通过具体方案,系统中有5个用户(A-E)具有加密密钥对。

A 1-of-X scenario: 1-of-X场景:

  • encrypted = crypto_encrypt(clearText, [A.publicKey, B.publicKey], 1) (1-of-2) encrypted = crypto_encrypt(clearText, [A.publicKey, B.publicKey], 1) (1-of-2)
  • decrypted = crypto_decrypt(encrypted, [A.privateKey])
    • success : decrypted === clearText 成功decrypted === clearText
    • because A.publicKey was used in encryption 因为A.publicKey用于加密
  • decrypted = crypto_decrypt(encrypted, [C.privateKey])
    • failure : unable to decrypt 失败 :无法解密
    • because C.publicKey was not used in encryption 因为C.publicKey没有用于加密

A Y-of-X scenario: Y-of-X场景:

  • encrypted = crypto_encrypt(clearText, [A.publicKey, B.publicKey, C.publicKey], 2) (2-of-3) encrypted = crypto_encrypt(clearText, [A.publicKey, B.publicKey, C.publicKey], 2) (2-of-3)
  • decrypted = crypto_decrypt(encrypted, [A.privateKey, C.privateKey])
    • success : decrypted === clearText 成功decrypted === clearText
    • because both A.publicKey and C.publicKey was used in encryption 因为A.publicKeyC.publicKey都用于加密
  • decrypted = crypto_decrypt(encrypted, [C.privateKey, E.privateKey])
    • failure : unable to decrypt 失败 :无法解密
    • because while C.publicKey was used in encryption, E.publicKey was not 因为虽然C.publicKey用于加密,但E.publicKey却没有

Ideally... 理想的情况下...

  • At minimum I need to be able to support the 1-of-X scenario, but if Y-of-X is also possible, that would be better 至少我需要能够支持1-of-X场景,但是如果Y-of-X也是可能的话,那会更好
  • What the actual key pairs are is not so important here, could be RSA, could be any of the elliptic curves. 实际的密钥对在这里不是那么重要,可能是RSA,可以是任何椭圆曲线。 If the method supports a number of different ones, and allows one to pick, that would be better 如果该方法支持许多不同的方法,并允许一个选择,那就更好了
  • Preferably not tied to the use of any particular toolset or framework 优选地,不依赖于任何特定工具集或框架的使用

PGP can do this. PGP可以做到这一点。

Specifically for node, openpgpjs has a section in the README - https://github.com/openpgpjs/openpgpjs#encrypt-and-decrypt-string-data-with-pgp-keys - which could be condensed into: 特别是对于节点, openpgpjs在README中有一节 - https://github.com/openpgpjs/openpgpjs#encrypt-and-decrypt-string-data-with-pgp-keys - 可以压缩成:

    const encryptedText = await openpgp.encrypt({ message: clearText, publicKeys });
    const decryptedText = await openpgp.decrypt({ message: encryptedText, privateKeys });

However: 然而:

  • for number of keys required to decrypt, it only supports the 1 of many scenario, not the more general some of many scenario you'd ideally want 对于解密所需的密钥数量,它只支持许多场景中的1个,而不是更理想的一些场景中的一些
  • supports both RSA and many elliptic curve based keys, but the key format is designed for use by PGP, as the name of the library implies (so it is specific to the PGP toolchain) 支持RSA和许多基于椭圆曲线的键,但键格式设计为供PGP使用,因为库的名称暗示(因此它特定于PGP工具链)

As noted by Luke Joshua Park in the comments, this sounds like a textbook use case for a secret sharing scheme . 正如Luke Joshua Park在评论中所指出的,这听起来像是秘密共享方案的教科书用例。 Specifically, I would recommend that you: 具体来说,我建议你:

  1. Generate a random AES (or other symmetric cipher) key. 生成随机AES(或其他对称密码)密钥。 Make sure to use a cryptographically secure RNG (such as Crypto.randomBytes() ) for this, since an attacker who can guess this key can also break the entire scheme! 确保使用加密安全的RNG(例如Crypto.randomBytes() ),因为可以猜测此密钥的攻击者也可以破坏整个方案!
  2. Encrypt the data with this key, using an authenticated encryption mode such as AES-SIV (as provided eg by miscreant ). 使用经过身份验证的加密模式(例如AES-SIV (例如由miscreant提供))使用此密钥加密数据。
  3. Split the AES key into multiple shares using Shamir's secret sharing scheme with the desired reconstruction threshold. 使用具有所需重建阈值的Shamir秘密共享方案将AES密钥拆分为多个共享 (Some JS implementations I found with a quick Google search include secrets.js , jsss and ThresholdJS .) (有些JS实现,我发现一个快速谷歌搜索包括secrets.jsJSSSThresholdJS 。)
  4. Encrypt each share using a different user's public key. 使用其他用户的公钥加密每个共享。
  5. Send each user their encrypted share and a copy of the AES-encrypted data. 向每个用户发送其加密共享和AES加密数据的副本。

Disclaimer: I have not reviewed the security or correctness of any of the APIs or libraries linked above. 免责声明:我尚未审查上述链接的任何API或库的安全性或正确性。 The cryptographic techniques they claim to use appear to be sound and suitable for this task, but I cannot guarantee that they have been implemented safely and correctly. 他们声称使用的加密技术看似合理,适合这项任务,但我不能保证它们已经安全,正确地实施。 Caveat emptor. 买者自负。

To decrypt the data, each user can first decrypt their share of the AES key using their private key, and a sufficient number of the decrypted shares can then be combined (using the same implementation of Shamir's secret sharing as used to create them) to reconstruct the original AES key, which can then be used to decrypt (and verify the integrity of) the data. 为了解密数据,每个用户可以首先使用他们的私钥解密他们的AES密钥份额,然后可以组合足够数量的解密份额(使用与创建它们相同的Shamir秘密共享实现)来重建原始AES密钥,然后可用于解密(并验证数据的完整性)。

Note that Shamir's secret sharing implicitly assumes that the users who combine their shares to reconstruct the secret will trust each other and not lie about their shares or otherwise misbehave. 请注意,Shamir的秘密共享隐含地假设组合其共享以重建秘密的用户将相互信任而不是谎言他们的共享或其他行为不端。 If that's not necessarily true, there are various ways for a malicious user to trick the others — perhaps most simply by waiting for everyone else to reveal their share to them and then refusing to reveal their own share to the others. 如果这不一定是真的,恶意用户可以通过各种方式欺骗其他人 - 也许最简单的方法是等待其他人向他们透露他们的份额,然后拒绝向其他人透露他们自己的份额。 In general, preventing such attacks is all but impossible without the help of some kind of a mutually trusted party. 一般来说,如果没有某种相互信任的政党的帮助,防止这种攻击几乎是不可能的。

At the very least, though, using an encryption mode like AES-SIV with built-in authentication should ensure that users will detect if the reconstructed AES key is incorrect, since the decryption will then fail. 但是,至少使用具有内置身份验证的AES-SIV等加密模式应该确保用户将检测重建的AES密钥是否不正确,因为解密将失败。 If you want to be extra sure of this, you may wish to also send each of the users a secure cryptographic hash (eg SHA-512 ) of the AES key, so that they can verify its correctness before attempting decryption. 如果您想要更加确定这一点,您可能还希望向每个用户发送AES密钥的安全加密哈希(例如SHA-512 ),以便他们可以在尝试解密之前验证其正确性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否可以在NodeJS中生成密钥对,使用公共密钥在PHP中加密数据以及在NodeJS中解密? - Can I generate a key-pair in NodeJS, encrypt data in PHP using the public key, and decrypt in NodeJS? 如何使用 NodeJS 中的公钥仅加密 JSON 有效负载的选定值? - How do I encrypt only selected values of a JSON payload using a public key in NodeJS? 如何在NodeJS中创建加密和解密功能? - How do I create an encrypt and decrypt function in NodeJS? 如何使用 nodejs 使用密码短语加密私钥和公钥? - How do I encrypt a private and public key with a pass phrase using nodejs? 如何使用 Hyperledger Fabric 中生成的 ECDSA 私钥和公钥进行加密和解密 - How to encrypt and decrypt using ECDSA private key and public key generated in Hyperledger fabric 如何使用java生成的public加密nodejs中的字符串 - How do I encrypt string in nodejs with public generated by java 如何从nodejs中解析的x509认证中获取公钥长度 - How to get the public key length out of parsed x509 certification in nodejs 如何在nodejs中加密和解密字符串/对象 - How to encrypt and decrypt string/object in nodejs 如何使用 CryptoJS 在 Angularjs 中加密并在 Nodejs 中解密 - How to Encrypt in Angularjs and Decrypt in Nodejs using CryptoJS 如何使用相同的密钥加密和解密一个数字? - How to encrypt and decrypt a number using same key?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM