AES和RSA

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: AES和RSA

AES和RSA



AES是一种常用的对称加密算法,加解密都用同一个密钥。crypto模块提供了AES支持,但是需要自己封装好函数,便于使用:


const crypto = require('crypto');



function aesEncrypt(data, key) {


  const cipher = crypto.createCipher('aes192', key);


  var crypted = cipher.update(data, 'utf8', 'hex');


  crypted += cipher.final('hex');


  return crypted;


}



function aesDecrypt(encrypted, key) {


  const decipher = crypto.createDecipher('aes192', key);


  var decrypted = decipher.update(encrypted, 'hex', 'utf8');


  decrypted += decipher.final('utf8');


  return decrypted;


}




var data = 'Hello, this is a secret message!';


var key = 'Password!';


var encrypted = aesEncrypt(data, key);


var decrypted = aesDecrypt(encrypted, key);




console.log('Plain text: ' + data);


console.log('Encrypted text: ' + encrypted);


console.log('Decrypted text: ' + decrypted);




运行结果如下:


Plain text: Hello, this is a secret message!


Encrypted text: 8a944d97bdabc157a5b7a40cb180e7...


Decrypted text: Hello, this is a secret message!


可以看出,加密后的字符串通过解密又得到了原始内容。



注意到AES有很多不同的算法,如aes192,aes-128-ecb,aes-256-cbc等,AES除了密钥外还可以指定IV(Initial Vector),不同的系统只要IV不同,用相同的密钥加密相同的数据得到的加密结果也是不同的。加密结果通常有两种表示方法:hex和base64,这些功能Nodejs全部都支持,但是在应用中要注意,如果加解密双方一方用Nodejs,另一方用Java、PHP等其它语言,需要仔细测试。如果无法正确解密,要确认双方是否遵循同样的AES算法,字符串密钥和IV是否相同,加密后的数据是否统一为hex或base64格式。



Diffie-Hellman


DH算法是一种密钥交换协议,它可以让双方在不泄漏密钥的情况下协商出一个密钥来。DH算法基于数学原理,比如小明和小红想要协商一个密钥,可以这么做:



小明先选一个素数和一个底数,例如,素数p=23,底数g=5(底数可以任选),再选择一个秘密整数a=6,计算A=g^a mod p=8,然后大声告诉小红:p=23,g=5,A=8;



小红收到小明发来的p,g,A后,也选一个秘密整数b=15,然后计算B=g^b mod p=19,并大声告诉小明:B=19;

小明自己计算出s=B^a mod p=2,小红也自己计算出s=A^b mod p=2,因此,最终协商的密钥s为2。


在这个过程中,密钥2并不是小明告诉小红的,也不是小红告诉小明的,而是双方协商计算出来的。第三方只能知道p=23,g=5,A=8,B=19,由于不知道双方选的秘密整数a=6和b=15,因此无法计算出密钥2。



用crypto模块实现DH算法如下:



const crypto = require('crypto');




// xiaoming's keys:


var ming = crypto.createDiffieHellman(512);


var ming_keys = ming.generateKeys();




var prime = ming.getPrime();


var generator = ming.getGenerator();




console.log('Prime: ' + prime.toString('hex'));


console.log('Generator: ' + generator.toString('hex'));




// xiaohong's keys:


var hong = crypto.createDiffieHellman(prime, generator);


var hong_keys = hong.generateKeys();




// exchange and generate secret:


var ming_secret = ming.computeSecret(hong_keys);


var hong_secret = hong.computeSecret(ming_keys);




// print secret:


console.log('Secret of Xiao Ming: ' + ming_secret.toString('hex'));


console.log('Secret of Xiao Hong: ' + hong_secret.toString('hex'));


运行后,可以得到如下输出:




$ node dh.js  


Prime: a8224c...deead3


Generator: 02


Secret of Xiao Ming: 695308...d519be


Secret of Xiao Hong: 695308...d519be


注意每次输出都不一样,因为素数的选择是随机的。



RSA


RSA算法是一种非对称加密算法,即由一个私钥和一个公钥构成的密钥对,通过私钥加密,公钥解密,或者通过公钥加密,私钥解密。其中,公钥可以公开,私钥必须保密。



RSA算法是1977年由Ron Rivest、Adi Shamir和Leonard Adleman共同提出的,所以以他们三人的姓氏的头字母命名。



当小明给小红发送信息时,可以用小明自己的私钥加密,小红用小明的公钥解密,也可以用小红的公钥加密,小红用她自己的私钥解密,这就是非对称加密。相比对称加密,非对称加密只需要每个人各自持有自己的私钥,同时公开自己的公钥,不需要像AES那样由两个人共享同一个密钥。




在使用Node进行RSA加密前,我们先要准备好私钥和公钥。



首先,在命令行执行以下命令以生成一个RSA密钥对:



