从Web应用程序导出/导入RSA密钥对

时间:2018-08-09 12:44:16

标签: javascript encryption rsa service-worker

我想对聊天室(Web应用程序)中的消息进行加密,以使除接收者之外的任何人都无法解密消息。似乎RSA加密是一个好方法。每个用户(实际上是每个设备)都将具有一个公钥-私钥对,并且每个消息都将使用接收者公共密钥加密,并使用接收者私有密钥解密,因此,每个消息的发送次数应与接收者相同。 我找到了tutorial,其中说明了如何实现该目标。加密/解密是在Service Worker中计算的,并且私钥不会公开,而只是存储在同一个Worker中。

但是,我想知道是否存在一种安全的方法来从一台设备导出密钥对,以便能够从另一台设备查看您的消息。 我可以添加一个名为messageType的{​​{1}}并像下面的示例一样检索两个键:

在以上教程中,添加了“ exportKeys” messageType和函数:

"exportKeys"

然后,我可以向用户显示QR或其他内容,以将其密钥导出到另一台设备,并让他使用诸如self.window = self // This is required for the jsencrypt library to work within the web worker // Import the jsencrypt library self.importScripts('https://cdnjs.cloudflare.com/ajax/libs/jsencrypt/2.3.1/jsencrypt.min.js'); let crypt = null let privateKey = null /** Webworker onmessage listener */ onmessage = function(e) { const [ messageType, messageId, text, key ] = e.data let result switch (messageType) { case 'generate-keys': result = generateKeypair() break case 'encrypt': result = encrypt(text, key) break case 'decrypt': result = decrypt(text) break case 'exportKeys': result = exportKeys(key) break } // Return result to the UI thread postMessage([ messageId, result ]) } /** Generate and store keypair */ function generateKeypair () { crypt = new JSEncrypt({default_key_size: 2056}) privateKey = crypt.getPrivateKey() // Only return the public key, keep the private key hidden return crypt.getPublicKey() } /** Encrypt the provided string with the destination public key */ function encrypt (content, publicKey) { crypt.setKey(publicKey) return crypt.encrypt(content) } /** Decrypt the provided string with the local private key */ function decrypt (content) { crypt.setKey(privateKey) return crypt.decrypt(content) } /** Export keys */ function exportKeys (publicKey) { return { publicKey: publicKey, privateKey: privateKey } } 之类的新设备进行相反的操作。

尽管这可能有效,但我还将在客户端使用"importKeys"公开私钥。但是,如果您不真正通过互联网发送私钥,那将是一个安全问题吗?

还有其他提示吗?

1 个答案:

答案 0 :(得分:1)

对于privateencrypted消息,也许可以在JavaScript中使用libsodium实现,例如js-nacllibsodium来实现Public-key authenticated encryption using crypto_box。大多数功能与您已经使用的功能相似。为了更好地解释:

发件人和收件人必须具有一组密钥( 公开 私有 ),以便进行加密/解密消息。

发件人需要sender-PrivateKeyrecipient-PublicKeynonce来加密邮件。

收件人需要recipient-PrivateKeysender-PublicKeynonce来解密邮件。

示例代码摘自js-nacl Github自述页面。

senderKeypair = nacl.crypto_box_keypair();
recipientKeypair = nacl.crypto_box_keypair();
message = nacl.encode_utf8("Hello!");

nonce = nacl.crypto_box_random_nonce();
packet = nacl.crypto_box(message, nonce, recipientKeypair.boxPk, senderKeypair.boxSk);

decoded = nacl.crypto_box_open(packet, nonce, senderKeypair.boxPk, recipientKeypair.boxSk);

"Hello!" === nacl.decode_utf8(decoded); // always true
  

我想以某种方式对聊天室(Web应用程序)中的消息进行加密   任何人都无法解密它们,除了   接收者。似乎RSA加密是一个好方法。

我不知道RSA加密是否是一种好方法。根据最佳策略Cryptographic Best Practices - Asymmetric Encryption,使用libsodium(NaCL)函数进行加密比使用RSA更好。

最后要问的是如何在不显示密钥的情况下导出密钥?

您可以使用nacl.crypto_box_seed_keypair(Uint8Array)和用户提供的输入来导出密钥(要使用nacl.encode_utf8(String)转换为Uint8Array)。

  

nacl.crypto_box_seed_keypair(Uint8Array)

     
      
  • 从其参数产生一个加密的已认证盒密钥对。一种   给定的二进制输入将始终产生与输出相同的密钥对。

  •   
  • 输入可以是任何长度。使用sha512将输入哈希一次,   并将结果的前32个字节作为32个字节的密钥   密钥,然后将其传递给nacl.crypto_box_keypair_from_raw_sk。

  •