1.Java开源RSA/AES/SHA1/PGP/SM2/SM3/SM4加密算法介绍

1.Java开源RSA/AES/SHA1/PGP/SM2/SM3/SM4加密算法介绍

  • 支持RSA(1024/2048)/AES(128/192/256)/SHA-1/SHA-256/SHA-512/SHA-3/MD5/PGP/HMAC-SHA256/HMAC-SHA512等国际通用的加密算法;
  • 支持SM2/SM3/SM4/HMAC-SM3等国密算法;
  • 还支持国密和国际加密算法的统一抽象与封装,并封装了国际/国密组合使用的一些实践;
  • 加密组件引入方法:
    <dependency>
        <groupId>com.biuqu</groupId>
        <artifactId>bq-encryptor</artifactId>
        <version>1.0.5</version>
    </dependency>
    

1. 为什么要写bq-encryptor加解密组件

  • 密码学原理较复杂,但是应用阶段,绝大部分时候是不需要关注原理的。而网上一大堆内容在介绍原理,对于实现仅寥寥几笔,容易让涉足者望而却步,我想做到原理和应用隔离,让有兴趣的人快速上手怎么应用加解密;
  • 随着国密加解密算法崛起(基本上按照国际规范自研了1套),刚好可以按照抽象思维来实现2套加解密逻辑,有助于站在更高的位置、更好地理解各种加密算法的加解密特性;
  • 国密密改在政府、银行、金融保险行业有很高的安全诉求,在其他行业,也势在必行,此处也做了较好地模拟实现,以供参考;
  • 在Java世界里,当前使用最广泛的加解密组件莫过于BouncyCastle(澳大利亚非盈利组织)
    了,本加解密组件也是基于BouncyCastle做了二次封装,但是同时也屏蔽了其底层实现,期待着有一天我们也有自己的国产的更优实现;

