Crypto JS Doc

ShiftWatchOut,JS前端translation

初始文档: https://code.google.com/archive/p/crypto-js/ (opens in a new tab)https://cryptojs.gitbook.io/docs/ (opens in a new tab)

标准安全加密算法的 JavaScript 实现。

CryptoJS 是在 JavaScript 中使用最佳实践和设计模式实现的标准安全加密算法的集合(不确定是否还会持续增长)。它们速度很快,并且具有一致且简单的接口。

如果您对 CryptoJS 有疑问,如果您想讨论新功能,或者您想为项目做出贡献,您可以访问 CryptoJS 的 讨论组 (opens in a new tab)

哈希

哈希算法
MD5

MD5 是一种广泛使用的哈希函数。它已被用于各种安全应用程序,也常用于检查文件完整性。但是,MD5 无法防止碰撞的,因此它并不适用于 SSL 证书或数字签名这类依赖抗碰撞特性的应用。

var hash = CryptoJS.MD5("Message");
SHA-1

SHA 哈希函数由美国国家安全局 (NSA) 设计。SHA-1 是现有 SHA 哈希函数中最成熟的,它被用于各种安全应用和协议。不过,随着攻击方式的更新,SHA-1 的抗碰撞能力一直在减弱。

var hash = CryptoJS.SHA1("Message");
SHA-2

SHA-256 是 SHA-2 系列中的四个变体之一。尽管它似乎提供了更好的安全性,但却不像 SHA-1 那样被广泛使用。

var hash = CryptoJS.SHA256("Message");

SHA-512 与 SHA-256 基本相同,但它运行在 64 位字上而不是 32 位。(what?)

var hash = CryptoJS.SHA512("Message");

CryptoJS 还支持 SHA-224 和 SHA-384,它们大致相同,但分别是 SHA-256 和 SHA-512 的截短版。

SHA-3

SHA-3 是一项为期五年的竞赛的胜出者,该竞赛为了选出一种新的加密哈希算法,对 64 种竞争设计进行了评估。

注意: 当我将此实现命名为 SHA-3 时,我犯了一个错误。它应该被命名为 Keccak[c=2d]。每个 SHA-3 函数都基于 Keccak 算法的一个实例,NIST 将其选为 SHA-3 竞赛的获胜者,但这些 CryptoJS 内的 SHA-3 函数不会产生与 Keccak 相同的哈希值。

var hash = CryptoJS.SHA3("Message");

SHA-3 可被配置为输出 224、256、384 或 512 位的哈希长度。默认为 512 位。

var hash = CryptoJS.SHA3("Message", { outputLength: 512 });

var hash = CryptoJS.SHA3("Message", { outputLength: 384 });

var hash = CryptoJS.SHA3("Message", { outputLength: 256 });

var hash = CryptoJS.SHA3("Message", { outputLength: 224 });
RIPEMD-160
var hash = CryptoJS.RIPEMD160("Message");
哈希输入

哈希算法接收字符串或 CryptoJS.lib.WordArray 的实例作为参数。WordArray 对象表示一个 32 位字的数组。当您传递一个字符串时,它会自动转换为 UTF-8 编码的 WordArray。

哈希输出

算法返回给您的哈希还不是一个字符串。它是一个 WordArray 对象。在会隐式转换为字符串的上下文中使用 WordArray 对象时,它会自动转换为十六进制字符串。

var hash = CryptoJS.SHA256("Message");

typeof hash
> "object";

hash
> "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91";

您可以通过显式调用 toString 方法并传递编码器,将 WordArray 对象转换为其他格式。

var hash = CryptoJS.SHA256("Message");

hash.toString(CryptoJS.enc.Base64)
> "L3dmip37+NWEi57rSnFFypTG7ZI25Kdz9tyvpRMrL5E=";

hash.toString(CryptoJS.enc.Hex)
> "2f77668a9dfbf8d5848b9eeb4a7145ca94c6ed9236e4a773f6dcafa5132b2f91";
渐进式哈希
var sha256 = CryptoJS.algo.SHA256.create();
sha256.update("Message Part 1");
sha256.update("Message Part 2");
sha256.update("Message Part 3");

var hash = sha256.finalize();
HMAC

密钥散列消息验证码 (HMAC) 是一种使用加密散列函数进行消息验证的机制。

HMAC 可以与任何迭代加密散列函数结合使用。

var hash = CryptoJS.HmacMD5("Message", "Secret Passphrase");
var hash = CryptoJS.HmacSHA1("Message", "Secret Passphrase");
var hash = CryptoJS.HmacSHA256("Message", "Secret Passphrase");
var hash = CryptoJS.HmacSHA512("Message", "Secret Passphrase");
渐进式 HMAC 哈希
var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, "Secret Passphrase");
hmac.update("Message Part 1");
hmac.update("Message Part 2");
hmac.update("Message Part 3");

