9.3 数据加密 crypto

发布于 2024-09-06 00:31:39 字数 13866 浏览 12 评论 0

hash 例子

hash.digest([encoding]):计算摘要。encoding 可以是 hexlatin1 或者 base64 。如果声明了 encoding,那么返回字符串。否则,返回 Buffer 实例。注意,调用 hash.digest() 后,hash 对象就作废了,再次调用就会出错。

hash.update(data[, input_encoding]):input_encoding 可以是 utf8ascii 或者 latin1 。如果 data 是字符串,且没有指定 input_encoding,则默认是 utf8 。注意,hash.update() 方法可以调用多次。

var crypto = require('crypto');
var fs = require('fs');

var content = fs.readFileSync('./test.txt', {encoding: 'utf8'});
var hash = crypto.createHash('sha256');
var output;

hash.update(content);

output = hash.digest('hex'); 

console.log(output);
// 输出内容为:
// b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

也可以这样:

var crypto = require('crypto');
var fs = require('fs');

var input = fs.createReadStream('./test.txt', {encoding: 'utf8'});
var hash = crypto.createHash('sha256');

hash.setEncoding('hex');

input.pipe(hash).pipe(process.stdout)

// 输出内容为:
// b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9

hash.digest() 后,再次调用 digest() 或者 update()

var crypto = require('crypto');
var fs = require('fs');

var content = fs.readFileSync('./test.txt', {encoding: 'utf8'});
var hash = crypto.createHash('sha256');
var output;

hash.update(content);
hash.digest('hex'); 

// 报错:Error: Digest already called
hash.update(content);

// 报错:Error: Digest already called
hash.digest('hex');

HMAC 例子

HMAC 的全称是 Hash-based Message Authentication Code,也即在 hash 的加盐运算。

算法细节可以参考附录链接,具体到使用的话,跟 hash 模块差不多,选定 hash 算法,指定“盐”即可。

例子 1:

var crypto = require('crypto');
var fs = require('fs');

var secret = 'secret';
var hmac = crypto.createHmac('sha256', secret);
var input = fs.readFileSync('./test.txt', {encoding: 'utf8'});

hmac.update(input);

console.log( hmac.digest('hex') );
// 输出:
// 734cc62f32841568f45715aeb9f4d7891324e6d948e4c6c60c0621cdac48623a

例子 2:

var crypto = require('crypto');
var fs = require('fs');

var secret = 'secret';
var hmac = crypto.createHmac('sha256', secret);
var input = fs.createReadStream('./test.txt', {encoding: 'utf8'});

hmac.setEncoding('hex');

input.pipe(hmac).pipe(process.stdout)
// 输出:
// 734cc62f32841568f45715aeb9f4d7891324e6d948e4c6c60c0621cdac48623a

加密/解密

加解密主要用到下面两组方法:

加密:

  • crypto.createCipher(algorithm, password)
  • crypto.createCipheriv(algorithm, key, iv)

解密:

  • crypto.createDecipher(algorithm, password)
  • crypto.createDecipheriv(algorithm, key, iv)

crypto.createCipher(algorithm, password)

先来看下 crypto.createCipher(algorithm, password),两个参数分别是加密算法、密码

  • algorithm:加密算法,比如 aes192 ,具体有哪些可选的算法,依赖于本地 openssl 的版本,可以通过 openssl list-cipher-algorithms 命令查看支持哪些算法。
  • password:用来生成密钥(key)、初始化向量(IV)。

备注:这里 nodejs 屏蔽了 AES 的使用/实现细节,关于 key、IV,感兴趣的同学可以自行谷歌下。

var crypto = require('crypto');
var secret = 'secret';

var cipher = crypto.createCipher('aes192', secret);
var content = 'hello';
var cryptedContent;

cipher.update(content);
cryptedContent = cipher.final('hex');
console.log(cryptedContent);
// 输出:
// 71d30ec9bc926b5dbbd5150bf9d3e5fb

crypto.createDecipher(algorithm, password)

可以看作 crypto.createCipher(algorithm, password) 逆向操作,直接看例子

var crypto = require('crypto');
var secret = 'secret';

var cipher = crypto.createCipher('aes192', secret);
var content = 'hello';
var cryptedContent;

cipher.update(content);
cryptedContent = cipher.final('hex');
console.log(cryptedContent);
// 输出:
// 71d30ec9bc926b5dbbd5150bf9d3e5fb

var decipher = crypto.createDecipher('aes192', secret);
var decryptedContent;

decipher.update(cryptedContent, 'hex');
decryptedContent = decipher.final('utf8');
console.log(decryptedContent);
// 输出:
// hello

crypto.createCipheriv(algorithm, key, iv)

相对于 crypto.createCipher() 来说,crypto.createCipheriv() 需要提供 keyiv ,而 crypto.createCipher() 是根据用户提供的 password 算出来的。

key、iv 可以是 Buffer,也可以是 utf8 编码的字符串,这里需要关注的是它们的长度:

  • key:根据选择的算法有关,比如 aes128、aes192、aes256,长度分别是 128、192、256 位(16、24、32 字节)
  • iv:都是 128 位(16 字节)
var crypto = require('crypto');
var key = crypto.randomBytes(192/8);
var iv = crypto.randomBytes(128/8);
var algorithm = 'aes192';

function encrypt(text){
    var cipher = crypto.createCipheriv(algorithm, key, iv);
    cipher.update(text);
    return cipher.final('hex');
}

function decrypt(encrypted){
    var decipher = crypto.createDecipheriv(algorithm, key, iv);
    decipher.update(encrypted, 'hex');
    return decipher.final('utf8');
}