2. 使用bq-encryptor加解密组件有什么好处

  • 3.2.1分层设计的包名规划图所示,除了加密算法(XxxEncryption)外,其它的封装皆为SpringBoot准备,可以非常方便的注入其中,使用也及其简单;

    • 在SpringBoot yaml中配置如下:
      bq:
        encrypt:
          #默认加密算法(true表示国密)
          gm: true
          #模拟的加密机(正常情况下,加密机的秘钥是在加密机服务中,此处是不用配置的)
          hsm:
            - algorithm: SM4Hsm
              pri: e9c9ba0326f00c39...
            - algorithm: SM2Hsm
              pri: 3081930201003013...
              pub: 3059301306072a8e...
            - algorithm: SM3Hsm
            - algorithm: GmIntegrityHsm
            - algorithm: AESHsm
              pri: 7c9726e56ce9bc28b...
            - algorithm: RSAHsm
              pri: 308204bc020100...
              pub: 30820122300d0...
            - algorithm: SHAHsm
            - algorithm: UsIntegrityHsm
          #经过加密机加密的jasypt秘钥
          enc: d83b8495e86...
          #经过jasypt加密的适用于本地加密和对外交互数据加密的加密器秘钥
          security:
            - algorithm: SecureSM4
              pri: ENC([key]f7222de...)
            - algorithm: SM4
              pri: ENC([key]5495204...)
            - algorithm: SM2
              pri: ENC([key]61835c8...)
              pub: ENC([key]0b74f34...)
            - algorithm: SM3
            - algorithm: GM
            - algorithm: SecureAES
              pri: ENC([key]6916ae6...)
            - algorithm: AES
              pri: ENC([key]a6b7ecd...)
            - algorithm: RSA
              pri: ENC([key]23708c8...)
              pub: ENC([key]c1ae5a5...)
            - algorithm: SHA-512
            - algorithm: US
            - algorithm: PGP
              pri: ENC([key]29ff6fa...)
              pub: ENC([key]c315ac7...)
              kid: pgpUser01
              pwd: ENC(e71aebdc7b5e...)
              expire: 33219557748024
              #自定义的加密器可以通过`- name:`来区分
    
    • SpringBoot中注入加密机
    @Configuration
    public class EncryptHsmConfigurer
    {
      @Bean("hsmBatchKey")
      @ConfigurationProperties(prefix = "bq.encrypt.hsm")
      public List<EncryptorKey> hsmBatchKey()
      {
          List<EncryptorKey> batchKey = new ArrayList<>(Const.TEN);
          return batchKey;
      }
    
      /**
       * 注入加密机的配置秘钥信息
       *
       * @return 加密机的配置秘钥信息
       */
      @Bean(EncryptorConst.HSM_KEYS)
      public EncryptorKeys hsmKeys(@Qualifier("hsmBatchKey") List<EncryptorKey> batchKey)
      {
          EncryptorKeys keys = new EncryptorKeys();
          keys.setKeys(batchKey);
          keys.setGm(this.gm);
          return keys;
      }
    
      /**
       * 注入加密机服务门面
       *
       * @param hsmKeys 加密机的配置秘钥信息
       * @return 加密机服务门面
       */
      @Bean(EncryptorConst.HSM_SERVICE)
      public HsmFacade hsmFacade(@Qualifier(EncryptorConst.HSM_KEYS) EncryptorKeys hsmKeys)
      {
          return new HsmFacade(hsmKeys);
      }
    
      /**
       * 注入业务安全服务
       *
       * @param hsmFacade 加密机服务
       * @return 业务安全服务
       */
      @Bean
      public BizHsmFacade hsmBizFacade(@Qualifier(EncryptorConst.HSM_SERVICE) HsmFacade hsmFacade)
      {
          return new BizHsmFacade(hsmFacade);
      }
    
      /**
       * 对配置文件中加密的默认类型(国密/国际加密)
       */
      @Value("${bq.encrypt.gm}")
      private boolean gm;    
    }
    
    • SpringBoot中注入jasypt
    @Configuration
    public class JasyptEncryptConfigurer
    { 
      /**
       * 配置自动加解密的处理器
       *
       * @return 加解密处理器
       */
      @Bean("jasyptStringEncryptor")
      public StringEncryptor getEncryptor()
      {
          String confKey = this.key;
          //兼容有加密机的场景(加密机会对配置文件的加密key进行加密)
          if (null != this.hsmFacade)
          {
              //解密出真实的配置key
              confKey = this.hsmFacade.decrypt(this.key);
          }
    
          BaseSecureSingleEncryption encryption;
          if (this.gm)
          {
              encryption = EncryptionFactory.SecureSM4.createAlgorithm();
          }
          else
          {
              encryption = EncryptionFactory.SecureAES.createAlgorithm();
          }
          return new JasyptEncryptor(encryption, confKey);
      }
    
      /**
       * 注入加密机(有才注入,否则忽略)
       */
      @Autowired(required = false)
      private HsmFacade hsmFacade;
    
      /**
       * 对配置文件是否为国密
       */
      @Value("${bq.encrypt.gm:true}")
      private boolean gm;
    
      /**
       * 对配置文件加密的sm4 key
       */
      @Value("${bq.encrypt.enc}")
      private String key;   
    }
    
    • SpringBoot中注入加密安全器,配置类同加密机的配置类,略。

    上述3个SpringBoot配置类简单说明了怎么批量注入加解密的对象,后续使用时,仅需通过注解就可以了。这些逻辑本人已全部实现并验证。此处仅了解整体的设计即可。

  • 可以支持多种业务场景:

    • 如上配置代码所示,可完美适配jasypt组件:支持模拟的加密机对jasypt组件的秘钥加密,再使用jasypt组件对加密安全器秘钥加密;
    • 支持加密机自动对数据库数据做数据加密和完整性校验;
    • 接口认证数据加密
    • 接口数据防篡改校验
    • 接口数据加密

    综上,上述业务场景的实现,本人会在后续的基于SpringCloud的bq微服务基础框架中开源。

3. bq-encryptor加解密组件的使用说明

本节将从国际标准的加密分类、加解密组件的分层、加解密组件的使用、加解密组件的实现依次予以介绍。

3.1 加解密分类