var hash = hmac.finalize();
PBKDF2

PBKDF2 是一个基于口令的密钥派生函数。在密码学的许多应用中,用户安全最终取决于密码,并且由于密码通常不能直接用作密码密钥,因此需要进行一些处理。

salt 为任何给定的密码提供大量密钥,并且迭代次数增加了从密码生成密钥的成本,从而也增加了攻击的难度。

var salt = CryptoJS.lib.WordArray.random(128 / 8);
var key128Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, {
  keySize: 128 / 32
});
var key256Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, {
  keySize: 256 / 32
});
var key512Bits = CryptoJS.PBKDF2("Secret Passphrase", salt, {
  keySize: 512 / 32
});
var key512Bits1000Iterations = CryptoJS.PBKDF2("Secret Passphrase", salt, {
  keySize: 512 / 32,
  iterations: 1000
});
密码
加密算法
AES

高级加密标准 (AES) 是美国联邦信息处理标准 (FIPS)。它是经过 5 年的历程,对 15 种设计进行评估后选出的。

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");

var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");

CryptoJS 支持 AES-128、AES-192 和 AES-256。它将根据您传入的密钥的大小来选择变体。如果您使用密码,那么它将生成一个 256 位密钥。

DES, Triple DES

DES 是以前占主导地位的加密算法,并作为官方联邦信息处理标准 (FIPS) 发布。由于密钥大小较小,DES 现在被认为是不安全的。

var encrypted = CryptoJS.DES.encrypt("Message", "Secret Passphrase");

var decrypted = CryptoJS.DES.decrypt(encrypted, "Secret Passphrase");

Triple DES 对每个块应用 DES 三次以增加密钥大小。该算法在这种形式下被认为是安全的。

var encrypted = CryptoJS.TripleDES.encrypt("Message", "Secret Passphrase");

var decrypted = CryptoJS.TripleDES.decrypt(encrypted, "Secret Passphrase");
Rabbit

Rabbit 是一种高性能流密码,也是 eSTREAM Portfolio 的决赛选手。它是在 3 年半的时间里选出的四种设计之一,其间有 22 种设计被评估。

var encrypted = CryptoJS.Rabbit.encrypt("Message", "Secret Passphrase");

var decrypted = CryptoJS.Rabbit.decrypt(encrypted, "Secret Passphrase");
RC4, RC4Drop

RC4 是一种广泛使用的流密码。它被用于流行的协议,例如 SSL 和 WEP。尽管该算法的简单性和速度令人瞩目,但该算法的出身并没有激发人们对其安全性的信心。

var encrypted = CryptoJS.RC4.encrypt("Message", "Secret Passphrase");

var decrypted = CryptoJS.RC4.decrypt(encrypted, "Secret Passphrase");

密钥流的前几个字节是非随机的,并且会泄漏有关密钥的信息。我们可以通过丢弃密钥流的初始部分来防御这种攻击。这种修改后的算法传统上称为 RC4-drop。

默认情况下,修改后的算法会删除 192 个字(768 字节),但您可以将其配置为删除任意数量的字。

var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase");

var encrypted = CryptoJS.RC4Drop.encrypt("Message", "Secret Passphrase", {
  drop: 3072 / 4
});

var decrypted = CryptoJS.RC4Drop.decrypt(encrypted, "Secret Passphrase", {
  drop: 3072 / 4
});
自定义 Key 和 IV
var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");

var iv = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");

var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv });
块模式和填充
var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", {
  mode: CryptoJS.mode.CFB,
  padding: CryptoJS.pad.AnsiX923
});

CryptoJS 支持下列模式:

以及下列填充方案:

加密输入

对于明文消息,密码算法接受字符串或 CryptoJS.lib.WordArray 的实例。

对于密钥,当您传递一个字符串时,它会被视为密码并用于派生实际密钥和 IV。或者您可以传递一个代表实际密钥的 WordArray。如果您传递实际密钥,则还必须传递实际 IV。

对于密文,密码算法接受字符串或 CryptoJS.lib.CipherParams 的实例。CipherParams 对象表示参数的集合,例如 IV、salt 和原始密文本身。当您传递一个字符串时,它会根据可配置的格式策略自动转换为 CipherParams 对象。

加密输出

解密后得到的明文是一个 WordArray 对象。有关更多详细信息,请参阅哈希输出。

加密后得到的密文还不是字符串。这是一个 CipherParams 对象。CipherParams 对象允许您访问加密期间使用的所有参数。当您在字符串上下文中使用 CipherParams 对象时,它会根据格式策略自动转换为字符串。默认为与 OpenSSL 兼容的格式。

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");

encrypted.key
> "74eb593087a982e2a6f5dded54ecd96d1fd0f3d44a58728cdcd40c55227522223 ";

