我想对聊天室(网络应用程序)中的消息进行加密,以使除接收者之外的任何人都无法解密消息。似乎RSA加密是一个好方法。每个用户(实际上是每个设备)都将具有一个公钥-私钥对,并且每个消息都将使用接收者公钥加密,并使用接收者私钥解密,因此,每个消息的发送次数应与接收者相同。
我找到了tutorial,它解释了如何实现该目标。加密/解密是在Service Worker中计算的,并且私钥不会公开,而只是存储在同一Worker中。
但是,我想知道是否存在一种安全的方法来从一台设备导出密钥对,以便能够从另一台设备查看您的消息。
我可以添加一个名为messageType
的"exportKeys"
并像下面的示例一样检索两个键:
从上面的教程中添加“ exportKeys”的messageType和函数:
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
}
}
然后,我可以向用户显示QR或其他内容,以将其密钥导出到另一台设备,然后让他使用诸如
"importKeys"
之类的新设备进行相反的操作。尽管这可能行得通,但我还要在客户端使用
"exportKeys"
公开私钥。但是,如果您不真正通过互联网发送私钥,那将是一个安全问题吗?还有其他提示吗?
最佳答案
对于private
和encrypted
消息,也许可以在JavaScript中使用libsodium实现,例如js-nacl或libsodium来实现Public-key authenticated encryption using crypto_box
。大多数功能与您已经使用的功能相似。为了更好地解释:
发件人和收件人必须具有一组密钥(公用密钥和专用密钥)才能加密/解密消息。
发件人需要sender-PrivateKey
和recipient-PublicKey
和nonce
来加密邮件。
收件人需要recipient-PrivateKey
,sender-PublicKey
和nonce
来解密邮件。
示例代码取自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
我想以某种方式对聊天室(网络应用程序)中的消息进行加密
任何人都无法解密它们,除了
接收者。似乎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。