名称全称类型加密长度加密/工作模式/填充模式签名算法使用场景典型案例
RSA3人名缩写非对称加密1024
2048
- RSA/ECB/PKCS1Padding
RSA/ECB/OAEPWithSHA-1AndMGF1Padding
RSA/ECB/OAEPWithSHA-256AndMGF1Padding
SHA512WITHRSA
SHA256WITHRSA
加密效率较低,一般不用作加密
用做签名
HTTPS证书
JwtToken签名
SM2SM2椭圆曲线公钥密码算法非对称加密256-SM3WithSM2安全性优于RSA 2048,可用于替代RSA
用做签名
国产HTTPS证书
国产加密机
AESAdvanced Encryption Standard对称加密128
192
256
AES/CBC/NoPadding
AES/CBC/PKCS5Padding
AES/ECB/PKCS5Padding
AES/CTR/NoPadding
-加密效率高,当下只有256位是安全的
通常使用CBC/CTR模式加密
各种数据加密
SM4SM4分组密码算法对称加密128
SM4/CBC/PKCS5Padding
SM4/CTR/NoPadding
-安全性优于AES 256,可用于替换AES
通常使用CBC/CTR模式加密
各种数据加密
3DESTriple Data Encryption Algorithm对称加密192
DESede/CBC/NoPadding
DESede/CBC/PKCS5Padding
DESede/ECB/PKCS5Padding
-安全性较差,建议使用AES/SM4来替代各种数据加密
SHA-1Secure Hash Algorithm 1摘要算法160
--- 用于内容防篡改各种报文/下载文件的完整性校验
SHA-256Secure Hash Algorithm 2摘要算法256
--- 用于内容防篡改各种报文/下载文件的完整性校验
SHA-512Secure Hash Algorithm 2摘要算法512
--- 用于内容防篡改各种报文/下载文件的完整性校验
SHA3Secure Hash Algorithm 3摘要算法512
--- 用于内容防篡改各种报文/下载文件的完整性校验
SM3SM3密码杂凑算法摘要算法256
--在SHA-256基础上的改进算法,用于替代SHA算法各种报文/下载文件的完整性校验
MD5Secure Hash Algorithm 1摘要算法128<--用于内容防篡改安全性较差,建议使用SHA-512/SM3来替替代
HmacSHA256Hash-based Message Authentication Code基于摘要的带认证码的加密算法256
--用于内容防篡改
用于消息认证
安全性一般,曾用于早期的JwtToken认证
HmacSHA512Hash-based Message Authentication Code基于摘要的带认证码的加密算法512
--用于内容防篡改
用于消息认证
Hmac-SHA256的升级版
HmacSM3Hash-based Message Authentication Code基于摘要的带认证码的加密算法256
--用于内容防篡改Hmac的国产实现,用于替代HmacSHA256

加密长度: 在加密算法中通常是指分段秘钥的长度,在摘要算法中通常是指内容块的长度;

补充说明: 由于加密长度、填充模式、签名算法的不同,实际上会有非常多的组合使用方式,此处并没有一一列举,但组件基本上都已支持;

3.2 加解密组件的分层

3.2.1 分层整体设计
     加密算法                      加密器                        加密机
 +-------------+             +-------------+             +-------------+
 | encryption  |             |  encryptor  |             |     hsm     |
 |             |  -------->  |             |  -------->  |             |
 +-------------+             +-------------+     |       +-------------+
                                                 |
                                                 |           加密安全器
                                                 |       +-------------+
                                                 |       |   security  |
                                                 +---->  |             |
                                                         +-------------+

加密算法(encryption):提供了基本的加解密算法能力,包括生成秘钥,传入报文和秘钥做加解密,还提供了部分证书解析和转换的能力。包名:com.biuqu.encryption

加密器(encryptor):加密算法的封装类,简化了加解密算法的使用,初始化加密器时,就需要初始化秘钥,仅需要传入报文做加解密,包名:com.biuqu.encryptor

加密机(hsm):加密器的子类,封装了只需要在系统内部使用秘钥的、安全等级最高的加密器的使用,仅需要传入报文做特定的加解密,包名:com.biuqu.hsm

加密安全器(security):加密器的子类,封装了需要与外部交换秘钥、内部安全等级不高的特殊的加密器的使用,仅需要传入报文做加解密,包名:com.biuqu.security

  • 在实际的业务场景中,基本上只会使用加密机(hsm)和加密安全器(security)2种模式,因为很少需要在运行过程中去生成秘钥。
3.2.2 分层详细设计
  • 按照加解密算法类型划分