encrypted.iv
> "7781157e2629b094f0e3dd48c4d786115";

encrypted.salt
> "7a25f9132ec6a8b34";

encrypted.ciphertext
> "73e54154a15d1beeb509d9e12f1e462a0";

encrypted
> "U2FsdGVkX1+iX5Ey7GqLND5UFUoV0b7rUJ2eEvHkYqA=";

您可以定义自己的格式,以便与其他加密实现兼容。格式是一个具有 stringifyparse 两种方法的对象。使得其能够将 CipherParams 对象和密文字符串进行彼此转换。

您可以像下面这样编写一个 JSON 格式化程序:

var JsonFormatter = {
  stringify: function(cipherParams) {
    // create json object with ciphertext
    var jsonObj = { ct: cipherParams.ciphertext.toString(CryptoJS.enc.Base64) };

    // optionally add iv or 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
    var jsonObj = JSON.parse(jsonStr);

    // extract ciphertext from json object, and create cipher params object
    var cipherParams = CryptoJS.lib.CipherParams.create({
      ciphertext: CryptoJS.enc.Base64.parse(jsonObj.ct)
    });

    // optionally extract iv or salt

    if (jsonObj.iv) {
      cipherParams.iv = CryptoJS.enc.Hex.parse(jsonObj.iv);
    }

    if (jsonObj.s) {
      cipherParams.salt = CryptoJS.enc.Hex.parse(jsonObj.s);
    }

    return cipherParams;
  }
};

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase", {
  format: JsonFormatter
});

encrypted
> {
    ct: "tZ4MsEnfbcDOwqau68aOrQ==",
    iv: "8a8c8fd8fe33743d3638737ea4a00698",
    s: "ba06373c8f57179c"
  };

var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase", {
  format: JsonFormatter
});

decrypted.toString(CryptoJS.enc.Utf8)
> "Message";
渐进式加密
var key = CryptoJS.enc.Hex.parse("000102030405060708090a0b0c0d0e0f");
var iv = CryptoJS.enc.Hex.parse("101112131415161718191a1b1c1d1e1f");

// encrypt
var aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, { iv: iv });

var ciphertextPart1 = aesEncryptor.process("Message Part 1");
var ciphertextPart2 = aesEncryptor.process("Message Part 2");
var ciphertextPart3 = aesEncryptor.process("Message Part 3");
var ciphertextPart4 = aesEncryptor.finalize();

// decrypt
var aesDecryptor = CryptoJS.algo.AES.createDecryptor(key, { iv: iv });

var plaintextPart1 = aesDecryptor.process(ciphertextPart1);
var plaintextPart2 = aesDecryptor.process(ciphertextPart2);
var plaintextPart3 = aesDecryptor.process(ciphertextPart3);
var plaintextPart4 = aesDecryptor.process(ciphertextPart4);
var plaintextPart5 = aesDecryptor.finalize();
互操作性

与 OpenSSL

使用 OpenSSL 加密:

openssl enc -aes-256-cbc -in infile -out outfile -pass pass:"Secret Passphrase" -e -base64

使用 CryptoJS 解密:

var decrypted = CryptoJS.AES.decrypt(openSSLEncrypted, "Secret Passphrase");
编码器

CryptoJS可以将Base64、Latin1或Hex等编码格式转换为WordArray对象,反之亦然。

var words = CryptoJS.enc.Base64.parse("SGVsbG8sIFdvcmxkIQ==");

var base64 = CryptoJS.enc.Base64.stringify(words);

var words = CryptoJS.enc.Latin1.parse("Hello, World!");

var latin1 = CryptoJS.enc.Latin1.stringify(words);

var words = CryptoJS.enc.Hex.parse("48656c6c6f2c20576f726c6421");

var hex = CryptoJS.enc.Hex.stringify(words);

var words = CryptoJS.enc.Utf8.parse("𔭢");

var utf8 = CryptoJS.enc.Utf8.stringify(words);

var words = CryptoJS.enc.Utf16.parse("Hello, World!");

var utf16 = CryptoJS.enc.Utf16.stringify(words);

var words = CryptoJS.enc.Utf16LE.parse("Hello, World!");

var utf16 = CryptoJS.enc.Utf16LE.stringify(words);

译者:感脚这个文档写得一般,动不动就讲算法的来历,背后涉及的竞赛,很少提出注意事项。在我今天的实际使用过程中,通过它的 AES 加密方法生成的 string 居然无法通过 cryptojs 进行解密。然鹅 iOS 的加密库拿到密文和 key 却能解密,晕。好在我浏览器端并不需要解密 O(∩_∩)O。Github 的 issue 列表里大量的 Malformed UTF-8 data 相关报错始终没有得到作者的解答,遗憾

© ShiftWatchOut.RSS