【发布时间】:2018-08-09 12:44:15
【问题描述】:
我想加密聊天室(网络应用程序)中的消息,使除接收者之外的任何人都无法解密它们。看来RSA加密是个好办法。每个用户(实际上是每个设备)都有一个公钥-私钥对,每条消息都将使用接收方公钥加密并使用接收方私钥解密,因此每条消息的发送次数应与接收方相同。 我找到了tutorial,它解释了如何实现该目标。加密/解密在 Service Worker 中计算,私钥不暴露,只是存储在同一个 Worker 中。
但是,我想知道是否有一种安全的方法可以从设备导出密钥对,以便能够从另一台设备查看您的消息。
我可以添加一个名为 "exportKeys" 的 messageType 并检索两个键,如下例所示:
从上面的教程中添加“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
}
}
然后,我可以向用户显示 QR 或其他任何内容,以将他的密钥导出到另一台设备,并让他使用 "importKeys" 之类的方式执行与新设备相反的操作。
虽然这可能有效,但我也会在客户端使用"exportKeys" 公开私钥。但是如果你不真的通过互联网发送私钥会不会是一个安全问题?
关于它的任何其他提示?
【问题讨论】:
-
也许使用一次性访问令牌/密钥来(加密和)同步真正的密钥?所以至少真正的钥匙不会直接出现(通过屏幕录像机或其他东西)
-
您使用的 PHP 版本是什么?如果是 PHP 7.2,那么我建议您使用
sodium函数,更具体地说是sodium_crypto_boxphp.net/manual/en/function.sodium-crypto-box.php -
@PeterDarmis 此处仅涉及 Javascript。
-
@Manolo 对不起,我很抱歉...在这种情况下,您可以使用 NaCl.js github.com/tonyg/js-nacl 来实现相同的功能,或者在 github 中使用任何您熟悉的 javascript 中的 libsodium 实现。
-
@PeterDarmis 你的意思是像苹果一样,在导出之前加密私钥并需要密钥来导入它吗?
标签: javascript encryption rsa service-worker