4.Java开源RSA/SM2非对称加密算法介绍
前期内容导读:
- Java开源RSA/AES/SHA1/PGP/SM2/SM3/SM4加密算法介绍
- Java开源AES/SM4/3DES对称加密算法介绍及其实现
- Java开源AES/SM4/3DES对称加密算法的验证说明
-
非对称加密
主要是指秘钥对
是非对称的(相对于对称加密
而言),简单理解就是加密秘钥和解密秘钥不同,一般叫做公钥和私钥。公钥是需要给出去的,私钥需要自己保存,属于非常重要的隐私数据; -
非对称加密
在加解密能力的基础上,还衍生出了签名和验证的能力,用于应对内容是否被篡改,就像古代的蜡封一样; - 由于非对称加密算法比较复杂,加解密效率并不高,加之当下服务都在分布式化,运行分布式服务的机器配置(包括VM)都不高,所以实际很少使用其加解密特性,大多都是使用其签名和验签能力,比如:加密机、PGP加密等;
- 国际上非对称加密算法主要为RSA,与之对应的国密非对称加密算法为SM2,当下SM2的应用还相对较少;
1. 开源组件 非对称秘钥加密介绍
- 加密组件引入方法:
<dependency> <groupId>com.biuqu</groupId> <artifactId>bq-encryptor</artifactId> <version>1.0.5</version> </dependency>
1.1 非对称秘钥加密算法列表如下:
名称 | 全称 | 加密长度 |
常用模式 | 填充模式 | 签名算法 | 常用算法 | 加密特点 | 签名特点 |
---|---|---|---|---|---|---|---|---|
RSA | 3人名缩写 |
2048 3072 4096 |
ECB |
NoPadding PKCS1Padding OAEPPadding |
SHA512WITHRSA SHA256WITHRSA … |
RSA/ECB/PKCS1Padding |
支持公钥加密,私钥解密 支持私钥加密,公钥解密 不支持分段加密 |
支持私钥签名,公钥验签 |
SM2 | SM2椭圆曲线公钥密码算法 | 256 | - | - | SM3WithSM2 | - | 国密算法,安全性优于RSA 2048,可用于替换RSA; 支持公钥加密,私钥解密 支持分段加密 |
支持私钥签名,公钥验签 |
说明:
加密长度
: 在非加密算法中通常是指一次性可加密的密文块的长度。注意:加密长度
不等于秘钥长度,在RSA/SM2中秘钥长度与加密长度是存在一定关系的;- 在非对称加密算法中,RSA加密时,PKCS1Padding/OAEPPadding/NoPadding等多种填充算法,填充长度是不同的,这会直接影响加密的明文的长度;
RSA
虽然支持私钥加密公钥解密,但是这是不符合实际的应用场景的,因为公钥通常是要给出去的,有时不止给1个客户方,这样所有的客户方都可以解密了,框架中虽然可以支持这种方式,但是不推荐使用;- 可以看下
BouncyCastle
源码org.bouncycastle.jcajce.provider.asymmetric.rsa.CipherSpi.java
,里面有各种填充模式;并且里面做了全大写转换匹配,所以不会有大小写问题;
1.2 非对称秘钥加密算法的特点如下:
- 加密长度、秘钥和明文的关系表如下:
加密算法 | 秘钥初始值 (byte) |
加密长度 (bit) |
私钥长度 (byte) |
公钥长度 (byte) |
生成耗时 (ms) |
---|---|---|---|---|---|
RSA | 1000 | 1024 | 633-636 | 162 | 79 |
RSA | 1000 | 2048 | 1216-1218 | 294 | 612 |
RSA | 1000 | 3072 | 1792-1795 | 422 | 2038 |
RSA | 1000 | 4096 | 2372-2376 | 550 | 8577 |
SM2 | 1000 | 256 | 150 | 91 | 15 |
说明:
- RSA私钥长度是个范围,公钥长度是固定值;
- SM2公私钥长度是固定值;
- 自验发现SM2生成秘钥的效率要远远高于RSA;RSA加密长度提升时,其生成耗时也增长了好几倍(限于本人机器性能和精力有限,仅做了20+次简单验证);
- 明文长度、加密长度、填充算法与密文长度关系表:
加密算法 | 加密长度 (bit) |
填充算法 | 填充长度 (byte) |
明文长度 (byte) |
密文长度 (byte) |
加密耗时 (ms) |
---|---|---|---|---|---|---|
RSA | 1024/2048/3072/4096 | NoPadding | 0 | 1-${EncLen}
|
${EncLen} |
400-500 |
RSA | 1024/2048/3072/4096 | PKCS1Padding | 11 | 1-(${EncLen} -11) |
${EncLen} |
400-500 |
RSA | 1024/2048/3072/4096 | OAEPPadding | 42 | 1-(${EncLen} -42) |
${EncLen} |
400-500 |
SM2 | 256 | - | - | 1 | 98 | 15 |
SM2 | 256 | - | - | 2 | 99 | 15 |
SM2 | 256 | - | - | … | … | 15 |
SM2 | 256 | - | - | 65 | 162 | 15 |
说明:
${EncLen}
表示加密长度,RSA每次可加密的明文长度=${EncLen}
-填充长度,明文超过部分需要做二次加密调用,但BouncyCastle RSA不支持二次调用;- RSA加密时,PKCS1Padding填充符占用11byte,NoPadding占0byte,
OAEPPadding
填充符占用42byte;在C/C++资料中有PKCS1OAEPPadding
填充算法,可能和Java中的OAEPPadding
是同一种填充算法,待验证;尤其说明下,好多线上资料都说OAEPPadding
填充占41byte,大家也可以自行验证下;- RSA加密时,选择
NoPadding
时,在批量加密时,经常报错,但因为这种模式本来就不安全,本身也是不推荐使用的;- SM2 密文长度不是定长的,密文最低是98byte,每增加1byte的数据,密文也相应增加1byte;
- BouncyCastle SM2支持分段加密;
2. 开源组件 非对称秘钥加密实现
2.1 对称秘钥加密代码设计
bq-encryptor非对称秘钥加密代码设计 | |||||
---|---|---|---|---|---|
算法名称 | 算法实现类 | 抽象类 | 是否安全 | 补充说明 | |
RSA | RsaEncryption | BaseSingleSignature | ✔ | 2048及以上是安全的 | |
SM2 | Sm2Encryption | ✔ | RSA的国内替代算法 |
2.2 非对称秘钥加密核心逻辑
-
非对称加密RSA与SM2实现的原理完全不同,所以抽象类
BaseSingleSignature
只做了公共接口定义,比如:生成秘钥、加密、解密、签名、验签等,具体的实现分别在算法实现类里面; -
RSA与SM2的设计与实现会单独讲解;文章来源:https://www.toymoban.com/news/detail-626595.html
3. 开源组件 非对称加密使用
以SM2算法为例,可以有如下3种使用方式:文章来源地址https://www.toymoban.com/news/detail-626595.html
- 使用方式1:直接创建SM2加密对象
BaseSingleSignature encryption = new Sm2Encryption();
- 使用方式2:通过算法工厂创建SM2加密对象
BaseSingleSignature encryption = EncryptionFactory.SM2.createAlgorithm();
4.RSA算法的的应用
4.1 RSA在JwtToken的应用
- 在
spring-security-oauth2-authorization-server
自定义Jwt认证服务的秘钥:/** * 注入秘钥管理服务 * * @param JWK 秘钥对象 * @return 秘钥管理服务 */ @Bean public JWKSource<SecurityContext> jwkSource(JWK jwk) { JWKSet jwkSet = new JWKSet(jwk); return (jwkSelector, context) -> jwkSelector.select(jwkSet); } ... /** * 生成JWK对象 * * @param priKey 私钥(非必传时,表示仅需公钥验证) * @param pubKey 公钥 * @param kid 秘钥id(可重新设置,重启后对所有客户端生效) * @return JWK秘钥对象 */ private static JWK genRsaKey(byte[] priKey, byte[] pubKey, String kid) { BaseSingleSignature encryption = EncryptionFactory.RSA.createAlgorithm(); RSAPublicKey rsaKey = (RSAPublicKey)encryption.toPubKey(pubKey); RSAKey.Builder builder = new RSAKey.Builder(rsaKey); if (null != priKey) { PrivateKey rsaPriKey = encryption.toPriKey(priKey); builder.privateKey(rsaPriKey); } if (null == kid) { kid = UUID.randomUUID().toString(); } return builder.keyID(kid).build(); }
到了这里,关于4.Java开源RSA/SM2非对称加密算法对比介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!