在实现这些之前,请参阅Scott Arciszewski的回答。
我希望你对我将要分享的内容非常小心,因为我几乎没有安全知识(我很有可能误用了下面的API),所以我非常欢迎在社区的帮助下更新这个答案。
正如@richardtallent在他的回答中提到的,有对Web Crypto API的支持,因此本例使用了该标准。在撰写本文时,全球浏览器的支持率为95.88%。
我将分享一个使用Web Crypto API的示例
在我们继续之前,请注意(引用自MDN):
This API provides a number of low-level cryptographic primitives. It's very easy to misuse them, and the pitfalls involved can be very subtle.
Even assuming you use the basic cryptographic functions correctly, secure key management and overall security system design are extremely hard to get right and are generally the domain of specialist security experts.
Errors in security system design and implementation can make the security of the system completely ineffective.
If you're not sure you know what you are doing, you probably shouldn't be using this API.
我非常尊重安全性,我甚至加粗了MDN的附加部分……我已经警告过你了
现在来看看实际的例子……
JSFiddle:
在这里找到:https://jsfiddle.net/superjose/rm4e0gqa/5/
注意:
注意await关键字的使用。在异步函数中使用它或使用.then()和.catch()。
生成密钥:
// https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey
// https://developer.mozilla.org/en-US/docs/Web/API/RsaHashedKeyGenParams
// https://github.com/diafygi/webcrypto-examples#rsa-oaep---generatekey
const stringToEncrypt = 'https://localhost:3001';
// https://github.com/diafygi/webcrypto-examples#rsa-oaep---generatekey
// The resultant publicKey will be used to encrypt
// and the privateKey will be used to decrypt.
// Note: This will generate new keys each time, you must store both of them in order for
// you to keep encrypting and decrypting.
//
// I warn you that storing them in the localStorage may be a bad idea, and it gets out of the scope
// of this post.
const key = await crypto.subtle.generateKey({
name: 'RSA-OAEP',
modulusLength: 4096,
publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
hash: {name: 'SHA-512'},
}, true,
// This depends a lot on the algorithm used
// Go to https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto
// and scroll down to see the table. Since we're using RSA-OAEP we have encrypt and decrypt available
['encrypt', 'decrypt']);
// key will yield a key.publicKey and key.privateKey property.
加密:
const encryptedUri = await crypto.subtle.encrypt({
name: 'RSA-OAEP'
}, key.publicKey, stringToArrayBuffer(stringToEncrypt))
console.log('The encrypted string is', encryptedUri);
解密
const msg = await crypto.subtle.decrypt({
name: 'RSA-OAEP',
}, key.privateKey, encryptedUri);
console.log(`Derypted Uri is ${arrayBufferToString(msg)}`)
从字符串中来回转换ArrayBuffer(在TypeScript中完成):
private arrayBufferToString(buff: ArrayBuffer) {
return String.fromCharCode.apply(null, new Uint16Array(buff) as unknown as number[]);
}
private stringToArrayBuffer(str: string) {
const buff = new ArrayBuffer(str.length*2) // Because there are 2 bytes for each char.
const buffView = new Uint16Array(buff);
for(let i = 0, strLen = str.length; i < strLen; i++) {
buffView[i] = str.charCodeAt(i);
}
return buff;
}
你可以在这里找到更多的例子(我不是所有者):
/ / https://github.com/diafygi/webcrypto-examples