[英]JavaScript string encryption and decryption?
I'm interested in building a small app for personal use that will encrypt and decrypt information on the client side using JavaScript.我有兴趣构建一个供个人使用的小型应用程序,该应用程序将使用 JavaScript 在客户端加密和解密信息。 The encrypted information will be stored in a database on a server, but never the decrypted version.
加密信息将存储在服务器上的数据库中,但绝不会是解密版本。
It doesn't have to be super duper secure, but I would like to use a currently unbroken algorithm.它不必是超级安全的,但我想使用当前未破坏的算法。
Ideally I'd be able to do something like理想情况下,我可以做类似的事情
var gibberish = encrypt(string, salt, key);
to generate the encoded string, and something like生成编码字符串,以及类似的东西
var sensical = decrypt(gibberish, key);
to decode it later.稍后解码。
So far I've seen this: http://bitwiseshiftleft.github.io/sjcl/到目前为止,我已经看到了这个: http : //bitwiseshiftleft.github.io/sjcl/
Any other libraries I should look at?我应该看看其他图书馆吗?
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase"); //U2FsdGVkX18ZUVvShFSES21qHsQEqZXMxQ9zgHy+bu0= var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase"); //4d657373616765 document.getElementById("demo1").innerHTML = encrypted; document.getElementById("demo2").innerHTML = decrypted; document.getElementById("demo3").innerHTML = decrypted.toString(CryptoJS.enc.Utf8);
Full working sample actually is: <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js" integrity="sha256-/H4YS+7aYb9kJ5OKhFYPUjSJdrtV6AeyJOtTkw6X72o=" crossorigin="anonymous"></script> <br><br> <label>encrypted</label> <div id="demo1"></div> <br> <label>decrypted</label> <div id="demo2"></div> <br> <label>Actual Message</label> <div id="demo3"></div>
How about CryptoJS ? CryptoJS怎么样?
It's a solid crypto library, with a lot of functionality.这是一个可靠的加密库,具有很多功能。 It implements hashers, HMAC, PBKDF2 and ciphers.
它实现了哈希器、HMAC、PBKDF2 和密码。 In this case ciphers is what you need.
在这种情况下,密码就是您所需要的。 Check out the quick-start quide on the project's homepage.
查看项目主页上的快速入门指南。
You could do something like with the AES:你可以用 AES 做类似的事情:
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script>
var encryptedAES = CryptoJS.AES.encrypt("Message", "My Secret Passphrase");
var decryptedBytes = CryptoJS.AES.decrypt(encryptedAES, "My Secret Passphrase");
var plaintext = decryptedBytes.toString(CryptoJS.enc.Utf8);
</script>
As for security, at the moment of my writing AES algorithm is thought to be unbroken至于安全性,在我编写 AES 算法的那一刻被认为是完整的
Edit :编辑 :
Seems online URL is down & you can use the downloaded files for encryption from below given link & place the respective files in your root folder of the application.似乎在线 URL 已关闭,您可以使用从下面给定链接下载的文件进行加密,并将相应文件放在应用程序的根文件夹中。
https://code.google.com/archive/p/crypto-js/downloads https://code.google.com/archive/p/crypto-js/downloads
or used other CDN like https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/aes-min.js或使用其他 CDN,如https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/aes-min.js
I created an insecure but simple text cipher/decipher util.我创建了一个不安全但简单的文本密码/解密工具。 No dependencies with any external library.
不依赖任何外部库。
These are the functions这些是功能
const cipher = salt => {
const textToChars = text => text.split('').map(c => c.charCodeAt(0));
const byteHex = n => ("0" + Number(n).toString(16)).substr(-2);
const applySaltToChar = code => textToChars(salt).reduce((a,b) => a ^ b, code);
return text => text.split('')
.map(textToChars)
.map(applySaltToChar)
.map(byteHex)
.join('');
}
const decipher = salt => {
const textToChars = text => text.split('').map(c => c.charCodeAt(0));
const applySaltToChar = code => textToChars(salt).reduce((a,b) => a ^ b, code);
return encoded => encoded.match(/.{1,2}/g)
.map(hex => parseInt(hex, 16))
.map(applySaltToChar)
.map(charCode => String.fromCharCode(charCode))
.join('');
}
And you can use them as follows:您可以按如下方式使用它们:
// To create a cipher
const myCipher = cipher('mySecretSalt')
//Then cipher any text:
myCipher('the secret string') // --> "7c606d287b6d6b7a6d7c287b7c7a61666f"
//To decipher, you need to create a decipher and use it:
const myDecipher = decipher('mySecretSalt')
myDecipher("7c606d287b6d6b7a6d7c287b7c7a61666f") // --> 'the secret string'
The existing answers which leverage SJCL, CryptoJS, and/or WebCrypto aren't necessarily wrong but they're not as safe as you might initially suspect.利用 SJCL、CryptoJS 和/或 WebCrypto 的现有答案不一定是错误的,但它们并不像您最初怀疑的那样安全。 Generally you want to use libsodium .
通常你想使用 libsodium 。 First I'll explain why, then how.
首先我会解释为什么,然后是如何。
Short answer: In order for your encryption to actually be secure, these libraries expect you to make too many choices eg the block cipher mode (CBC, CTR, GCM; if you can't tell which of the three I just listed is secure to use and under what constraints, you shouldn't be burdened with this sort of choice at all ).简短回答:为了让您的加密真正安全,这些库希望您做出太多选择,例如分组密码模式(CBC、CTR、GCM;如果您无法分辨我刚刚列出的三个中的哪一个是安全的使用和在什么样的约束,你不应该有这种选择的所有负担)。
Unless your job title is cryptography engineer , the odds are stacked against you implementing it securely.除非您的职位是密码学工程师,否则您安全地实施它的可能性很大。
CryptoJS offers a handful of building blocks and expects you to know how to use them securely. CryptoJS 提供了一些构建块,并希望您知道如何安全地使用它们。 It even defaults to CBC mode ( archived ).
它甚至默认为 CBC 模式(已存档)。
Read this write-up on AES-CBC vulnerabilities .阅读这篇关于 AES-CBC 漏洞的文章。
WebCrypto is a potluck standard, designed by committee, for purposes that are orthogonal to cryptography engineering. WebCrypto 是一个由委员会设计的便餐标准,用于与密码工程正交的目的。 Specifically, WebCrypto was meant to replace Flash, not provide security .
具体来说, WebCrypto 旨在取代 Flash,而不是提供安全性。
SJCL's public API and documentation begs users to encrypt data with a human-remembered password. SJCL 的公共 API 和文档要求用户使用人类记住的密码加密数据。 This is rarely, if ever, what you want to do in the real world.
在现实世界中,这很少(如果有的话)您想要做的事情。
Additionally: Its default PBKDF2 round count is roughly 86 times as small as you want it to be .另外:它的默认 PBKDF2 轮数大约是您希望的 86 倍。 AES-128-CCM is probably fine.
AES-128-CCM 可能没问题。
Out of the three options above, SJCL is the least likely to end in tears.在上述三个选项中,SJCL 最不可能以眼泪收场。 But there are better options available.
但是有更好的选择。
You don't need to choose between a menu of cipher modes, hash functions, and other needless options.您无需在密码模式菜单、散列函数和其他不必要的选项之间进行选择。 You'll never risk screwing up your parameters and removing all security from your protocol .
你永远不会冒着搞砸你的参数和从你的协议中删除所有安全性的风险。
Instead, libsodium just gives you simple options tuned for maximum security and minimalistic APIs.相反, libsodium只是为您提供针对最大安全性和简约 API 进行调整的简单选项。
crypto_box()
/ crypto_box_open()
offer authenticated public-key encryption. crypto_box()
/ crypto_box_open()
提供经过身份验证的公钥加密。
crypto_secretbox()
/ crypto_secretbox_open()
offer shared-key authenticated encryption. crypto_secretbox()
/ crypto_secretbox_open()
提供共享密钥认证加密。
Additionally, libsodium has bindings in dozens of popular programming languages , so it's very likely that libsodium will just work when trying to interoperate with another programming stack.此外,libsodium 绑定了数十种流行的编程语言,因此当尝试与另一个编程堆栈进行互操作时,libsodium 很可能会正常工作。 Also, libsodium tends to be very fast without sacrificing security.
此外,libsodium 在不牺牲安全性的情况下往往非常快。
First, you need to decide one thing:首先,你需要决定一件事:
If you selected the first option , get CipherSweet.js .如果您选择了第一个选项,请获取CipherSweet.js 。
The documentation is available online .该文档可在线获取。
EncryptedField
is sufficient for most use cases, but the EncryptedRow
and EncryptedMultiRows
APIs may be easier if you have a lot of distinct fields you want to encrypt. EncryptedField
对于大多数用例来说就足够了,但是如果您有很多不同的字段要加密,那么EncryptedRow
和EncryptedMultiRows
API 可能会更容易。
With CipherSweet, you don't need to even know what a nonce/IV is to use it securely.使用 CipherSweet,您甚至不需要知道 nonce/IV 是什么就可以安全地使用它。
Additionally, this handles int
/ float
encryption without leaking facts about the contents through ciphertext size.此外,这可以处理
int
/ float
加密,而不会通过密文大小泄漏有关内容的事实。
Otherwise, you'll want sodium-plus , which is a user-friendly frontend to various libsodium wrappers.否则,您将需要钠加,它是各种 libsodium 包装器的用户友好前端。 Sodium-Plus allows you to write performant, asynchronous, cross-platform code that's easy to audit and reason about.
Salt-Plus 允许您编写易于审计和推理的高性能、异步、跨平台代码。
To install sodium-plus, simply run...要安装钠加,只需运行...
npm install sodium-plus
There is currently no public CDN for browser support.目前没有用于浏览器支持的公共 CDN。 This will change soon.
这将很快改变。 However, you can grab
sodium-plus.min.js
from the latest Github release if you need it.但是,如果需要,您可以从最新的 Github 版本中获取
sodium-plus.min.js
。
const { SodiumPlus } = require('sodium-plus'); let sodium; (async function () { if (!sodium) sodium = await SodiumPlus.auto(); let plaintext = 'Your message goes here'; let key = await sodium.crypto_secretbox_keygen(); let nonce = await sodium.randombytes_buf(24); let ciphertext = await sodium.crypto_secretbox( plaintext, nonce, key ); console.log(ciphertext.toString('hex')); let decrypted = await sodium.crypto_secretbox_open( ciphertext, nonce, key ); console.log(decrypted.toString()); })();
The documentation for sodium-plus is available on Github.可以在 Github 上找到关于 salt -plus的文档。
If you'd like a step-by-step tutorial, this dev.to article has what you're looking for.如果您需要分步教程, 这篇 dev.to 文章可以满足您的需求。
Modern browsers now support the crypto.subtle
API, which provides native encryption and decryption functions (async no less!) using one of these method: AES-CBC, AES-CTR, AES-GCM, or RSA-OAEP.现代浏览器现在支持
crypto.subtle
API,它使用以下方法之一提供本机加密和解密功能(异步不少!):AES-CBC、AES-CTR、AES-GCM 或 RSA-OAEP。
https://www.w3.org/TR/WebCryptoAPI/#dfn-Crypto https://www.w3.org/TR/WebCryptoAPI/#dfn-Crypto
@Jorgeblom my man, that's fantastic small crypto lib :DI touch it a bit because I didn't like that I have to assign the salt and to call it again but in general, for my needs is absolutely perfect. @Jorgeblom 我的男人,这是一个很棒的小型加密库:DI 有点触动它,因为我不喜欢我必须分配盐并再次调用它,但总的来说,对于我的需求来说绝对是完美的。
const crypt = (salt, text) => {
const textToChars = (text) => text.split("").map((c) => c.charCodeAt(0));
const byteHex = (n) => ("0" + Number(n).toString(16)).substr(-2);
const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code);
return text
.split("")
.map(textToChars)
.map(applySaltToChar)
.map(byteHex)
.join("");
};
const decrypt = (salt, encoded) => {
const textToChars = (text) => text.split("").map((c) => c.charCodeAt(0));
const applySaltToChar = (code) => textToChars(salt).reduce((a, b) => a ^ b, code);
return encoded
.match(/.{1,2}/g)
.map((hex) => parseInt(hex, 16))
.map(applySaltToChar)
.map((charCode) => String.fromCharCode(charCode))
.join("");
};
And you use it你用它
// encrypting
const encrypted_text = crypt("salt", "Hello"); // -> 426f666665
// decrypting
const decrypted_string = decrypt("salt", "426f666665"); // -> Hello
Before implementying any of this, please see Scott Arciszewski's answer .在实施任何这些之前,请参阅Scott Arciszewski 的回答。
I want you to be very careful with what I'm about to share as I have little to no security knowledge (There's a high chance that I'm misusing the API below), so I'd be more than welcome to update this answer with the help of the community .我希望你对我将要分享的内容非常小心,因为我几乎没有安全知识(我很可能滥用下面的 API),所以我非常欢迎更新这个答案在社区的帮助下。
As @richardtallent mentioned in his answer , there's support for the Web Crypto API, so this example uses the standard.正如@richardtallent 在他的回答中提到的,支持 Web Crypto API,因此本示例使用标准。 As of this writing, there's a 95.88% of global browser support .
在撰写本文时,全球浏览器支持 95.88% 。
I'm going to be sharing an example using the Web Crypto API我将分享一个使用 Web Crypto API 的示例
Before we proceed, please note ( Quoting from MDN ):在我们继续之前,请注意( 引自 MDN ):
This API provides a number of low-level cryptographic primitives.
此 API 提供了许多低级加密原语。 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 .
如果您不确定自己知道自己在做什么,那么您可能不应该使用这个 API 。
I respect security a lot, and I even bolded additional parts from MDN... You've been warned我非常尊重安全性,我什至在 MDN 中加粗了其他部分......你已经被警告过
Now, to the actual example...现在,以实际示例为例...
Found here: https://jsfiddle.net/superjose/rm4e0gqa/5/在这里找到: https : //jsfiddle.net/superjose/rm4e0gqa/5/
Note the use of await
keywords.注意
await
关键字的使用。 Use it inside an async
function or use .then()
and .catch()
.使用它的内部
async
功能或使用.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)}`)
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;
}
You can find more examples here (I'm not the owner): // https://github.com/diafygi/webcrypto-examples您可以在此处找到更多示例(我不是所有者):// https://github.com/diafygi/webcrypto-examples
you can use those function it's so easy the First one for encryption so you just call the function and send the text you wanna encrypt it and take the result from encryptWithAES function and send it to decrypt Function like this:你可以使用这些函数很容易第一个加密所以你只需调用函数并发送你想要加密的文本并从 encryptWithAES 函数中获取结果并将其发送到解密函数,如下所示:
const CryptoJS = require("crypto-js");
//The Function Below To Encrypt Text
const encryptWithAES = (text) => {
const passphrase = "My Secret Passphrase";
return CryptoJS.AES.encrypt(text, passphrase).toString();
};
//The Function Below To Decrypt Text
const decryptWithAES = (ciphertext) => {
const passphrase = "My Secret Passphrase";
const bytes = CryptoJS.AES.decrypt(ciphertext, passphrase);
const originalText = bytes.toString(CryptoJS.enc.Utf8);
return originalText;
};
let encryptText = encryptWithAES("YAZAN");
//EncryptedText==> //U2FsdGVkX19GgWeS66m0xxRUVxfpI60uVkWRedyU15I=
let decryptText = decryptWithAES(encryptText);
//decryptText==> //YAZAN
CryptoJS is no longer supported.不再支持 CryptoJS。 If you want to continue using it, you may switch to this url:
如果你想继续使用它,你可以切换到这个网址:
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>
crypt.subtle AES-GCM, self-contained, tested: crypt.subtle AES-GCM,自包含,经过测试:
async function aesGcmEncrypt(plaintext, password)
async function aesGcmDecrypt(ciphertext, password)
https://gist.github.com/chrisveness/43bcda93af9f646d083fad678071b90a https://gist.github.com/chrisveness/43bcda93af9f646d083fad678071b90a
Use SimpleCrypto使用简单加密
Using encrypt() and decrypt()使用 encrypt() 和decrypt()
To use SimpleCrypto, first create a SimpleCrypto instance with a secret key (password).
要使用 SimpleCrypto,首先创建一个带有密钥(密码)的 SimpleCrypto 实例。 Secret key parameter MUST be defined when creating a SimpleCrypto instance.
创建 SimpleCrypto 实例时必须定义密钥参数。
To encrypt and decrypt data, simply use encrypt() and decrypt() function from an instance.
要加密和解密数据,只需使用实例中的 encrypt() 和decrypt() 函数即可。 This will use AES-CBC encryption algorithm.
这将使用 AES-CBC 加密算法。
var _secretKey = "some-unique-key";
var simpleCrypto = new SimpleCrypto(_secretKey);
var plainText = "Hello World!";
var chiperText = simpleCrypto.encrypt(plainText);
console.log("Encryption process...");
console.log("Plain Text : " + plainText);
console.log("Cipher Text : " + cipherText);
var decipherText = simpleCrypto.decrypt(cipherText);
console.log("... and then decryption...");
console.log("Decipher Text : " + decipherText);
console.log("... done.");
Simple functions:简单的功能:
function Encrypt(value)
{
var result="";
for(i=0;i<value.length;i++)
{
if(i<value.length-1)
{
result+=value.charCodeAt(i)+10;
result+="-";
}
else
{
result+=value.charCodeAt(i)+10;
}
}
return result;
}
function Decrypt(value)
{
var result="";
var array = value.split("-");
for(i=0;i<array.length;i++)
{
result+=String.fromCharCode(array[i]-10);
}
return result;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.