var content = 'hello';
var crypted = encrypt('hello');
console.log( crypted );

var decrypted = decrypt( crypted );
console.log( decrypted );  // 输出:utf8

数字签名/签名校验

假设:

1、服务端原始信息为 M,摘要算法为 Hash,Hash(M) 得出的摘要是 H。 2、公钥为 Pub,私钥为 Piv,非对称加密算法为 Encrypt,非对称解密算法为 Decrypt。 3、Encrypt(H) 得到的结果是 S。 4、客户端拿到的信息为 M1,利用 Hash(M1) 得出的结果是 H1。

数字签名的产生、校验步骤分别如下:

2、数字签名的产生步骤:利用摘要算法 Hash 算出 M 的摘要,即 Hash(M) == H,利用非对称加密算法对摘要进行加密 Encrypt( H, Piv ),得到数字签名 S。 2、数字签名的校验步骤:利用解密算法 D 对数字签名进行解密,即 Decrypt(S) == H,计算 M1 的摘要 Hash(M1) == H1,对比 H、H1,如果两者相同,则通过校验。

私钥如何生成不是这里的重点,这里采用网上的服务来生成,点击 这里

了解了数字签名产生、校验的原理后,相信下面的代码很容易理解:

var crypto = require('crypto');
var fs = require('fs');
var privateKey = fs.readFileSync('./private-key.pem');  // 私钥
var publicKey = fs.readFileSync('./public-key.pem');  // 公钥
var algorithm = 'RSA-SHA256';  // 加密算法 vs 摘要算法

// 数字签名
function sign(text){
    var sign = crypto.createSign(algorithm);
    sign.update(text);
    return sign.sign(privateKey, 'hex');    
}

// 校验签名
function verify(oriContent, signature){
    var verifier = crypto.createVerify(algorithm);
    verifier.update(oriContent);
    return verifier.verify(publicKey, signature, 'hex');
}

// 对内容进行签名
var content = 'hello world';
var signature = sign(content);
console.log(signature);

// 校验签名,如果通过,返回 true
var verified = verify(content, signature);
console.log(verified);

DiffieHellman

DiffieHellman:Diffie–Hellman key exchange,缩写为 D-H,是一种安全协议,让通信双方在预先没有对方信息的情况下,通过不安全通信信道,创建一个密钥。这个密钥可以在后续的通信中,作为对称加密的密钥加密传递的信息。

代码如下,原理待补充 TODO

const crypto = require('crypto');
const assert = require('assert');

// Generate Alice's keys...
const alice = crypto.createDiffieHellman(2048);
const alice_key = alice.generateKeys();

// Generate Bob's keys...
const bob = crypto.createDiffieHellman(alice.getPrime(), alice.getGenerator());
const bob_key = bob.generateKeys();

// Exchange and generate the secret...
const alice_secret = alice.computeSecret(bob_key);
const bob_secret = bob.computeSecret(alice_key);

// OK
assert.equal(alice_secret.toString('hex'), bob_secret.toString('hex'));

ECDH:Elliptic Curve Diffie-Hellman

代码如下,原理待补充 TODO

const crypto = require('crypto');
const assert = require('assert');

// Generate Alice's keys...
const alice = crypto.createECDH('secp521r1');
const alice_key = alice.generateKeys();

// Generate Bob's keys...
const bob = crypto.createECDH('secp521r1');
const bob_key = bob.generateKeys();

// Exchange and generate the secret...
const alice_secret = alice.computeSecret(bob_key);
const bob_secret = bob.computeSecret(alice_key);

assert(alice_secret, bob_secret);
  // OK

证书

SPKAC:

SPKAC is an acronym that stands for Signed Public Key and Challenge, also known as Netscape SPKI.

SPKI:Simple public-key infrastructure

关键点

md5:固定长度(128bit)、不可逆(重要)、不同数据的散列值可能相同(重要)、高度离散型(原文细微的变化,会导致散列值差异巨大)

sha1:固定长度 160bit,广泛使用(如 TLS,目前安全性受到密码学家的质疑)

SHA-256/SHA-384/SHA-512:后面表示摘要的长度。

用途:数字签名、文件完整性校验

关系:sha1 基于 MD5,MD5 基于 MD4

md5(1991) -> SHA1

sha 家族:由美国国家安全局(NSA)所设计,并由美国国家标准与技术研究院(NIST)发布;是美国的政府标准。

相关术语

SPKAC:Signed Public Key and Challenge

MD5:Message-Digest Algorithm 5,信息-摘要算法。

SHA:Secure Hash Algorithm,安全散列算法。

HMAC:Hash-based Message Authentication Code,密钥相关的哈希运算消息认证码。

SPKAC:

  • 对称加密:比如 AES、DES
  • 非对称加密:比如 RSA、DSA

AES:Advanced Encryption Standard(高级加密标准),密钥长度可以是 128、192 和 256 位。

DES:Data Encryption Standard,数据加密标准,对称密钥加密算法(现在认为不安全)。 https://en.wikipedia.org/wiki/Data_Encryption_Standard

DiffieHellman:Diffie–Hellman key exchange,缩写为 D-H,是一种安全协议,让通信双方在预先没有对方信息的情况下,通过不安全通信信道,创建一个密钥。这个密钥可以在后续的通信中,作为对称加密的密钥加密传递的信息。(备注,使是用协议的发明者命名)

相关链接

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

鲸落

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

我们的影子

文章 0 评论 0

素年丶

文章 0 评论 0

南笙

文章 0 评论 0

18215568913

文章 0 评论 0

qq_xk7Ean

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文