我想对聊天室(网络应用程序)中的消息进行加密,除了接收者之外,任何人都无法解密它们。看来RSA加密是一个好方法。每个用户(实际上是每个设备)都会有一个公钥-私钥对,每条消息都将使用接收者公钥进行加密,并使用接收者私钥进行解密,因此每条消息都应该发送与接收者相同的次数。 我找到了tutorial其中解释了如何实现该目标。加密/解密是在 Service Worker 中计算的,私钥不会暴露,只是存储在同一个 Worker 中。
但是,我想知道是否有一种安全的方法可以从设备导出 key 对,以便能够从另一台设备查看您的消息。
我可以添加一个名为 "exportKeys"
的 messageType
并检索两个 key ,如下例所示:
从上面的教程中添加“exportKeys”消息类型和函数:
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
}
}
然后,我可以向用户显示二维码或其他内容,将其 key 导出到另一台设备,并让他使用 "importKeys"
之类的内容执行与新设备相反的操作。
尽管这可能有效,但我也会在客户端使用 "exportKeys"
公开私钥。但如果你不真正通过互联网发送私钥,会出现安全问题吗?
还有其他相关提示吗?
最佳答案
如果是私有(private)
和加密
消息,也许您可以在javascript中使用libsodium实现,例如js-nacl ,或libsodium用于使用 crypto_box 实现公钥验证加密
。大多数功能与您已经使用的功能相似。为了更好地解释:
发送者和接收者必须拥有一组 key (公共(public)和私有(private))才能加密/解密消息。
发件人需要 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
I want to encrypt messages in chat rooms (web app) in a way that it wouldn't be possible for anyone to decrypt them except for the receivers. It seems that RSA encryption is a good way.
我不知道RSA加密是不是一个好方法。根据被认为是最好的策略Cryptographic Best Practices - Asymmetric Encryption使用libsodium(NaCL)函数进行加密比RSA更好。
最后一件事是如何导出 key 而不泄露它们?
您可以使用 nacl.crypto_box_seed_keypair(Uint8Array)
导出 key 和用户提供的输入(要转换为 Uint8Array 使用 nacl.encode_utf8(String) )。
nacl.crypto_box_seed_keypair(Uint8Array)
Produces an encrypted authenticated box keypair from its argument. A given binary input will always produce the same keypair as output.
The input may be of any length. The input is hashed once with sha512, and the first 32 bytes of the result are taken as the 32-byte secret key, which is then passed to nacl.crypto_box_keypair_from_raw_sk.
关于javascript - 从 Web 应用程序导出/导入 RSA key 对,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51767414/