加密算法庫與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中重構加密