JavaScript字符串加密和解密?

2020/11/01 01:22 · javascript ·  · 0评论

我有兴趣构建一个供个人使用的小型应用程序,该应用程序将使用JavaScript在客户端加密和解密信息。加密的信息将存储在服务器上的数据库中,但不会存储在解密版本中。

它不必具有超级duper的安全性,但是我想使用当前不间断的算法。

理想情况下,我可以做类似的事情

var gibberish = encrypt(string, salt, key);

生成编码的字符串,诸如此类

var sensical = decrypt(gibberish, key);

稍后再解码。

到目前为止,我已经看到了:http :
//bitwiseshiftleft.github.io/sjcl/

我应该看看其他图书馆吗?

 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>

CryptoJS怎么

这是一个可靠的加密库,具有很多功能。它实现了哈希,HMAC,PBKDF2和密码。在这种情况下,您需要密码。在项目的主页上查看快速入门指南。

您可以使用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>

至于安全性,在撰写本文时,AES算法被认为是不间断的

编辑:

似乎在线URL已关闭,并且您可以从给定的链接下面使用下载的文件进行加密,并将相应的文件放在应用程序的根文件夹中。

https://code.google.com/archive/p/crypto-js/downloads

或使用其他CDN,例如https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/components/aes-min.js

我创建了一个不安全但简单的文本密码解密工具。没有与任何外部库的依赖关系。

这些是功能

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('');
}

您可以如下使用它们:

// 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'

利用SJCL,CryptoJS和/或WebCrypto的现有答案不一定是错误的,但是它们并不像您最初怀疑的那样安全。通常,您要使用libsodium首先,我将解释原因,然后再解释。

为什么不选择SJCL,CryptoJS,WebCrypto等?

简短的答案:为了使您的加密实际上是安全的,这些库希望您做出太多选择,例如,块密码模式(CBC,CTR,GCM;如果您不能确定我刚刚列出的三个中的哪一个是安全的,使用和在什么样的约束,你不应该有这种选择的负担在所有)。

除非您的职位是密码学工程师否则您就无法安全地实施它。

为什么要避免使用CryptoJS?

CryptoJS提供了一些构建基块,希望您知道如何安全地使用它们。它甚至默认为CBC模式archived)。

为什么CBC模式不好?

阅读有关AES-CBC漏洞的文章

为什么要避免使用WebCrypto?

WebCrypto是委员会制定的杂烩标准,目的是与密码学工程正交。具体来说,WebCrypto旨在取代Flash,而不是提供安全性

为什么要避免SJCL?

SJCL的公共API和文档恳求用户使用人类记住的密码来加密数据。如果有的话,这几乎是您在现实世界中想要做的事情。

此外:其默认的PBKDF2舍入计数大约是您希望的86倍AES-128-CCM可能还不错。

在以上三个选项中,SJCL哭泣的可能性最小。但是有更好的选择。

为什么Libsodium更好?

您无需在密码模式,哈希函数和其他不必要选项的菜单之间进行选择。您绝不会冒险修改参数并从协议中删除所有安全性

相反,libsodium只是为您提供了针对最大安全性和简约API进行了调整的简单选项。

  • crypto_box()/crypto_box_open()提供经过身份验证的公钥加密。

    • 有问题的算法将X25519(Curve25519上的ECDH)和XSalsa20-Poly1305结合在一起,但是您无需知道(甚至不在乎)就可以安全地使用它
  • crypto_secretbox()/crypto_secretbox_open()提供共享密钥验证的加密。

    • 有问题的算法是XSalsa20-Poly1305,但是您不需要知道/关心

另外,libsodium具有数十种流行编程语言的绑定,因此libsodium很可能在尝试与另一个编程堆栈进行互操作时才可以工作同样,libsodium往往非常快而不会牺牲安全性。

如何在JavaScript中使用Libsodium?

首先,您需要决定一件事:

  1. 您是否只想加密/解密数据(也许仍然以某种方式安全地使用数据库查询中的纯文本),而不必担心细节?要么...
  2. 您需要实施特定协议吗?

如果选择了第一个选项,请获取CipherSweet.js

该文档可在线获得EncryptedField在大多数情况下就足够了,但是如果您要加密很多不同的字段,则EncryptedRowEncryptedMultiRowsAPI可能会更容易。

使用CipherSweet,您甚至不需要知道安全地使用它的随机数/ IV

此外,这可以处理int/float加密,而不会通过密文大小泄露有关内容的事实。

否则,您将需要sodium-plus它是各种libsodium包装器的用户友好前端。使用Sodium-Plus,您可以编写易于审计和推理的高性能,异步,跨平台代码。

要安装sodium-plus,只需运行...

npm install sodium-plus

当前没有用于浏览器支持的公共CDN。这将很快改变。但是,如果需要,可以sodium-plus.min.js最新的Github版本中获取

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());
})();

钠加的文档可在Github上找到。

如果您需要分步教程,那么这篇dev.to文章将为您提供所需的内容。

现代浏览器现在支持该crypto.subtleAPI,该API使用以下方法之一提供本机加密和解密功能(不少于异步!):AES-CBC,AES-CTR,AES-GCM或RSA-OAEP。

https://www.w3.org/TR/WebCryptoAPI/#dfn-Crypto

在实施上述任何一项之前,请参阅Scott Arciszewski的答案

我希望您对我将要分享的内容非常小心,因为我几乎没有安全知识(很有可能我误用了下面的API),所以我们非常乐意更新此答案在社区的帮助下

正如@richardtallent在他的回答中提到的那样,Web Crypto API受到支持,因此本示例使用该标准。在撰写本文时,全球浏览器支持达到95.88%

我将使用Web Crypto API共享一个示例

在继续之前,请注意(从MDN引用):

该API提供了许多底层密码原语。这是很容易滥用它们,和陷阱参与可以非常微妙

即使假设您正确地使用了基本密码功能,安全密钥管理和整体安全系统设计也很难实现,并且通常属于专业安全专家的领域。

安全系统设计和实施中的错误可能会使系统的安全性完全失效。

如果不确定自己在做什么,则可能不应该使用此API

我非常重视安全性,甚至还对MDN的其他部分进行了加粗...
现在
已经警告您

,到实际示例...


JSFiddle:

在这里找到:https : //jsfiddle.net/superjose/rm4e0gqa/5/

注意:

注意await关键字的使用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)}`)

从String来回转换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

不再支持CryptoJS。如果您想继续使用它,可以切换到以下网址:

<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.2/rollups/aes.js"></script>

使用SimpleCrypto

使用crypto()和解密()

要使用SimpleCrypto,首先要创建一个带有密钥(密码)的SimpleCrypto实例。创建SimpleCrypto实例时必须定义密钥参数。

要加密和解密数据,只需使用实例中的crypto()和crypto()函数。这将使用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.");

简单的功能,


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;
} 
本文地址:http://javascript.askforanswer.com/javascriptzifuchuanjiamihejiemi.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!