加密算法库与ES6和Typescript兼容
安装:
yarn add crypto-es
在node.js项目中,我们建议您使用commonjs的ecmascript模块:
// package.json
{
"type": "module"
}
然后,您可以导入加密:
import CryptoES from 'crypto-es';
const rst = CryptoES.MD5("Message").toString();
或部分导入功能以减少包装重量:
import { MD5 } from 'crypto-es/lib/md5.js';
const rst = MD5("Message").toString();
该库中的每个文件现在都有自己的.D.T.TS文件,因此可以在打字稿项目中部分导入单个算法文件。
与加密js相同
MD5
MD5是广泛使用的哈希函数。它已用于各种安全应用程序,也通常用于检查文件的完整性。但是,MD5不具有抗碰撞,并且不适用于依靠此属性的SSL证书或数字签名等应用。
const hash = CryptoES.MD5("Message");
SHA-1
SHA哈希功能是由国家安全局(NSA)设计的。 SHA-1是现有的SHA HASH功能中最建立的,它用于各种安全应用程序和协议。但是,随着发现或改进新攻击,SHA-1的碰撞阻力一直在减弱。
const hash = CryptoES.SHA1("Message");
SHA-2
SHA-256是SHA-2集中的四个变体之一。尽管它似乎提供了更好的安全性,但它并不像SHA-1那样广泛使用。
const hash = CryptoES.SHA256("Message");
SHA-512在很大程度上与SHA-256相同,但用64位单词而不是32个。
const hash = CryptoES.SHA512("Message");
加密还支持SHA-224和SHA-384,它们在很大程度上相同但分别是SHA-256和SHA-512的截断版本。
SHA-3
SHA-3是一项为期五年的比赛的冠军,该竞赛选择了一种新的加密哈希算法,其中评估了64种竞争设计。
注意:当我命名此实现SHA-3时,我犯了一个错误。它应命名为keccak [C = 2D]。 SHA-3功能中的每个函数都基于Keccak算法的实例,该算法被选为SHA-3竞赛的获胜者,但是这些SHA-3功能不会产生与Keccak相同的哈希。
const hash = CryptoES.SHA3("Message");
SHA-3可以配置为输出哈希长度为224、256、384或512位之一。默认值为512位。
const hash = CryptoES.SHA3("Message", { outputLength: 512 });
const hash = CryptoES.SHA3("Message", { outputLength: 384 });
const hash = CryptoES.SHA3("Message", { outputLength: 256 });
const hash = CryptoES.SHA3("Message", { outputLength: 224 });
Ripemd-160
const hash = CryptoES.RIPEMD160("Message");
哈希算法接受cryptoes.lib.wordarray的字符串或实例。 WordArray对象表示32位单词的数组。当您传递字符串时,它会自动转换为编码为UTF-8的文字。
您回来的哈希还不是字符串。这是一个wordarray对象。当您在字符串上下文中使用WordArray对象时,它会自动转换为十六进制字符串。
const hash = CryptoES.SHA256("Message");
alert(typeof hash); // object
alert(hash); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91
您可以通过明确调用ToString方法并传递编码器来将WordArray对象转换为其他格式。
const hash = CryptoES.SHA256("Message");
alert(hash.toString(CryptoES.enc.Base64)); // L3dmip37+NWEi57rSnFFypTG7ZI25Kdz9tyvpRMrL5E= alert(hash.toString(CryptoES.enc.Latin1)); // /wf��ûøÕ���ëJqEÊ�Æí�6ä§söܯ¥�+/�
alert(hash.toString(CryptoES.enc.Hex)); // 2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91
const sha256 = CryptoES.algo.SHA256.create();
sha256.update("Message Part 1");
sha256.update("Message Part 2");
sha256.update("Message Part 3");
const hash = sha256.finalize();
键入锤击消息身份验证代码(HMAC)是使用加密哈希功能的消息身份验证的机制。
HMAC可以与任何迭代的加密哈希功能结合使用。
const hash = CryptoES.HmacMD5("Message", "Secret Passphrase");
const hash = CryptoES.HmacSHA1("Message", "Secret Passphrase");
const hash = CryptoES.HmacSHA256("Message", "Secret Passphrase");
const hash = CryptoES.HmacSHA512("Message", "Secret Passphrase");
const hmac = CryptoES.algo.HMAC.create(CryptoES.algo.SHA256, "Secret Passphrase");
hmac.update("Message Part 1");
hmac.update("Message Part 2");
hmac.update("Message Part 3");
const hash = hmac.finalize();
PBKDF2是基于密码的密钥推导功能。在密码学的许多应用中,用户安全最终取决于密码,并且由于密码通常不能直接用作加密密钥,因此需要进行一些处理。
盐为任何给定的密码提供了大量键,迭代计数增加了从密码中生产钥匙的成本,从而增加了攻击的困难。
const salt = CryptoES.lib.WordArray.random(128/8);
const key128Bits = CryptoES.PBKDF2("Secret Passphrase", salt, { keySize: 128/32 });
const key256Bits = CryptoES.PBKDF2("Secret Passphrase", salt, { keySize: 256/32 });
const key512Bits = CryptoES.PBKDF2("Secret Passphrase", salt, { keySize: 512/32 });
const key512Bits1000Iterations = CryptoES.PBKDF2("Secret Passphrase", salt, { keySize: 512/32, iterations: 1000 });
AES
高级加密标准(AES)是美国联邦信息处理标准(FIPS)。在5年的过程中选择了15种竞争设计。
const encrypted = CryptoES.AES.encrypt("Message", "Secret Passphrase");
const decrypted = CryptoES.AES.decrypt(encrypted, "Secret Passphrase");
加密支持AES-128,AES-192和AES-256。它将通过您传递的密钥的大小选择变体。如果您使用密码,则它将生成256位键。
des,三倍
DES是一种以前主要的加密算法,并作为官方的联邦信息处理标准(FIPS)出版。由于钥匙尺寸小,DES被认为是不安全的。
const encrypted = CryptoES.DES.encrypt("Message", "Secret Passphrase");
const decrypted = CryptoES.DES.decrypt(encrypted, "Secret Passphrase");
Triple DES将DES应用于每个块,以增加密钥大小。该算法被认为以这种形式安全。
const encrypted = CryptoES.TripleDES.encrypt("Message", "Secret Passphrase");
const decrypted = CryptoES.TripleDES.decrypt(encrypted, "Secret Passphrase");
兔子
兔子是一个高性能的流密封器,也是埃特里姆投资组合中的决赛入围者。它是在评估22种设计后进行3 1/2年后选择的四个设计之一。
const encrypted = CryptoES.Rabbit.encrypt("Message", "Secret Passphrase");
const decrypted = CryptoES.Rabbit.decrypt(encrypted, "Secret Passphrase");
RC4,RC4Drop
RC4是一个广泛使用的流密码。它用于流行协议,例如SSL和WEP。算法的历史并没有激发其对安全性的信心,尽管它以其简单和速度而出色。
const encrypted = CryptoES.RC4.encrypt("Message", "Secret Passphrase");
const decrypted = CryptoES.RC4.decrypt(encrypted, "Secret Passphrase");
人们发现,键流的前几个字节是强烈的非随机,并且有关钥匙的泄漏信息。我们可以通过丢弃键流的初始部分来防御这种攻击。这种修改的算法传统上称为RC4-Drop。
默认情况下,删除了192个单词(768个字节),但是您可以配置算法以删除任何数量的单词。
const encrypted = CryptoES.RC4Drop.encrypt("Message", "Secret Passphrase");
const encrypted = CryptoES.RC4Drop.encrypt("Message", "Secret Passphrase", { drop: 3072/4 });
const decrypted = CryptoES.RC4Drop.decrypt(encrypted, "Secret Passphrase", { drop: 3072/4 });
池塘
Blowfish是一种对称键的密码,由Bruce Schneier于1993年设计,并包括在许多密码套件和加密产品中。 Blowfish在软件中提供了良好的加密速率,迄今为止尚未发现对其进行有效的密码分析。但是,高级加密标准(AES)现在受到更多关注,Schneier建议对现代应用进行双重关注。
Schneier将洪水设计为一种通用算法,旨在替代衰老DES,并且没有与其他算法相关的问题和约束。当时释放了洪水,许多其他设计都是专有的,由专利构成,或者是商业或政府的秘密。 Schneier表示:“ Blodfish未经批评,并且将在所有国家 /地区保持如此。该算法在此放置在公共领域,任何人都可以自由使用。”
该设计的显着功能包括依赖密钥的S框和高度复杂的密钥时间表。
const ciphertext = CryptoJS.Blowfish.encrypt(message, key, cfg);
const plaintext = CryptoJS.Blowfish.decrypt(ciphertext, key, cfg);
const key = CryptoES.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
const iv = CryptoES.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
const encrypted = CryptoES.AES.encrypt("Message", key, { iv: iv });
const encrypted = CryptoES.AES.encrypt("Message", "Secret Passphrase", { mode: CryptoES.mode.CFB, padding: CryptoES.pad.AnsiX923 });
加密支持以下模式:
加密支持以下填充方案:
对于明文消息,密码算法接受cryptoes.lib.wordarray的字符串或实例。
对于钥匙,当您通过字符串时,它被视为密码,并用于得出实际的键和IV。或者,您可以通过代表实际键的文字段。如果您通过实际键,则还必须通过实际的IV。
对于密文,密码算法接受cryptoes.lib.cipherparams的字符串或实例。一个密码对象表示参数的集合,例如IV,盐和原始密文本身。当您传递字符串时,它会根据可配置的格式策略自动将其转换为CipherParams对象。
解密后您获得的明文是WordArray对象。有关更多详细信息,请参见哈希斯的输出。
加密后您会返回的密文还不是字符串。这是一个密码对象。 CipherParams对象使您可以访问加密过程中使用的所有参数。当您在字符串上下文中使用CipherParams对象时,它会根据格式策略自动转换为字符串。默认值是openssl兼容的格式。
const encrypted = CryptoES.AES.encrypt("Message", "Secret Passphrase"); alert(encrypted.key); // 74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223
alert(encrypted.iv); // 7781157e2629b094f0e3dd48c4d786115
alert(encrypted.salt); // 7a25f9132ec6a8b34
alert(encrypted.ciphertext); // 73e54154a15d1beeb509d9e12f1e462a0
alert(encrypted); // U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA=
您可以定义自己的格式,以便与其他加密实现兼容。格式是一种具有两种方法的对象,即Stringify和parse-在密码对象和密文字符串之间转换。
您可能会写JSON Formatter:
const JsonFormatter = {
stringify: function (cipherParams) { // create json object with ciphertext
const jsonObj = { ct: cipherParams.ciphertext.toString(CryptoES.enc.Base64) }; // optionally add iv and salt
if (cipherParams.iv) {
jsonObj.iv = cipherParams.iv.toString();
}
if (cipherParams.salt) {
jsonObj.s = cipherParams.salt.toString();
}
// stringify json object
return JSON.stringify(jsonObj);
},
parse: function (jsonStr) { // parse json string
const jsonObj = JSON.parse(jsonStr); // extract ciphertext from json object, and create cipher params object
const cipherParams = CryptoES.lib.CipherParams.create(
{ ciphertext: CryptoES.enc.Base64.parse(jsonObj.ct) },
); // optionally extract iv and salt
if (jsonObj.iv) {
cipherParams.iv = CryptoES.enc.Hex.parse(jsonObj.iv)
}
if (jsonObj.s) {
cipherParams.salt = CryptoES.enc.Hex.parse(jsonObj.s)
}
return cipherParams;
},
};
const encrypted = CryptoES.AES.encrypt(
"Message",
"Secret Passphrase",
{ format: JsonFormatter },
);
alert(encrypted); // {"ct":"tZ4MsEnfbcDOwqau68aOrQ==","iv":"8a8c8fd8fe33743d3638737ea4a00698","s":"ba06373c8f57179c"}
const decrypted = CryptoES.AES.decrypt(
encrypted,
"Secret Passphrase",
{ format: JsonFormatter },
);
alert(decrypted.toString(CryptoES.enc.Utf8)); // Message
const key = CryptoES.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
const iv = CryptoES.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');
const aesEncryptor = CryptoES.algo.AES.createEncryptor(key, { iv: iv });
const ciphertextPart1 = aesEncryptor.process("Message Part 1");
const ciphertextPart2 = aesEncryptor.process("Message Part 2");
const ciphertextPart3 = aesEncryptor.process("Message Part 3");
const ciphertextPart4 = aesEncryptor.finalize();
const aesDecryptor = CryptoES.algo.AES.createDecryptor(key, { iv: iv });
const plaintextPart1 = aesDecryptor.process(ciphertextPart1);
const plaintextPart2 = aesDecryptor.process(ciphertextPart2);
const plaintextPart3 = aesDecryptor.process(ciphertextPart3);
const plaintextPart4 = aesDecryptor.process(ciphertextPart4);
const plaintextPart5 = aesDecryptor.finalize();
使用OpenSSL
使用OpenSSL加密:
openssl enc -aes-256-cbc -in infile -out outfile -pass pass:"Secret Passphrase" -e -base64
用加密解密:
const decrypted = CryptoES.AES.decrypt(openSSLEncrypted, "Secret Passphrase");
加密可以从诸如base64,latin1或十六进制的编码格式转换为WordArray对象,反之亦然。
const words = CryptoES.enc.Base64.parse('SGVsbG8sIFdvcmxkIQ==');
const base64 = CryptoES.enc.Base64.stringify(words);
const words = CryptoES.enc.Base64url.parse('SGVsbG8sIFdvcmxkIQ==');
const base64url = CryptoES.enc.Base64.stringify(words);
const words = CryptoES.enc.Latin1.parse('Hello, World!');
const latin1 = CryptoES.enc.Latin1.stringify(words);
const words = CryptoES.enc.Hex.parse('48656c6c6f2c20576f726c6421');
const hex = CryptoES.enc.Hex.stringify(words);
const words = CryptoES.enc.Utf8.parse('?');
const utf8 = CryptoES.enc.Utf8.stringify(words);
const words = CryptoES.enc.Utf16.parse('Hello, World!');
const utf16 = CryptoES.enc.Utf16.stringify(words);
const words = CryptoES.enc.Utf16LE.parse('Hello, World!');
const utf16 = CryptoES.enc.Utf16LE.stringify(words);
WordArray的创建者可以恢复ArrayBuffer或TypedArray,以便加密算法可以适用于它们:
const words = CryptoES.lib.WordArray.create(new ArrayBuffer(8));
const rst = CryptoES.AES.encrypt(words, 'Secret Passphrase')
注意:ArrayBuffer不能直接传递给算法,您应该首先将它们更改为WordArray。
这样,加密文件将更容易:
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function () {
const arrayBuffer = reader.result;
const words = CryptoES.lib.WordArray.create(arrayBuffer);
const rst = CryptoES.AES.encrypt(words, 'Secret Passphrase')
...
};
更改日志
在现代ecmascript中重构加密