AES和RSA

简介: 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解密密文,即可获得明文。


相关文章
|
8天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
4天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2464 14
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
4天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1505 14
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19274 29
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18822 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17515 13
Apache Paimon V0.9最新进展
|
6天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
369 11
|
1月前
|
存储 人工智能 前端开发
AI 网关零代码解决 AI 幻觉问题
本文主要介绍了 AI Agent 的背景,概念,探讨了 AI Agent 网关插件的使用方法,效果以及实现原理。
18698 16
|
3天前
|
算法 Java
JAVA并发编程系列(8)CountDownLatch核心原理
面试中的编程题目“模拟拼团”,我们通过使用CountDownLatch来实现多线程条件下的拼团逻辑。此外,深入解析了CountDownLatch的核心原理及其内部实现机制,特别是`await()`方法的具体工作流程。通过详细分析源码与内部结构,帮助读者更好地理解并发编程的关键概念。
|
3天前
|
SQL 监控 druid
Druid连接池学习
Druid学习笔记,使用Druid进行密码加密。参考文档:https://github.com/alibaba/druid
196 82