bq-encryptor按照加解密算法类型划分
类型抽象类算法名称算法实现类是否安全补充说明
对称加密算法BaseSingleEncryptionAESAesEncryption只有256位是安全的
SM4Sm4EncryptionAES256的国内替代算法
3DESDes3Encryption不安全算法,不推荐使用
BaseSecureSingleEncryptionAESAesSecureEncryption在AES加解密时增加了盐值
SM4Sm4SecureEncryption在SM4加解密时增加了盐值
非对称加密算法BaseSingleSignatureRSARsaEncryption只有2048位是安全的
SM2Sm2EncryptionRSA2048的国内替代算法
复合加密算法BaseMultiEncryptionPGPPgpEncryption一般单独使用签名场景,加解密时效率也高于单独使用相同的非对称加密算法
在国际上有使用该协议做敏感报文的加解密
复合签名算法BaseMultiSignatureUSUsEncryption自定义算法,综合使用了RSA2048/SHA512/AES256算法
GMGmEncryption自定义国密算法,综合使用了SM2/SM3/SM4算法
UsHsmUsHsmEncryption自定义算法,应用于加密机场景,综合使用了RSA2048/SHA512
GmHsmGmHsmEncryption自定义国密算法,应用于加密机场景,综合使用了SM2/SM3
摘要算法BaseHashSHA-512ShaHashSHA摘要算法的通用实现,可支持:SHA-1/SHA-224/SHA-256/SHA-384/SHA-512/SHA3-224/SHA3-256/SHA3-384/SHA3-512/MD5等
SM3Sm3HashSHA256的国内替代算法
HMAC算法KeyHashHMACShaHmacKeyHashHMAC的通用实现,可支持:HmacSHA1/HmacSHA224/HmacSHA256/HmacSHA384/HmacSHA512/HmacMD5等
Sm3HmacSm3HmacKeyHashHMAC的国内替代算法
  1. 盐值:即对应加解密算法中的偏移量;
  2. 复合签名算法GM/US加密算法为业务场景中的提炼总结,GmHsm/UsHsm为加密机的实际使用经验总结,总之就是要兼顾加解密效率和安全;
  3. 上述算法实现均基于BouncyCastle做了统一的封装;
  4. 国际加密算法基本上都有1个与之对应的国密算法(PGP除外);
  • 加密算法的简化使用设计
    • 使用工厂+枚举类的方式(参见EncryptionFactory),可以非常快捷的创建任一个指定的加密算法对象;
    • GM加密算法是综合了多个加密算法对象,做了封装实现:
      • 使用SM3对源报文生成摘要;
      • 使用自持的SM2私钥对摘要签名;
      • 使用新生成的SM4秘钥对源报文加密并生成密文;
      • 再使用对端的SM2公钥对SM4秘钥加密生成加密秘钥;
      • 拼接加密秘钥、签名和密文;
      • GM解密是上述步骤的逆过程;
    • US加密算法实现原理同上;
    • GmHsm加密算法是加密机的最佳实践总结:
      • 使用加密机的SM3对源报文生成摘要;
      • 使用加密机的私钥对摘要做签名;
      • GmHsm解密就是对源报文生成的摘要做验签;
    • UsHsm加密算法实现原理同上;

