-
2020-08-29 11:45:37
- RSA(RSA algorithm):由RSA公司发明,是一个支持变长密钥的公开密钥算法,需要加密的文件块的长度也是可变的,非对称加密算法。
- DSA(Digital Signature Algorithm):数字签名算法,是一种标准的DSS(数字签名标准),严格来说不算加密算法;算法标准,速度快,安全级别高,在21世纪AES标准的一个实现是Rijndael算法。
- ECC(Elliptic Curves Cryptography):椭圆曲线密码编码学,也属于公开密钥算法。
更多相关内容 -
visual c++ vc实现RSA加密算法是最常用的非对称加密算法.zip
2021-01-29 11:52:51visual c++ vc实现RSA加密算法是最常用的非对称加密算法.zip -
常见加密算法方式(对称加密和非对称加密)
2018-03-26 16:29:29对称加密:DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES 非对称加密:RSA、ECC(移动设备用)、Diffie-Hellman、El Gamal、DSA(数字签名用) -
对称加密与非对称加密算法
2022-01-24 16:25:55目录 1、对称加密 1.1、加密类型 1.1.1、流加密 ...2.1、非对称加密算法 2.1.1、RSA 2.1.2、ECC 2.1.3、SM2 3、对称加密与非对称加密技术比较 4、实践 4.1、对称加密工具 4.1.1、AES加解密目录
1、对称加密
加密和解密使用同一个密钥。
1.1、加密类型
对称加密算法有两种加密类型:流加密和块加密。1.1.1、流加密
流加密:流加密法是一次加密明文中的一位,解密也是一位一位去解密。
1.1.2、块加密
块加密(也称为分组加密):块加密法是一次加密明文中的一块,解密也是一块一块去解密。
假设加密的明文是WELCOMETOCHINA,先加密WELCOME,再加密TO,再加密CHINA,即一次加密明文中的一个块。
算法模式是块加密法中一系列基本算法步骤的组合。块加密法常用的加密模式:电子编码簿模式(ECB),加密块链接模式(CBC),加密反馈模式(CFB),输出反馈模式(OFB),计数器模式(CTR)。
电子编码簿模式(ECB)
电子编码簿模式是最简单的操作模式,将输入明文消息分为64位块,然后单独加密每个块,消息中所有块使用相同密钥加密。
加密步骤如下:
从加密步骤我们可以看出,ECB模式中用同一个密钥加密消息的所有块,如果原消息中重复明文块,则加密消息中的相应密文块也会重复。如果输入中一个明文块多次出现,则输出中相应的密文块也会多次出现,从而让攻击者找到漏洞进行破解。
加密块链接模式(CBC)
为了解决ECB模式中相同明文产生相同密文的问题,出现了CBC加密模式。CBC加密模式保证了即使输入中明文块相同,也能得到不同的密文块。CBC加密模式使用了反馈机制。
加密步骤如下:
第一步接收两个输入:明文块1和一个随机文本块IV(Initialization Vector),称为初始化向量。
初始向量没有什么特别意义,只是使每个消息唯一。初始化向量是随机生成的,可以保证明文块1即使相同也能产生不同密文块1(随机生成的初始化向量相同的概率是很小的)。
加密时第一步使用IV和明文1作异或运算,加密后得到密文1,第二步用密文1和明文2作异或运算,加密后得到密文2,后面依此类推。
初始化向量只在第一个明文块中使用,但所有明文块加密依旧使用相同密钥。
加密反馈模式(CFB)
不是所有应用程序都能处理数据块,面向字符的应用程序也需要安全性。这时要使用流加密法,可以使用加密反馈模式。
加密反馈模式中,数据用更小的单元加密(可以是8位,即一个字符的长度),这个长度小于定义的块长(通常是64位)。假设我们一次处理j位(j通常取8)。
第一步:
与CBC模式一样,加密反馈模式也使用64位的初始化向量。初始化向量放在移位寄存器中,第一步产生相应的64位初始化向量密文
第二步:
加密初始化向量最左边的j位与明文前j位进行异或运算,产生密文第一部分密文C。
第三步:
初始化向量的位左移j位,使移位寄存器最右边的j位为不可预测的数据,在其中填入C的内容。
第四步:
重复1~3步,直到加密所有明文单元
总体加密过程如下
输出反馈模式(OFB)
输出反馈模式与CFB很相似,唯一差别是,CFB中密文填入加密过程下一阶段,而在OFB中,IV加密过程的输入填入加密过程下一阶段。
计数器模式(CTR)
计数器模式与OFB模式非常类似。它使用序号(称为计数器)作为算法的输入。每个块加密后,要填充到寄存器中,使用下一个寄存器值。通常使用一个常数作为初始计数器的值,并且每次迭代后递增(通常是增加1)。计数器块的大虚哎等于明文块的大小。
加密时,计数器加密后与明文块作XOR运算,得到密文。
1.2、对称加密算法
1.2.1、DES
全称为Data Encryption Standard,即数据加密标准。
DES是一种块加密算法,按64位块长加密数据,即把64位明文作为DES的输入,产生64位密文输出。
DES工作原理
DES使用56位密钥。实际上,最初的密钥为64位,但在DES过程开始之前放弃密钥的每个第八位,从而得到56位密钥,即放弃第8、16、24、32、40、48、56、64位。
1.2.2、3DES
即三重DES,就是三次执行DES,分为两个大类
三个密钥的三重DES
首先用密钥K1加密明文块P,然后用密钥K2加密,最后用密钥K3加密,其中K1,K2,K3各不相同
两个密钥的三重DES
1.2.4、AES
全称为Advanced Encryption Standard,即高级加密标准,这个标准用来替代原先的DES。1998年6月,Rijndael算法提交给美国国家标准与技术协会(NIST),作为AES的候选算法之一。最初有15种候选算法。2000年10月,NIST宣布AES最终选择Rijndael。
Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256位为上限。AES只选择了区块长度固定为128位,密钥长度为128,192或256位。
2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。
1.2.5、SM1
SM1 为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。1.2.6、SM4
SM4由我国国家密码管理局在2012年发布,常用于无线互联网加密等领域。与DES和AES算法类似,SM4算法也是一种分组加密算法。其分组长度为128位,密钥长度也为128位。1.2.7、RC2
RC2是一种块加密算法。输入和输出块大小都是64位。而密钥是可变的,从1字节到128字节。1.2.8、RC4
RC4是一种流加密算法。1.2.9、RC5
RC5是一种块加密算法。块长、轮数、密钥长度都是可变的。块长可取16,32和64位。密钥长度为0~2040位。RC5算法的特定实例记作R5-w/r/b,其中w为分组长度,r为轮数,b为密钥长度。
RC5-32/16/16 表示RC5的块长为64位(RC5一次加密2字节),16轮和16字节(128位)密钥。
说明
上面介绍的几种对称加密算法,只有RC4是流加密,其他都是分组加密。上面这些只是对对称加密算法进行了一个简单介绍,没有介绍这些算法的加密步骤,如果你对这些加密算法的步骤感兴趣,推荐两本书籍,可以自行去查阅:
《密码编码学与网络安全》 -[美] William Stallings 著 电子工业出版社
《密码学与网络安全》-Atul Kahate著 清华大学出版社
后面如果有时间和精力,我会单独写文章介绍这些加密算法的加密步骤。
2、非对称加密
非对称加密又称为公钥加密,使用一对密钥,一把为私钥,是保密的,一把为公钥,可以对外公布。使用公钥对明文进行加密,使用私钥对密文进行解密。公钥密码学的发展是整个密码学发展历史中最伟大的一次革命。在公钥加密算法发明之前,加密算法都是基于替换和置换这些初等方法之上。而公钥密码学算法则是基于数学函数。
2.1、非对称加密算法
2.1.1、RSA
RSA是被研究得最广泛的公钥算法,从提出到现在,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥方案之一。RSA公开密钥密码体制的原理是:根据数论,寻求两个大素数比较简单,而将它们的乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。
RSA算法生成密钥对以及加解密过程:
(1) 选择两个大素数P,Q
设P = 7,Q = 17
(2) 计算N = P x Q
N = 7 x 17 = 119
(3) 选择一个公钥E,使其不是(P - 1)与(Q - 1)的因子
(P - 1) = 6 = 2 x 3
(Q - 1) = 16 = 2 x 2 x 2 x 2
因此我们选的公钥E不能有因子2和3。我们取E = 5
(4) 选择私钥D,满足:(D x E) mod (P - 1) x (Q - 1) = 1
(D x 5) mod 6 x 16 = 1
(D x 5) mod 96 = 1
经计算,取D = 77
(5) 加密时,从明文PT计算密文CT:CT = mod N
假设明文为10
CT = mod 119 = 40
(6) 将密文CT发送给接收方
将40发送给接收方
(7) 解密时,从密文CT得到明文PT:PT = mod N
PT = mod 119 = 10
从上述例子可以看出,RSA算法本身很简单,关键是选择正确的密钥。
假设B要接收A的加密消息,首先生成公钥E和私钥D,私钥D自己保留,公钥E和数字N发布出去,攻击者拿到公钥E和数字N,似乎可以通过试错法计算出私钥D。这里就到了问题的关键,从上述例子可以看出,攻击者只要从N中分解出P和Q,就可以破解私钥。我们上述例子中选择的N很小,实际N是很大的,而大素数分解是极其困难的。
2.1.2、ECC
大多数使用公钥密码学进行加密和数字签名的产品和标准都使用RSA算法。我们知道,为了保证RSA使用的安全性,最近这些年来密钥的位数一直在增加,这对使用RSA的应用是很重的负担,对进行大量安全交易的电子商务更是如此(从上面RSA加解密的例子可以推测,当要使用1024位密钥时,计算量是很大的)。与RSA相比,ECC可以使用比RSA短得多得密钥得到相同得安全性,因此可以减少处理负荷。另一方面,虽然关于ECC的理论已经很成熟,但ECC的可信度还没有RSA高。
ECC全称为elliptic curve cryptography,即椭圆曲线密码学算法。安全性建立在以下数学困难问题基础之上:
椭圆曲线上的离散对数问题:
已知有限域Fp 椭圆曲线点群Ep (a,b) 及其生成元点P∈Ep (a,b),P的阶是一个大素数。已知整数
k∈Fp 和点P,求点Q=kP是容易的,但已知点P和Q求整数k则是困难的。
椭圆曲线上的两个点P和Q,k为整数,Q = kP,椭圆曲线加密的数学原理:点P称为基点,k为私钥,Q为公钥。
给定k和P,计算Q很容易。但给定P和Q,求k非常困难。
椭圆曲线方程:y =
+ a
+ b
加解密过程:
(1) 用户选定一条椭圆曲线Ep(a, b), 并取椭圆曲线上一点作为基点P
(2) 用户A选择大数k作为私钥,并生成公钥Q = kP
(3) 用户A将Ep(a, b),公钥Q和基点P传给B用户
(4) 用户B接受到信息后,将待传输的明文编码到Ep(a,b)上的一点M,并产生一个随机整数r。
(5) 用户B计算点C1 = M + rQ,C2 = rP
(6) 用户B将C1和C2传给A
(7) 用户A接收到信息后,计算C1 - kC2,就可以得到点M(C1 - kC2 = M + rQ - krP = M + r(Q - kP) = M)。
(8) 再对M进行解码就可以得到明文。
假设在加密过程中,有一个第三者H,H只能知道椭圆曲线 Ep(a,b)、公钥Q、基点P、密文点C(C1, C2),而通过公钥Q、基点P求私钥k或者通过密文点C(C1, C2)、基点P求随机数r都是非常困难的,因此得以保证数据传输的安全。
密码学中,描述一条Fp上的椭圆曲线,常用到六个参量:T=(p,a,b,n,x,y)。(p 、a 、b) 用来确定一条椭圆曲线,p为素数域内点的个数,a和b是其内的两个大数;x,y为G基点的坐标,也是两个大数;n为点G基点的阶;以上六个量就可以描述一条椭圆曲线。
2.1.3、SM2
SM2算法是我国自主知识产权的商业密码算法,是ECC的一种。ECC是基于椭圆曲线方程 y =
+ a
+ b,SM通过指定系数a,b确定了唯一的一条曲线。简单理解就是ECC选取的椭圆曲线可以有无数个,而SM2只是选取了唯一的一条椭圆曲线。
SM2椭圆曲线公钥密码算法推荐曲线参数
推荐使用素数域256位椭圆曲线。
椭圆曲线方程:y =
+ a
+ b
曲线参数:
p=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFF
a=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF 00000000 FFFFFFFF FFFFFFFC
b=28E9FA9E 9D9F5E34 4D5A9E4B CF6509A7 F39789F5 15AB8F92 DDBCBD41 4D940E93
n=FFFFFFFE FFFFFFFF FFFFFFFF FFFFFFFF 7203DF6B 21C6052B 53BBF409 39D54123
Gx=32C4AE2C 1F198119 5F990446 6A39C994 8FE30BBF F2660BE1 715A4589 334C74C7
Gy=BC3736A2 F4F6779C 59BDCEE3 6B692153 D0A9877C C62A4740 02DF32E5 2139F0A0
国家密码管理局已经发布了《SM2椭圆曲线公钥密码算法》公告,对SM2算法有非常详细的说明,感兴趣的读者可以自行去查阅。
国家密码管理局关于发布《SM2椭圆曲线公钥密码算法》公告(国密局公告第21号)_国家密码管理局 (oscca.gov.cn)https://oscca.gov.cn/sca/xxgk/2010-12/17/content_1002386.shtml
3、对称加密与非对称加密技术比较
对称加密优点:加密速度快
缺点:密钥管理分配困难,安全性较低
非对称加密
优点:安全性较高
缺点:加密速度慢
对称加密技术加密和解密使用的都是同一个密钥,因此密钥的管理非常困难,在分发密钥的过程中,如果密钥被截获,那后面的通信就是不安全的。而非对称加密技术就很好的解决了这一问题,非对称加密技术使用公钥加密,私钥加密。通信前把公钥发布出去,私钥只有自己保留,即便你的公钥被攻击者拿到,没有私钥,就无法进行解密。
那有了非对称加密技术,对称加密是不是就被淘汰了?当然不是,因为非对称加密技术加解密比较慢,不适合对大量数据的加解密。
实际中对称加密和非对称加密是结合使用的。一般我们用对称密钥对明文进行加密,然后用非对称算法的公钥对对称密钥进行加密(加密后的东西称为数字信封),然后将数字信封和密文一起发送出去,接收者收到信息后,先用非对称算法的私钥对数字信封进行解密,得到对称密钥,再用对称密钥解密密文,就拿到了原文信息。
这就是数字信封的原理,具体原理参考我写的另一篇文章《浅谈数字信封》。
4、实践
接下来我们就实际操作一下,先介绍一下开源库openssl。
OpenSSL 是一个开源且功能强大的包含丰富的密码算法和 SSL/TLS 协议的库,主要包括的密码算法、常用的密钥和证书封装管理功能及 SSL 协议,并提供了多用途的命令行工具。使用 c 语言编写,跨平台性能好,支持 Linux、Windows、BDS、Mac、VMS 等平台。
Openssl由3部分组成
- The Crypto library(密码学算法库)
- The SSL library(SSL/TLS协议库)
- Command line tool(命令行工具)
ubuntu下安装命令:
sudo apt-get install openssl
sudo apt-get install libssl-dev
安装后就可以直接使用openssl命令行工具。
4.1、对称加密工具enc是openssl提供的一个对称加解密命令行工具。安装openssl后,执行命令openssl enc -list,可以看到enc支持的所有对称加密算法
lng@ubuntu:~$ openssl enc -list Supported ciphers: -aes-128-cbc -aes-128-cfb -aes-128-cfb1 -aes-128-cfb8 -aes-128-ctr -aes-128-ecb -aes-128-ofb -aes-192-cbc -aes-192-cfb -aes-192-cfb1 -aes-192-cfb8 -aes-192-ctr -aes-192-ecb -aes-192-ofb -aes-256-cbc -aes-256-cfb -aes-256-cfb1 -aes-256-cfb8 -aes-256-ctr -aes-256-ecb -aes-256-ofb -aes128 -aes128-wrap -aes192 -aes192-wrap -aes256 -aes256-wrap -aria-128-cbc -aria-128-cfb -aria-128-cfb1 -aria-128-cfb8 -aria-128-ctr -aria-128-ecb -aria-128-ofb -aria-192-cbc -aria-192-cfb -aria-192-cfb1 -aria-192-cfb8 -aria-192-ctr -aria-192-ecb -aria-192-ofb -aria-256-cbc -aria-256-cfb -aria-256-cfb1 -aria-256-cfb8 -aria-256-ctr -aria-256-ecb -aria-256-ofb -aria128 -aria192 -aria256 -bf -bf-cbc -bf-cfb -bf-ecb -bf-ofb -blowfish -camellia-128-cbc -camellia-128-cfb -camellia-128-cfb1 -camellia-128-cfb8 -camellia-128-ctr -camellia-128-ecb -camellia-128-ofb -camellia-192-cbc -camellia-192-cfb -camellia-192-cfb1 -camellia-192-cfb8 -camellia-192-ctr -camellia-192-ecb -camellia-192-ofb -camellia-256-cbc -camellia-256-cfb -camellia-256-cfb1 -camellia-256-cfb8 -camellia-256-ctr -camellia-256-ecb -camellia-256-ofb -camellia128 -camellia192 -camellia256 -cast -cast-cbc -cast5-cbc -cast5-cfb -cast5-ecb -cast5-ofb -chacha20 -des -des-cbc -des-cfb -des-cfb1 -des-cfb8 -des-ecb -des-ede -des-ede-cbc -des-ede-cfb -des-ede-ecb -des-ede-ofb -des-ede3 -des-ede3-cbc -des-ede3-cfb -des-ede3-cfb1 -des-ede3-cfb8 -des-ede3-ecb -des-ede3-ofb -des-ofb -des3 -des3-wrap -desx -desx-cbc -id-aes128-wrap -id-aes128-wrap-pad -id-aes192-wrap -id-aes192-wrap-pad -id-aes256-wrap -id-aes256-wrap-pad -id-smime-alg-CMS3DESwrap -rc2 -rc2-128 -rc2-40 -rc2-40-cbc -rc2-64 -rc2-64-cbc -rc2-cbc -rc2-cfb -rc2-ecb -rc2-ofb -rc4 -rc4-40 -seed -seed-cbc -seed-cfb -seed-ecb -seed-ofb -sm4 -sm4-cbc -sm4-cfb -sm4-ctr -sm4-ecb -sm4-ofb
enc完整命令
openssl enc -ciphername [-in filename] [-out filename] [-pass arg] [-e ] [-d ] [-a ] [-A] [-k password ] [-kfile filename] [-K key] [-iv IV] [-p] [-P] [-bufsize number] [-nopad] [-debug]
-ciphername:对称算法名称(就是上面执行openssl enc -list命令后展示的那些)
-in filename:输入文件,默认为标准输入。
-out filename:输出文件,默认为标准输出。
-pass arg:输入文件如果有密码保护,指定密码来源。
-e:进行加密操作,默认操作。
-d:进行解密操作。
-a:当进行加解密时,它只对数据进行运算,有时需要进行base64转换。设置此选项后,加密结果进行base64编码;解密前先进行base64解码。
-A:默认情况下,base64编码结果在文件中是多行的。如果要将生成的结果在文件中只有一行,需设置此选项;解密时,必须采用同样的设置,否则读取数据时会出错。
-k password:指定加密口令,不设置此项时,程序会提示用户输入口令。
-kfile filename:指定口令存放的文件。
-K key:密钥,为16进制。
-iv IV:初始化向量,为16进制。
-p:打印出使用的salt、口令以及初始化向量IV。
-P:打印使用的salt、口令以及IV,不做加密和解密操作。
-bufsize number:设置I/O操作的缓冲区大小,因为一个文件可能很大,每次读取的数据是有限的。
-debug:打印调试信息。
4.1.1、AES加解密
加密命令
openssl enc -aes-128-cbc -in in.txt -out out.txt -a -K 001122334455BBCCDDEEFF0011223344 -iv 0123456789ABCDEF0123456789ABCDEF
我们选择的密钥长度为128位,从上面列表可以知道,密钥长度可以选取128位,192位,256位。选择的加密模式为cbc,加密模式可以选取ecb,cbc,cfb,ofb,ctr。加密模式是什么意思在上面已经将的很清楚了。
演示
lng@ubuntu:~/CSDN/enc$ cat in.txt hello word lng@ubuntu:~/CSDN/enc$ openssl enc -aes-128-cbc -in in.txt -out out.txt -a -K 001122334455BBCCDDEEFF0011223344 -iv 0123456789ABCDEF0123456789ABCDEF lng@ubuntu:~/CSDN/enc$ ls in.txt out.txt lng@ubuntu:~/CSDN/enc$ cat out.txt Bqbu9rk0uOXRgahyZWW7tA== lng@ubuntu:~/CSDN/enc$
解密命令
openssl enc -aes-128-cbc -in out.txt -out inin.txt -d -a -K 001122334455BBCCDDEEFF0011223344 -iv 0123456789ABCDEF0123456789ABCDEF
演示
lng@ubuntu:~/CSDN/enc$ openssl enc -aes-128-cbc -in out.txt -out inin.txt -d -a -K 001122334455BBCCDDEEFF0011223344 -iv 0123456789ABCDEF0123456789ABCDEF lng@ubuntu:~/CSDN/enc$ ls inin.txt in.txt out.txt lng@ubuntu:~/CSDN/enc$ cat inin.txt hello word lng@ubuntu:~/CSDN/enc$
注意:如果你要阅读密文,要指定参数-a进行base64编码,否则密文是二进制文件,解密时也要指定-a参数,先进行base64解码,再进行解密。
默认是加密操作,加密时可以不指定参数,但解密时我们要指定参数-d
ecb模式是没有初始化向量的,所以ecb模式我们不用指定-iv参数
你可以选择不同的密钥长度和不同的加密模式,看看密文有什么不同。我这里就不演示了
4.1.2、DES加解密
des密钥长度是固定的,为64位,所以我们只需要选择加密模式。
lng@ubuntu:~/CSDN/enc$ cat in.txt hello word lng@ubuntu:~/CSDN/enc$ openssl enc -des-ecb -K 0123456789AAAAAA -in in.txt -out out.txt -a lng@ubuntu:~/CSDN/enc$ ls in.txt out.txt lng@ubuntu:~/CSDN/enc$ cat out.txt munBF17bqEeZ28tiddZVxg== lng@ubuntu:~/CSDN/enc$ openssl enc -des-ecb -d -K 0123456789AAAAAA -in out.txt -out inin.txt -a lng@ubuntu:~/CSDN/enc$ ls inin.txt in.txt out.txt lng@ubuntu:~/CSDN/enc$ cat inin.txt hello word lng@ubuntu:~/CSDN/enc$
4.2、非对称加密工具
4.2.1、RSA加密
这里介绍下openssl命令行工具的两个命令
genrsa 生成rsa密钥
rsa 用于处理rsa密钥,格式转换和打印信息
生成私钥
# private.key 为私钥文件,其中包含公钥和私钥,1024为密钥长度 openssl genrsa -out private.key 1024
导出公钥
# 从私钥文件中导出公钥 openssl rsa -in private.key -pubout -out public.key
使用公钥加密
openssl rsautl -encrypt -pubin -inkey public.key -in in.txt -out out.txt
使用私钥解密
openssl rsautl -decrypt -inkey private.key -in out.txt -out inin.txt
4.2.2、ECC加密
ecparam 椭圆曲线密钥参数生成及操作
ec 椭圆曲线密钥处理工具
查看支持的椭圆曲线
openssl ecparam -list_curves
可以看到支持的所有椭圆曲线,最前面的就是曲线名称。
secp112r1 : SECG/WTLS curve over a 112 bit prime field secp112r2 : SECG curve over a 112 bit prime field secp128r1 : SECG curve over a 128 bit prime field secp128r2 : SECG curve over a 128 bit prime field secp160k1 : SECG curve over a 160 bit prime field secp160r1 : SECG curve over a 160 bit prime field secp160r2 : SECG/WTLS curve over a 160 bit prime field secp192k1 : SECG curve over a 192 bit prime field secp224k1 : SECG curve over a 224 bit prime field secp224r1 : NIST/SECG curve over a 224 bit prime field secp256k1 : SECG curve over a 256 bit prime field secp384r1 : NIST/SECG curve over a 384 bit prime field secp521r1 : NIST/SECG curve over a 521 bit prime field prime192v1: NIST/X9.62/SECG curve over a 192 bit prime field prime192v2: X9.62 curve over a 192 bit prime field prime192v3: X9.62 curve over a 192 bit prime field prime239v1: X9.62 curve over a 239 bit prime field prime239v2: X9.62 curve over a 239 bit prime field prime239v3: X9.62 curve over a 239 bit prime field prime256v1: X9.62/SECG curve over a 256 bit prime field sect113r1 : SECG curve over a 113 bit binary field sect113r2 : SECG curve over a 113 bit binary field sect131r1 : SECG/WTLS curve over a 131 bit binary field sect131r2 : SECG curve over a 131 bit binary field sect163k1 : NIST/SECG/WTLS curve over a 163 bit binary field sect163r1 : SECG curve over a 163 bit binary field sect163r2 : NIST/SECG curve over a 163 bit binary field sect193r1 : SECG curve over a 193 bit binary field sect193r2 : SECG curve over a 193 bit binary field sect233k1 : NIST/SECG/WTLS curve over a 233 bit binary field sect233r1 : NIST/SECG/WTLS curve over a 233 bit binary field sect239k1 : SECG curve over a 239 bit binary field sect283k1 : NIST/SECG curve over a 283 bit binary field sect283r1 : NIST/SECG curve over a 283 bit binary field sect409k1 : NIST/SECG curve over a 409 bit binary field sect409r1 : NIST/SECG curve over a 409 bit binary field sect571k1 : NIST/SECG curve over a 571 bit binary field sect571r1 : NIST/SECG curve over a 571 bit binary field c2pnb163v1: X9.62 curve over a 163 bit binary field c2pnb163v2: X9.62 curve over a 163 bit binary field c2pnb163v3: X9.62 curve over a 163 bit binary field c2pnb176v1: X9.62 curve over a 176 bit binary field c2tnb191v1: X9.62 curve over a 191 bit binary field c2tnb191v2: X9.62 curve over a 191 bit binary field c2tnb191v3: X9.62 curve over a 191 bit binary field c2pnb208w1: X9.62 curve over a 208 bit binary field c2tnb239v1: X9.62 curve over a 239 bit binary field c2tnb239v2: X9.62 curve over a 239 bit binary field c2tnb239v3: X9.62 curve over a 239 bit binary field c2pnb272w1: X9.62 curve over a 272 bit binary field c2pnb304w1: X9.62 curve over a 304 bit binary field c2tnb359v1: X9.62 curve over a 359 bit binary field c2pnb368w1: X9.62 curve over a 368 bit binary field c2tnb431r1: X9.62 curve over a 431 bit binary field wap-wsg-idm-ecid-wtls1: WTLS curve over a 113 bit binary field wap-wsg-idm-ecid-wtls3: NIST/SECG/WTLS curve over a 163 bit binary field wap-wsg-idm-ecid-wtls4: SECG curve over a 113 bit binary field wap-wsg-idm-ecid-wtls5: X9.62 curve over a 163 bit binary field wap-wsg-idm-ecid-wtls6: SECG/WTLS curve over a 112 bit prime field wap-wsg-idm-ecid-wtls7: SECG/WTLS curve over a 160 bit prime field wap-wsg-idm-ecid-wtls8: WTLS curve over a 112 bit prime field wap-wsg-idm-ecid-wtls9: WTLS curve over a 160 bit prime field wap-wsg-idm-ecid-wtls10: NIST/SECG/WTLS curve over a 233 bit binary field wap-wsg-idm-ecid-wtls11: NIST/SECG/WTLS curve over a 233 bit binary field wap-wsg-idm-ecid-wtls12: WTLS curve over a 224 bit prime field Oakley-EC2N-3: IPSec/IKE/Oakley curve #3 over a 155 bit binary field. Not suitable for ECDSA. Questionable extension field! Oakley-EC2N-4: IPSec/IKE/Oakley curve #4 over a 185 bit binary field. Not suitable for ECDSA. Questionable extension field! brainpoolP160r1: RFC 5639 curve over a 160 bit prime field brainpoolP160t1: RFC 5639 curve over a 160 bit prime field brainpoolP192r1: RFC 5639 curve over a 192 bit prime field brainpoolP192t1: RFC 5639 curve over a 192 bit prime field brainpoolP224r1: RFC 5639 curve over a 224 bit prime field brainpoolP224t1: RFC 5639 curve over a 224 bit prime field brainpoolP256r1: RFC 5639 curve over a 256 bit prime field brainpoolP256t1: RFC 5639 curve over a 256 bit prime field brainpoolP320r1: RFC 5639 curve over a 320 bit prime field brainpoolP320t1: RFC 5639 curve over a 320 bit prime field brainpoolP384r1: RFC 5639 curve over a 384 bit prime field brainpoolP384t1: RFC 5639 curve over a 384 bit prime field brainpoolP512r1: RFC 5639 curve over a 512 bit prime field brainpoolP512t1: RFC 5639 curve over a 512 bit prime field SM2 : SM2 curve over a 256 bit prime field
生成参数文件
选择一条曲线生成参数文件
openssl ecparam -name secp256k1 -out secp256k1.pem
显示参数文件参数
openssl ecparam -in secp256k1.pem -text -param_enc explicit -noout
使用参数文件生成私钥
openssl ecparam -in secp256k1.pem -genkey -out secp256k1-key.key
从私钥中导出公钥
openssl ec -in secp256k1-key.key -pubout -out public.key
参考资料
《密码编码学与网络安全》 -[美] William Stallings 著 电子工业出版社
《密码学与网络安全》-Atul Kahate著 清华大学出版社
-
常用的几种非对称加密算法
2019-10-26 17:22:09相对对称加密而言,无需拥有同一组密钥,非对称加密是一种“信息公开的密钥交换协议”。非对称加密需要公开密钥和私有密钥两组密钥,公开密钥和私有密钥是配对起来的,也就是说使用公开密钥进行数据加密,只有对应的...
相对对称加密而言,无需拥有同一组密钥,非对称加密是一种“信息公开的密钥交换协议”。非对称加密需要公开密钥和私有密钥两组密钥,公开密钥和私有密钥是配对起来的,也就是说使用公开密钥进行数据加密,只有对应的私有密钥才能解密。这两个密钥是数学相关,用某用户密钥加密后的密文,只能使用该用户的加密密钥才能解密。如果知道了其中一个,并不能计算出另外一个。因此如果公开了一对密钥中的一个,并不会危害到另外一个密钥性质。这里把公开的密钥为公钥,不公开的密钥为私钥。算法代表:RSA,DSA。RSA 能同时用于加密和数字签名,而DSA只能用于签名,本文重点讲解RSA。
1、RSA(算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman)
这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。算法的名字以发明者的名字命名:Ron Rivest, AdiShamir 和Leonard Adleman。
这种加密算法的特点主要是密钥的变化,上文我们看到DES只有一个密钥。相当于只有一把钥匙,如果这把钥匙丢了,数据也就不安全了。RSA同时有两把钥匙,公钥与私钥。同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。
RSA 加密工具类:
package com.blog.www.util.coder.asymmetrical; import com.blog.www.util.coder.base.BaseCoderUtils; import lombok.extern.slf4j.Slf4j; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.cert.CertificateException; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; /** * RSA非对称加密解密工具类 * * <p> * 这种算法1978年就出现了,它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作,也很流行。 算法的名字以发明者的名字命名:Ron * Rivest, AdiShamir 和Leonard Adleman。 这种加密算法的特点主要是密钥的变化,RSA同时有两把钥匙,公钥与私钥。 * 同时支持数字签名。数字签名的意义在于,对传输过来的数据进行校验。确保数据在传输工程中不被修改。 * <p> * 参考: * <br/> * <ul> * <li><a href='https://www.iteye.com/blog/snowolf-381767'>Java加密技术(四)——非对称加密算法RSA</a></li> * <li><a href='https://my.oschina.net/jiangli0502/blog/171263'>RSA加密解密及数字签名Java实现</a></li> * </ul> * <p> * <a href="https://github.com/wwwtyro/cryptico">前端demo<a> <br> * <br> */ @Slf4j public class RSACoder { /** * 填充方式。这里有【RSA/ECB/PKCS1Padding】填充(默认)和【RSA/ECB/NoPadding】填充两种可选。 * <p> * 注意:使用填充时,公钥每次加密的字符串都会不一样,这样更安全;不使用则每次都一样。因为java默认是填充的,而安卓默认不填充, * 所以安卓默认加密的密文,java默认不能解密!!必须手动指定他们用一致的填充方式,才能正确加密解密。 */ private static final String CIPHER_MODE = "RSA/ECB/PKCS1Padding"; /** * 算法类型 */ private static final String ALGORITHM = "RSA"; /** * RSA密钥长度必须是64的倍数,在512~65536之间。默认是1024 */ private static final int KEY_SIZE = 1024; /** * 由公钥字节数组用Base64编码成的字符串,方便传播、储存 */ private static final String PUB_KEY_BASE64 = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxKRX+P64kA0qrd3JYYZIZ5jam63DsAlx5PKlfC0hOAhJ3wfD2Bjl3CHKNMtEKwcnZlunvikOt7/7uKdVdxDYzwpU2ivwNXDA5kMPsx8prjwS7FsdCMWnOTGWBTCYeReFHWVmSj4KxYaOO7csPWBR0AhQX9qiPSWDEKcnH5YNiiQIDAQAB"; /** * 由私钥字节数组用Base64编码成的字符串,方便传播、储存 */ private static final String PRI_KEY_BASE64 = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALEpFf4/riQDSqt3clhhkhnmNqbrcOwCXHk8qV8LSE4CEnfB8PYGOXcIco0y0QrBydmW6e+KQ63v/u4p1V3ENjPClTaK/A1cMDmQw+zHymuPBLsWx0Ixac5MZYFMJh5F4UdZWZKPgrFho47tyw9YFHQCFBf2qI9JYMQpycflg2KJAgMBAAECgYBltrwc1HzrykQFvDeXTLWwTv+TyFt19UkYhl6L5hNmTkRCI8RvzFUT5XK3ZLSmY2q7lazMTerbo44POU96XVvsV+ltmUW4ohh1cf+q7ICz73r+OEaFdxa+wHFthXvMuKpFbDiH89HfAmGGUVezf7dByClyVxn3yuKlb42ZC6AdsQJBAOyA+mBot7a98txTrMl4jRD1MI9t0dWHA51JzJ2vLBX4IlEr944Qhb6N0lNtYChEkEOCrTlLIDxWUtQhZbTP6R0CQQC/w8PcHulcbCY1JhBTefyzA4jmm9LZ0c+byqCSEiffE6/neTMLOxUpt9zDvtdWw7UvMZWgQ4a8QGZrlCw3Lw9dAkEAg9cqvE/kChU9q6FhszZmvUtR9MLttLD9TNN1I3ohg2W+C64M5L9FL4Lz+toAPrJqEZhpZIUCxWAB8ItlnTRB6QJBAKUMwsv3kxUoRG5kV5LxoK0XMsKBhaZSrmTBrxhqJgUbtb/+Eg/th1aD2LBl1oPoKE75V3Y8CICI0V5whunsSEUCQE1ZvMp5a0yblGENWU5F+kWT3aBCkmMN8Zqp2+R5p8kQ7Chxv7llCZ405YXnTdEQyLp+q6OW+eu0TdIQ3qHkA4c="; /** * 公钥对象 */ static PublicKey PUB_KEY; /** * 私钥对象 */ static PrivateKey PRI_KEY; // 初始化 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // 静态代码块,初始化密钥对象,供后面使用 static { try { PUB_KEY = restorePubKey(); PRI_KEY = restorePriKey(); } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { log.error("初始化出错", e); } } /** * 从 .p12 文件中读取私钥。 <br> * <br> * 创建人: leigq <br> * 创建时间: 2017年10月28日 下午4:21:56 <br> * * @param pfxKeyFileName .p12文件路径 * @param aliasName 私钥别名 * @param pfxPassword 私钥密码 * @return 私钥对象 */ public static PrivateKey readP12Key(String pfxKeyFileName, String aliasName, String pfxPassword) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException { InputStream fis = new FileInputStream(pfxKeyFileName); KeyStore keyStore = KeyStore.getInstance("PKCS12"); keyStore.load(fis, pfxPassword.toCharArray()); return (PrivateKey) keyStore.getKey(aliasName, pfxPassword.toCharArray()); } // 加密、解密 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ /** * 通用加密操作 * <p> * 创建人:leigq <br> * 创建时间:2018年8月18日 下午5:37:32 <br> * <p> * 修改人: <br> * 修改时间: <br> * 修改备注: <br> * </p> * * @param key 公钥或密钥对象 * @param data 明文字符串 * @return 密文字节数组用Base64算法编码成的字符串,方便传输、储存 */ public static String encrypt(Key key, String data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance(CIPHER_MODE); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] bytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8)); return BaseCoderUtils.encryptBase64(bytes); } /** * 通用解密操作 * <p> * 创建人:leigq <br> * 创建时间:2018年8月18日 下午5:43:34 <br> * <p> * 修改人: <br> * 修改时间: <br> * 修改备注: <br> * </p> * * @param key 公钥或密钥对象 * @param data 密文字符串(由密文字节数组用Base64算法编码成的字符串) * @return 明文字符串 */ public static String decrypt(Key key, String data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { Cipher cipher = Cipher.getInstance(CIPHER_MODE); cipher.init(Cipher.DECRYPT_MODE, key); byte[] bytes = cipher.doFinal(BaseCoderUtils.decryptBase64(data)); return new String(bytes, StandardCharsets.UTF_8); } /** * 用公钥加密 <br> * <br> * 创建人: leigq <br> * 创建时间: 2017年10月24日 下午2:00:49 <br> * * @param decoded 明文字符串 * @return 密文字节数组用Base64算法编码成的字符串,方便传输、储存 */ public static String encryptByPubKey(String decoded) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException { return encrypt(PUB_KEY, decoded); } /** * 用私钥解密 <br> * <br> * 创建人: leigq <br> * 创建时间: 2017年10月24日 下午1:57:42 <br> * * @param encoded 密文字符串(由密文字节数组用Base64算法编码成的字符串) * @return 明文字符串 */ public static String decryptByPriKey(String encoded) throws NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, UnsupportedEncodingException, InvalidKeyException { return decrypt(PRI_KEY, encoded); } /** * 用私钥加密 * <p> * 创建人:leigq <br> * 创建时间:2018年8月18日 下午5:37:32 <br> * <p> * 修改人: <br> * 修改时间: <br> * 修改备注: <br> * </p> * * @param decoded 明文字符串 * @return 密文字节数组用Base64算法编码成的字符串,方便传输、储存 */ public static String encryptByPriKey(String decoded) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException { return encrypt(PRI_KEY, decoded); } /** * 用公钥解密 * <p> * 创建人:leigq <br> * 创建时间:2018年8月18日 下午5:43:34 <br> * <p> * 修改人: <br> * 修改时间: <br> * 修改备注: <br> * </p> * * @param encoded 密文字符串(由密文字节数组用Base64算法编码成的字符串) * @return 明文字符串 */ public static String decryptByPubKey(String encoded) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException { return decrypt(PUB_KEY, encoded); } /** * 还原公钥,X509EncodedKeySpec 用于构建公钥的规范 * <p> * 创建人:leigq <br> * 创建时间:2018年8月18日 下午5:16:50 <br> * <p> * 修改人: <br> * 修改时间: <br> * 修改备注: <br> * </p> * * @return 公钥对象 */ private static PublicKey restorePubKey() throws NoSuchAlgorithmException, InvalidKeySpecException { X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(BaseCoderUtils.decryptBase64(RSACoder.PUB_KEY_BASE64)); KeyFactory factory = KeyFactory.getInstance(ALGORITHM); return factory.generatePublic(x509EncodedKeySpec); } /** * 还原私钥,PKCS8EncodedKeySpec 用于构建私钥的规范 * <p> * 创建人:leigq <br> * 创建时间:2018年8月18日 下午5:19:09 <br> * <p> * 修改人: <br> * 修改时间: <br> * 修改备注: <br> * </p> * * @return 私钥对象 */ private static PrivateKey restorePriKey() throws NoSuchAlgorithmException, InvalidKeySpecException { PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(BaseCoderUtils.decryptBase64(RSACoder.PRI_KEY_BASE64)); KeyFactory factory = KeyFactory.getInstance(ALGORITHM); return factory.generatePrivate(pkcs8EncodedKeySpec); } // 更换密钥对 // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ /** * 生成密钥对。注意这里是生成密钥对KeyPair,再由密钥对获取公私钥 * <p> * 创建人:leigq <br> * 创建时间:2018年8月18日 下午7:35:21 <br> * <p> * 修改人: <br> * 修改时间: <br> * 修改备注: <br> * </p> */ public static void generateKeyPair() { try { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM); keyPairGenerator.initialize(KEY_SIZE); KeyPair keyPair = keyPairGenerator.generateKeyPair(); /* 公钥、私钥用 encryptBase64 还是 encryptBase64Sun 加密都可以,后者的 Base64 是多行的,比较适合保存到文件的方式储存 */ RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); log.info("新公钥:{}", BaseCoderUtils.encryptBase64(publicKey.getEncoded())); RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); log.info("新私钥:{}", BaseCoderUtils.encryptBase64(privateKey.getEncoded())); } catch (NoSuchAlgorithmException e) { log.error("生成密钥对异常:", e); } } }
测试加密:
/** * RSA 测试 */ @Slf4j class RSATest { public static void main(String[] args) throws IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException, NoSuchAlgorithmException, InvalidKeyException, UnsupportedEncodingException { // 生成密钥对。注意这里是生成密钥对KeyPair,再由密钥对获取公私钥 RSACoder.generateKeyPair(); log.warn("公钥加密 >> 私钥解密"); String originalStr = "helloWorld"; log.warn("原文:{}", originalStr); /* 公钥加密 >> 私钥解密 */ // 公钥加密 String encryptByPubKey = RSACoder.encryptByPubKey(originalStr); log.warn("公钥加密后:" + encryptByPubKey); // 私钥解密 String decryptByPriKey = RSACoder.decryptByPriKey(encryptByPubKey); log.warn("私钥解密后:" + decryptByPriKey); /* 私钥加密 >> 公钥解密 */ // 私钥加密 String encryptByPriKey = RSACoder.encryptByPriKey(originalStr); log.warn("私钥加密后:" + encryptByPriKey); // 公钥解密 String decryptByPubKey = RSACoder.decryptByPubKey(encryptByPriKey); log.warn("公钥解密后:" + decryptByPubKey); } }
RSA加密、解密测试结果:
RSA 签名工具类:
package com.blog.www.util.coder.asymmetrical; import com.blog.www.util.coder.base.BaseCoderUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import java.nio.charset.StandardCharsets; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.Signature; import java.security.SignatureException; /** * RSA签名验签类 */ @Slf4j public class RSASignature extends RSACoder { /** * 用哪个算法来签名 */ private static final String SIGNATURE_ALGORITHM = "SHA1WithRSA"; /* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 生成签名 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */ /** * 用私钥生成 Base64数字签名 * <br> * * @param encoded 加密字符串 * @return 签名,已用Base64编码 */ public static String signToBase64(String encoded) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature sign = getSign(encoded.getBytes(StandardCharsets.UTF_8)); return BaseCoderUtils.encryptBase64(sign.sign()); } /** * 用私钥生成16进制数字签名 * <br> * * @param encoded 加密字符串 * @return 签名,已用转16进制字符串 */ public static String signToHex(String encoded) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature sign = getSign(encoded.getBytes(StandardCharsets.UTF_8)); return Hex.encodeHexString(sign.sign()); } /* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 生成签名 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */ /* ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 验证签名 ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ */ /** * 用公钥校验 Base64数字签名 * <br> * * @param encoded 加密数据 * @param signed 签名,已用Base64编码 * @return 校验成功返回true 失败返回false */ public static boolean verifyFromBase64(String encoded, String signed) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature verify = getVerify(encoded.getBytes(StandardCharsets.UTF_8)); return verify.verify(BaseCoderUtils.decryptBase64(signed)); } /** * 用公钥校验 16进制数字签名 * <br> * * @param data 加密数据 * @param signed 签名,是由字节数组转换成的16进制字符串 */ public static boolean verifyFromHex(String data, String signed) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, DecoderException { Signature verify = getVerify(data.getBytes(StandardCharsets.UTF_8)); return verify.verify(Hex.decodeHex(signed)); } /* ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ 验证签名 ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ */ /** * 用私钥生成数字签名对象 * <br> * * @param encoded 加密字符串转换的字节数组 * @return Signature,方便进一步转换为其他数据 */ private static Signature getSign(byte[] encoded) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initSign(PRI_KEY); signature.update(encoded); return signature; } /** * 用公钥生成校验数字签名对象 * <br> * * @param data 加密字符串转换的字节数组 * @return */ private static Signature getVerify(byte[] data) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM); signature.initVerify(PUB_KEY); signature.update(data); return signature; } }
测试签名:
/** * RSA 签名测试 */ @Slf4j class RSASignTest { public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, DecoderException { // 上面公钥加密产生的密文 String ciphertext = "S1E4OieVAlGyrOB7CzKugseg/R9TGSdDhRSna64tTpxJubpndp2AwCrJ3myIoWEqXNBPKlPVo21vd+KQgzhQcX5WxoNXD5sLarmbZ5eFsBNQOuTzwIhSql+zaUKV6qq+RTSYNR4c/fqllh5Mviq73dB42bWbUY7nHlim+jGojPY="; log.warn("私钥签名——公钥验证签名"); // 产生签名 16 进制签名 String signToBase64 = RSASignature.signToBase64(ciphertext); log.warn("签名:[{}]", signToBase64); // 验证签名 boolean verifyFromBase64 = RSASignature.verifyFromBase64(ciphertext, signToBase64); log.warn("验证签名:[{}]", verifyFromBase64); // 产生签名 16 进制签名 String signToHex = RSASignature.signToHex(ciphertext); log.warn("签名:[{}]", signToHex); // 验证签名 boolean verifyFromHex = RSASignature.verifyFromHex(ciphertext, signToHex); log.warn("验证签名:[{}]", verifyFromHex); } }
测试结果:
2、DSA 签名
DSA-Digital Signature Algorithm 是Schnorr和ElGamal签名算法的变种,被美国NIST作为DSS(DigitalSignature Standard)。简单的说,这是一种更高级的验证方式,用作数字签名。不单单只有公钥、私钥,还有数字签名。私钥加密生成数字签名,公钥验证数据及签名。如果数据和签名不匹配则认为验证失败!数字签名的作用就是校验数据在传输过程中不被修改。数字签名,是单向加密的升级
具体使用看:https://blog.csdn.net/jianggujin/article/details/53440060
-
对称加密算法和非对称加密算法
2020-10-15 17:47:18让对方任意想一个3位数,并把这个数和91相乘,然后告诉我积的最后三位数,我就可以猜出对方想的是什么数字啦!比如对方想的是123,那么对方就计算出123 * 91等于11193,并把结果的末三位193告诉我。看起来,这么做...第一 对称加密:
对称加密是指,加密方和解密方使用同样的秘钥来进行加密和解密。
在对称加密算法中,数据发信方将明文( 原始数据 )和加密 密钥 (mi yue)一起经过特殊加密算法处理后,使其变成复杂的加密密文发送出去。
常用的对称加密算法:AES,RC4,3DES
传输的示意图如下所示:
第二 、非对称加密:
非对称加密算法实现机密信息交换的基本过程是:
- 甲方生成一对密钥并将其中的一把作为公用密钥向其它方公开;
- 得到该公用密钥的乙方使用该密钥对机密信息进行加密后再发送给甲方;
- 甲方再用自己保存的另一把专用密钥对加密后的信息进行解密。
- 甲方只能用其专用密钥解密由其公用密钥加密后的任何信息。
非对称加密算法:RSA,DSA/DSS
用通俗易懂的话来解释非对称加密:
看一个小时候经常在《趣味数学》这类书里的一个数学小魔术:
让对方任意想一个3位数,并把这个数和91相乘,然后告诉我积的最后三位数,我就可以猜出对方想的是什么数字啦!比如对方想的是123,那么对方就计算出123 * 91等于11193,并把结果的末三位193告诉我。看起来,这么做似乎损失了不少信息,让我没法反推出原来的数。不过,我仍然有办法:只需要把对方告诉我的结果再乘以11,乘积的末三位就是对方刚开始想的数了。可以验证一下,193 * 11 = 2123,末三位正是对方所想的秘密数字!
其实道理很简单,91乘以11等于1001,而任何一个三位数乘以1001后,末三位显然都不变(例如123乘以1001就等于123123)。
知道原理后,我们可以构造一个定义域和值域更大的加密解密系统。比方说,任意一个数乘以400000001后,末8位都不变,而400000001 = 19801 * 20201,于是你来乘以19801,我来乘以20201,又一个加密解密不对称的系统就构造好了。
甚至可以构造得更大一些:4000000000000000000000000000001 = 1199481995446957 * 3334772856269093,这样我们就成功构造了一个30位的加密系统。
这是一件非常coooooooool的事情,任何人都可以按照我公布的方法加密一个数,但是只有我才知道怎么把所得的密文变回去。
其安全性就建立在算乘积非常容易,但是要把4000000000000000000000000000001分解成后面两个数相乘,在没有计算机的时代几乎不可能成功!但如果仅仅按照上面的思路,如果对方知道原理,知道我要构造出带很多0的数,根据19801和8位算法这2个条件非常容易穷举出400000001这个目标值。
要解决这个问题,真实世界就不是使用乘法了,比如RSA算法使用的是指数和取模运算,但本质上就是上面这套思想。
传输的示意图如下所示:
如上图所示,客户端用公钥对请求内容加密,服务器使用私钥对内容解密,反之亦然,但上述过程也存在缺点:
公钥是公开的(也就是黑客也会有公钥),所以第 ④ 步私钥加密的信息,如果被黑客截获,其可以使用公钥进行解密,获取其中的内容。
非对称和对称完美结合
非对称加密既然也有缺陷,那我们就将对称加密,非对称加密两者结合起来,取其精华、去其糟粕,发挥两者的各自的优势:
如上图所示
- 第 ③ 步时,客户端说:(咱们后续回话采用对称加密吧,这是对称加密的算法和对称密钥)这段话用公钥进行加密,然后传给服务器
- 服务器收到信息后,用私钥解密,提取出对称加密算法和对称密钥后,服务器说:(好的)对称密钥加密
- 后续两者之间信息的传输就可以使用对称加密的方式了
这是个非常非常经典的数据传输过程,也是Https传输协议里面最经典的部分。也是把对称加密和非对称加密的作用发挥到了很好的地方。在https传输的过程中,如果单独只用对称加密,或者单独使用非对称加密都会出现问题。
-
常用加密算法之非对称加密算法
2018-03-16 21:44:45非对称加密算法 非对称加密算法是一种密钥的保密方法。非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey)。公开密钥与私有密钥是一对,如果用公开密钥对数据进行加密,只有用对应的私有... -
独孤密码-非对称加密算法RSA解析
2021-01-07 20:31:41一种常用的非对称加密算法. 非对称加密算法家族包含了鼻祖DH算法,基于因子分解难题的RSA算法,基于离散对数难题的ElGamal算法和ECC算法等.在本人对接过的多家银行和第三方支付接口中,RSA算法是非对称加密中的网红花旦... -
常用的对称加密算法
2019-10-26 17:20:38需要对加密和解密使用相同密钥的加密算法。由于其速度快,对称性加密通常在消息发送方需要加密大量数据时使用。对称性加密也称为密钥加密。 所谓对称,就是采用这种加密方法的双方使用方式用同样的密钥进行加密和... -
非对称加密算法
2021-04-20 10:49:26常用的非对称加密算法有RSA、DSA、ECC等。 二、非对称加密算法优缺点 1.非对称加密算法优点 私有密匙泄露的风险降低,较大程度上保证了消息的来源性以及消息的准确性和完整性。 2.非对称加密算法缺点 算法强度复杂... -
对称与非对称加密算法
2021-01-12 11:09:33一、对称加密算法:常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。 二、非对称加密算法:常见的非对称加密算法:RSA、DSA(数字签名用)、ECC(移动设备用)、Diffie-Hellman、El Gamal。 三、... -
快速了解常用的对称加密算法,再也不用担心面试官的刨根问底
2022-01-23 15:18:49面试官:说一说你常用的加密算法有哪些? -
典型的对称加密和非对称加密算法有哪些
2021-07-10 11:58:53几种对称性加密算法:AES,DES,3DES DES是一种分组数据加密技术(先将数据分成固定长度的小数据块,...几种非对称性加密算法:RSA,DSA,ECC RSA和DSA的安全性及其它各方面性能都差不多,而ECC较之则有着很多的性能优越, -
三种非对称加密算法总结
2018-09-06 10:45:14最经典的非对称加密算法 也可认为是使用最多的非对称加密算法 能用于密钥分配,也能用于加解密数据(“私钥加密,公钥解密”和“公钥加密,私钥解密”) 密钥长度:512~65536(64的整数倍) 只有发送方有一个... -
对称加密和非对称加密的区别以及应用。了解哪些常用的加密算法?MD5算法详解
2020-01-27 13:31:41对称加密和非对称加密的区别以及应用。了解哪些常用的加密算法?能简单介绍一种吗? 内推军P186 P192 1.分类 加密算法首先分为两种:单向加密、双向加密。 单向加密是不可逆的,也就是只能加密,不能解密。通常... -
对称加密、非对称加密和散列算法
2022-02-21 13:49:03对称加密算法用来对敏感数据等信息进行加密。对称加密算法使用起来简单快捷,密钥较短,且破译困难。除了数据加密标准(DESData Encryption Standard),另一个对称密钥加密系统是国际数据加密算法(IDEA),它比DES的... -
Java常用非对称加密算法-RSA
2018-05-15 16:20:07RSA作为常用的非对称加密算法,用法基本就是首先生成公钥和私钥密钥对,然后用公钥加密私钥解密或者用私钥加密公钥解密。这里只写代码实现。import javax.crypto.Cipher; import java.security.*; import java.... -
java中的对称加密算法和非对称加密算法
2019-01-16 19:08:11对称加密算法用来对敏感数据等信息进行加密,常用的算法包括DES、3DES、AES、DESX、Blowfish、、RC4、RC5、RC6。 DES(Data Encryption Standard):数据加密标准,速度较快,适用于加密大量数据的场合。 3DES... -
基于FPGA的常用哈希及对称加密算法.pdf
2021-07-13 10:16:37基于FPGA的常用哈希及对称加密算法.pdf -
常用加密算法的Java实现总结(二)——对称加密算法DES、3DES和AES.pdf
2020-02-10 19:04:20常用加密算法的java实现总结,常用加密算法的java实现总结,常用加密算法的java实现总结,常用加密算法的java实现总结,常用加密算法的java实现总结 -
常用加密算法--对称加密算法
2019-10-26 20:36:11DES是1977年美国联邦信息处理标准(FIPS)中所采用的一种对称密码(FIPS46.3)。DES一直以来被美国以及其他国家的政府和银行等广泛使用。然而,随着计算机的进步,现在DES已经能够被暴力破解,强度大不如前了 ... -
java加密解密之对称加密算法desx_常用对称加密算法
2020-08-24 13:44:42Java 加密解密之对称加密算法DES 本文转自网络 数据加密算法Data Encryption AlgorithmDEA是一种对称加密算法很可能是使用最广泛的密钥系统特别是在保护金融数据的安全中最初开发的DEA是嵌入硬件中的通常自动取款机... -
对称加密算法和非对称加密算法的完美结合
2018-04-13 13:17:05第一 对称加密: 对称加密是指,加密...常用的对称加密算法:AES,RC4,3DES传输的示意图如下所示:如上图所示,此种方式属于对称加密,双方拥有相同的密钥,信息得到安全传输,但此种方式的缺点是:(1)不同的客户... -
常见非对称加密算法
2019-04-10 15:14:35和对称加密技术只使用一个秘钥不同,非对称机密技术使用两个秘钥进行加解密,一个叫做公钥,一个叫做私钥,私钥自己来保管,公钥可以公开,使用公钥加密的数据必须使用私钥解密,反之亦然公钥和私钥是两个不同的秘钥... -
Java与对称加密、非对称加密算法
2017-05-16 18:27:22对数据加密的算法有很多种。总体来说分为两大类:对称加密算法和非对称加密算法。 用Java来实现非对称加密和对称加密 -
Java中常用的加密算法
2021-01-08 01:29:14Java中常用的加密算法主要有MD5,DES(对称加密),RSA(非对称加密),每一种加密算法有着各自的加密特点。(注意:本文为kotlin编码) 一.MD5 MD5全称Message_Digest Algorithm-5,即信息-摘要算法5,消息摘要是采用任意... -
对称与非对称加密算法总结
2020-08-30 15:20:521.对称加密与非对称加密 一段明文通过密钥进行加密,可以生成一段密文;这段密文通过同样的密钥进行解密,可以还原成明文。这样一来,只要双方事先约定好了密钥,就可以使用密文进行往来通信。例如:AES加密。 ... -
常用对称加密算法与分组模式
2021-08-29 22:08:31一、常用的对称加密算法有 DES:特点是每隔7位做一次奇偶校验,加密时8个字节为一组,得到的密文长度不变 3DES:三重DES 加密过程为 加密-解密-加密(不是加密-加密-加密,是为了兼容以前的DES) 特点:安全,... -
Java加密算法—非对称加密
2022-02-15 15:54:34Java加密算法—非对称加密