openssl genrsa -aes256 -out rsa-key.pem 2048


根据提示输入密码,这个密码是用来加密RSA密钥的,加密方式指定为AES256,生成的RSA的密钥长度是2048位。执行成功后,我们获得了加密的rsa-key.pem文件。



第二步,通过上面的rsa-key.pem加密文件,我们可以导出原始的私钥,命令如下:



openssl rsa -in rsa-key.pem -outform PEM -out rsa-prv.pem


输入第一步的密码,我们获得了解密后的私钥。




类似的,我们用下面的命令导出原始的公钥:



openssl rsa -in rsa-key.pem -outform PEM -pubout -out rsa-pub.pem


这样,我们就准备好了原始私钥文件rsa-prv.pem和原始公钥文件rsa-pub.pem,编码格式均为PEM。




下面,使用crypto模块提供的方法,即可实现非对称加解密。



首先,我们用私钥加密,公钥解密:



const


  fs = require('fs'),


  crypto = require('crypto');




// 从文件加载key:


function loadKey(file) {


  // key实际上就是PEM编码的字符串:


  return fs.readFileSync(file, 'utf8');


}




let


  prvKey = loadKey('./rsa-prv.pem'),


  pubKey = loadKey('./rsa-pub.pem'),


  message = 'Hello, world!';




// 使用私钥加密:


let enc_by_prv = crypto.privateEncrypt(prvKey, Buffer.from(message, 'utf8'));


console.log('encrypted by private key: ' + enc_by_prv.toString('hex'));




let dec_by_pub = crypto.publicDecrypt(pubKey, enc_by_prv);


console.log('decrypted by public key: ' + dec_by_pub.toString('utf8'));


执行后,可以得到解密后的消息,与原始消息相同。




接下来我们使用公钥加密,私钥解密:




// 使用公钥加密:


let enc_by_pub = crypto.publicEncrypt(pubKey, Buffer.from(message, 'utf8'));


console.log('encrypted by public key: ' + enc_by_pub.toString('hex'));




// 使用私钥解密:


let dec_by_prv = crypto.privateDecrypt(prvKey, enc_by_pub);


console.log('decrypted by private key: ' + dec_by_prv.toString('utf8'));


执行得到的解密后的消息仍与原始消息相同。




如果我们把message字符串的长度增加到很长,例如1M,这时,执行RSA加密会得到一个类似这样的错误:data too large for key size,这是因为RSA加密的原始信息必须小于Key的长度。那如何用RSA加密一个很长的消息呢?实际上,RSA并不适合加密大数据,而是先生成一个随机的AES密码,用AES加密原始信息,然后用RSA加密AES口令,这样,实际使用RSA时,给对方传的密文分两部分,一部分是AES加密的密文,另一部分是RSA加密的AES口令。对方用RSA先解密出AES口令,再用AES解密密文,即可获得明文。


相关文章
|
7月前
|
安全 算法 网络安全
RSA2048与RSA3072的闲言碎语
RSA2048与RSA3072的闲言碎语
327 0
如何生成RSA,RSA2密钥
密钥生成或如何使用(创建应用):[url]https://openclub.alipay.com/read.php?tid=1606&fid=72[/url] 1.密钥生成工具下载:[url]https://docs.
1695 13
|
3月前
|
存储 安全 数据安全/隐私保护
浅谈对称加密(AES与DES)
浅谈对称加密(AES与DES)
83 1
|
3月前
|
安全 算法 网络安全
浅谈非对称加密(RSA)
浅谈非对称加密(RSA)
170 0
|
4月前
|
算法 知识图谱
极简ECDSA
该文章以极简的方式介绍了ECDSA(椭圆曲线数字签名算法)的基本原理,包括私钥和公钥的生成、签名过程、以及验证签名的方法,旨在帮助读者轻松掌握ECDSA的核心概念。
56 6
极简ECDSA
|
7月前
|
安全 算法 数据库
MD5、SHA、DES、AES、RSA的算法说明
【5月更文挑战第10天】MD5、SHA、DES、AES、RSA的算法说明
389 2
|
算法 Linux 数据安全/隐私保护
RSA加密算法
RSA加密算法
261 0
RSA加密算法
|
算法 安全 Java
[转载]加密解密算法【RSA、AES、DES、MD5】介绍和使用
为了防止我们的数据泄露,我们往往会对数据进行加密,特别是敏感数据,我们要求的安全性更高。下面将介绍几种常用的加密算法使用。这些算法的加密对象都是基于二进制数据,如果要加密字符串就使用统一编码(如:utf8)进行编码后加密。
2610 0
|
数据安全/隐私保护
RSA对称加密
RSA对称加密
|
算法 安全 数据安全/隐私保护
浅谈加密算法 aes
浅谈加密算法 aes
浅谈加密算法 aes