3.3 bq-encryptor加解密组件的使用

  • 使用EncryptionFactory构建3.2.2表中的任意算法实现类并使用加解密,如:
        Sm2Encryption sm2 = EncryptionFactory.SM2.createAlgorithm();
        SecureRandom random = sm2.createRandom(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));
        byte[] sm2InitKey = new byte[16];
        random.nextBytes(sm2InitKey);  
    
        String text = "testTextAbc`123";
        KeyPair keyPair = sm2.createKey(sm2InitKey);
        byte[] pubKey = keyPair.getPublic().getEncoded();
        byte[] priKey = keyPair.getPrivate().getEncoded();
        byte[] encryptBytes = sm2.encrypt(text.getBytes(StandardCharsets.UTF_8), pubKey, null);
        byte[] decryptBytes = sm2.decrypt(encryptBytes, priKey, null);
        System.out.println("Decrypt text=" + new String(decryptBytes, StandardCharsets.UTF_8));
    
  • 使用EncryptorFactory构建3.2.2表中任意算法对应的加密器并使用加解密,如:
        EncryptorKey sm2Key = new EncryptorKey();
        sm2Key.setAlgorithm(EncryptorFactory.SM2.getAlgorithm());
        sm2Key.setPri(Hex.toHexString(keyPair.getPrivate().getEncoded()));
        sm2Key.setPub(Hex.toHexString(keyPair.getPublic().getEncoded()));
    
        Sm2Encryptor sm2Encryptor = EncryptorFactory.SM2.createEncryptor(sm2Key);
        byte[] encryptBytes = sm2Encryptor.encrypt(text.getBytes(StandardCharsets.UTF_8), null);
        byte[] decryptBytes = sm2Encryptor.decrypt(encryptBytes, null);
        System.out.println("Decrypt text=" + new String(decryptBytes, StandardCharsets.UTF_8));      
    
  • 使用SecurityFacade构建3.2.2表中任意算法对应的业务安全加密器并使用加解密(亦可参见第2章的SpringBoot注入方式),如:
        List<EncryptorKey> keys = new ArrayList<>(32);
        keys.add(sm2Key);
    
        SecurityFacade securityFacade = new SecurityFacade(keys);
        String encryptText = securityFacade.signEncrypt(text);
        String decryptText = securityFacade.signDecrypt(encryptText);
        System.out.println("Decrypt text=" + decryptText);        
    
  • 使用HsmFacade构建3.2.2表中任意算法对应的加密机并使用加解密(亦可参见第2章的SpringBoot注入方式),如:
        List<EncryptorKey> keys = new ArrayList<>(32);
        keys.add(sm2Key);
    
        HsmFacade hsmFacade = new HsmFacade(keys);
        String signText = hsmFacade.sign(text);
        boolean result = hsmFacade.verify(text,signText);
        System.out.println("verify result=" + result);      
    

3.4 bq-encryptor加解密组件的实现

  • EncryptionFactory汇聚了所有加解密算法的实现;
  • EncryptorFactory构建了所有加密器的实现(内置了加密算法和秘钥);
  • SecurityFacade构建了本地秘钥和安全要求不高的加解器的实现(除了内置加密算法和秘钥,还内置了一定的安全业务逻辑);
  • HsmFacade构建了安全极高的加密机的实现(除了内置加密算法和秘钥,且秘钥是无法被获取的,还内置了一定的安全业务逻辑);
  • ClientSecurity构建了本地秘钥和安全要求不高的加密器的实现(除了SecurityFacade的作用外,还可以根据客户指定不同的秘钥);
  • 后续会基于各种加密算法分别详细分析与总结;
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我能够帮你用 JavaRSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING 加密和解密。以下是示例代码: 加密: ```java import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import java.security.*; import java.security.spec.MGF1ParameterSpec; import java.security.spec.X509EncodedKeySpec; public class Encryptor { public static byte[] encrypt(byte[] input, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"); MGF1ParameterSpec mgf1ParameterSpec = new MGF1ParameterSpec("SHA-256"); OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", mgf1ParameterSpec, PSource.PSpecified.DEFAULT); cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaepParameterSpec); return cipher.doFinal(input); } } ``` 解密: ```java import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import java.security.*; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; public class Decryptor { public static byte[] decrypt(byte[] input, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"); MGF1ParameterSpec mgf1ParameterSpec = new MGF1ParameterSpec("SHA-256"); OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", mgf1ParameterSpec, PSource.PSpecified.DEFAULT); cipher.init(Cipher.DECRYPT_MODE, privateKey, oaepParameterSpec); return cipher.doFinal(input); } } ``` 你需要提供公钥和私钥。下面是使用示例: ```java import java.security.*; public class Main { public static void main(String[] args) throws Exception { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); KeyPair keyPair = keyPairGenerator.generateKeyPair(); PublicKey publicKey = keyPair.getPublic(); PrivateKey privateKey = keyPair.getPrivate(); String plainText = "Hello, world!"; byte[] encrypted = Encryptor.encrypt(plainText.getBytes(), publicKey); byte[] decrypted = Decryptor.decrypt(encrypted, privateKey); String decryptedText = new String(decrypted); System.out.println("Original text: " + plainText); System.out.println("Decrypted text: " + decryptedText); } } ``` 在这里,我们首先生成一个 RSA 密钥对,并将公钥和私钥传递给加密和解密函数。然后我们加密字符串 "Hello, world!",并使用相同的私钥解密它。最后,我们将原始文本和解密后的文本一起打印出来。 提醒:在真实的应用中,你需要将生成的密钥保存到文件或数据库中,以便以后使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值