先解释一下什么是数字信封:  将对称密钥通过非对称加密(即:有公钥和私钥两个)的结果分发对称密钥的方法。大白话讲: 用对称秘钥对文件或字节加密,然后用非对称秘钥对对称秘钥的钥匙进行加密.

这里再解释一下对称秘钥和非对称秘钥:

  • 非对称秘钥: 非对称加密算法需要两个密钥:公开密钥(publickey:简称公钥)和私有密钥(privatekey:简称私钥)。公钥与私钥是一对,如果用公钥对数据进行加密,只有用对应的私钥才能解密。因为加密和解密使用的是两个不同的密钥,所以这种算法叫作非对称加密算法
  • 对称秘钥算法:加密是双方使用相同的密钥,必须以绝对安全的形式传送密钥才能保证安全。若果密钥泄露,加密数据将受到威胁,这点不如非对称密钥。只有一个秘钥

数字信封是实现信息保密性验证的技术。

  • 文件加密流程:

  • 文件解密流程:

  • 我的实现思路:  对称算法选择国密的sm4算法, 采用SM4/ECB/PKCS5Padding, 非对称算法采用国密sm2 ,

具体实现代码:

  • 数字信封加密
数字信封加密
package com.ymwk;

import java.io.BufferedOutputStream;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.security.InvalidKeyException;import java.security.KeyFactory;import java.security.NoSuchAlgorithmException;import java.security.NoSuchProviderException;import java.security.PublicKey;import java.security.Security;import java.security.cert.CertificateException;import java.security.cert.CertificateFactory;import java.security.cert.X509Certificate;import java.security.spec.InvalidKeySpecException;import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.crypto.InvalidCipherTextException;import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;import org.bouncycastle.jce.provider.BouncyCastleProvider;

import com.ymwk.base64.Base64Utils;import com.ymwk.file.FileUtils;import com.ymwk.result.Result;import com.ymwk.sm2.GMBaseUtil;import com.ymwk.sm2.SM2CertUtil;import com.ymwk.sm2.SM2Util;import com.ymwk.sm4.Sm4Utils;

/** * 对文件的数字信封 * @author Saxon  * @Date   2021年7月8日 */public class FileEncrypt extends GMBaseUtil{

  /**    * @param publicKey 公钥对象  * @param fileBytes  文件字节数组   * @return Result if(code== 200)success else fail       * encryptFileStr 加密后的文件字符串    * encryptKeyStr  加密后的秘钥字符串    * @throws IOException    * @throws NoSuchProviderException    * @throws NoSuchAlgorithmException   */   public static Result fileEncrypt(PublicKey publicKey,byte[] fileBytes)  {     try {         //创建对称秘钥对         byte[] key = Sm4Utils.generateKey();         //对文件加密           byte[] fileEncryptBytes = Sm4Utils.encryptEcbPadding(key, fileBytes);            //对秘钥对加密          byte[] encryptKey = SM2Util.encrypt((BCECPublicKey)publicKey, key);          //将返回值base64加密            String encryptKeyStr = Base64Utils.encode(encryptKey);           return new Result(Result.CODE_SUCCESS,"文件加密成功",encryptKeyStr,fileEncryptBytes);     } catch (NoSuchAlgorithmException e) {            e.printStackTrace();          return new Result(Result.CODE_EXCEPTION, "NoSuchAlgorithmException,没有找到该摘要算法");     } catch (NoSuchProviderException e) {         e.printStackTrace();          return new Result(Result.CODE_EXCEPTION, "NoSuchProviderException,没有找到该加密机");       }catch (InvalidKeyException | IllegalBlockSizeException | BadPaddingException | NoSuchPaddingException | InvalidCipherTextException e ) {         e.printStackTrace();          return new Result(Result.CODE_EXCEPTION, "文件加密失败:"+e.getMessage());        } }

  /**    *     * @param publicKey 公钥对象  * @param fileInput  文件输入流    * @return Result if(code== 200)success else fail       * encryptFileStr 加密后的文件字符串    * encryptKeyStr  加密后的秘钥字符串    * @throws IOException    */   public static Result fileEncrypt(PublicKey publicKey,InputStream fileInput)   {        ByteArrayOutputStream output = new ByteArrayOutputStream();      byte[] buffer = new byte[1024*4];        int n = 0;       try {            while (-1 != (n = fileInput.read(buffer))) {                output.write(buffer, 0, n);            }        } catch (IOException e) {         e.printStackTrace();      }     return fileEncrypt(publicKey,output.toByteArray());   }

  /**    * @param cert  证书对象  * @param file  文件    * @return Result if(code== 200)success else fail       * encryptFileStr 加密后的文件字符串    * encryptKeyStr  加密后的秘钥字符串    */   public static Result fileEncrypt(X509Certificate cert,File file)   {      try {         return fileEncrypt(cert,new FileInputStream(file));       } catch (FileNotFoundException e) {           e.printStackTrace();          return new Result(Result.CODE_ERROR_PARAM, "文件不存在:"+e.getMessage());       } }

  /**    *     * @param cert  证书对象  * @param fileInput  文件输入流    * @return Result if(code== 200)success else fail       * encryptFileStr 加密后的文件字符串    * encryptKeyStr  加密后的秘钥字符串    * @throws IOException    */   public static Result fileEncrypt(X509Certificate cert,InputStream fileInput)  {       return fileEncrypt(SM2CertUtil.getBCECPublicKey(cert),fileInput); }

  /**    * @param certStr  证书base64   * @param fileInput  文件输入流    * @return Result if(code== 200)success else fail       * encryptFileStr 加密后的文件字符串    * encryptKeyStr  加密后的秘钥字符串    * @throws IOException    */   public static Result fileEncrypt(String certStr,InputStream fileInput) {      try {        ByteArrayInputStream bais = new ByteArrayInputStream(Base64Utils.decode(certStr));           CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);           X509Certificate cert =  (X509Certificate) cf.generateCertificate(bais);          return fileEncrypt(cert,fileInput);        }catch (Exception e) {            e.printStackTrace();          return new Result(Result.CODE_EXCEPTION, "证书base64转换证书对象失败:"+e.getMessage());      } } /**    * @param certStr  证书base64   * @param filePath  文件路径  * @return Result if(code== 200)success else fail       * encryptFileStr 加密后的文件字符串    * encryptKeyStr  加密后的秘钥字符串    */   public static Result fileEncrypt(String certStr,String filePath){         return fileEncrypt(certStr,new File(filePath));   }

  /**    * @param certStr  证书base64   * @param file  文件    * @return Result if(code== 200)success else fail       * encryptFileStr 加密后的文件字符串    * encryptKeyStr  加密后的秘钥字符串    * @throws FileNotFoundException      * @throws IOException    */   public static Result fileEncrypt(String certStr,File file)  {     try {         return fileEncrypt(certStr,new FileInputStream(file));        } catch (FileNotFoundException e) {           e.printStackTrace();          return new Result(Result.CODE_ERROR_PARAM, "文件不存在:"+e.getMessage());       } }

  public static void main(String[] args) throws CertificateException, NoSuchProviderException, IOException, NoSuchAlgorithmException, InvalidKeySpecException {      Security.addProvider(new BouncyCastleProvider());        // FileInputStream bais = new FileInputStream("D:\\test.cer");      //CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);        // X509Certificate cert =  (X509Certificate) cf.generateCertificate(bais);       // String cert = "MIICzzCCAnSgAwIBAgIJAdInmr8fIJiNMAoGCCqBHM9VAYN1MIGPMQswCQYDVQQGEwJDTjEzMDEGA1UECgwq5rmW5Y2X5b6h56CB572R5o6n5L+h5oGv5oqA5pyv5pyJ6ZmQ5YWs5Y+4MQ4wDAYDVQQLDAVIVU5ZTTETMBEGA1UEAwwKSFVOQU5ZTVNNMjESMBAGA1UEBwwJ6ZW/5rKZ5biCMRIwEAYDVQQIDAnmuZbljZfnnIEwHhcNMjEwNzEyMDczMjMxWhcNNDEwNzA3MDczMjMxWjCBqDELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCea5luWNl+ecgTESMBAGA1UEBwwJ5bi45b635biCMTYwNAYDVQQKDC3muZbljZfnnIHmlbDlrZforqTor4HmnI3liqHkuK3lv4PmnInpmZDlhazlj7gxITAfBgNVBAsMGOW4uOW+t+W4gua1i+ivleS4k+eUqOeroDEWMBQGA1UEAwwNNDMwMzAxMDAwMzAwNDBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABOK7wKAe409JYZkd8tx6Ey6cb0OxeHZc1AG1TKrTiuM7ErQPFwPTRjkCrmnk19+xu4vZKuPR+KmYSOshoAIlm5+jgZ0wgZowHQYDVR0OBBYEFJbAkoS2vkJuuXZT+Gj0XMtEjBHwMB8GA1UdIwQYMBaAFJS9gxFrCotSpHOaUiZRiKVK6SPiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgO4MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATAYBgNVHREEETAPgg00MzAzMDEwMDAzMDA0MAoGCCqBHM9VAYN1A0kAMEYCIQCNBSkNdrrO0ZqZC6zwpDo7ZpWwr8PqkJdge8IEBgVjbQIhAIZHM5FZY+0Bb3Kui9ZaJr5eAZb83jGXpOGSpMCQUIr6";        String publicKeyStr = "MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/v8AAAAA//8wRAQg/v8AAAAA//wEICjp+p6dn140TVqeS89lCafzl4n1FauPkt28vUFNlA6TBEEEMsSuLB8ZgRlfmQRGajnJlI/jC7/yZgvhcVpFiTNMdMe8Nzai9PZ3nFm9zuNraSFT0KmHfMYqR0AC3zLlITnwoAIhAP7///9yA99rIcYFK1O79Ak51UEjAgEBA0IABMWwe7cKGGDCHWVCCmI195Ump1xqhZcXn7oYa23gNPUYs8vAxmC/nf7t+8Kq7Iq2KR5zlafOR5+Igs/BX4AkUkQ=";      X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64Utils.decode(publicKeyStr));        KeyFactory keyFactory = KeyFactory.getInstance("EC");      PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);         Result fileEncrypt = fileEncrypt(publicKey,new FileInputStream("C:\\Users\\Saxon\\Desktop\\Test.java"));       BufferedOutputStream bos = null;         FileOutputStream fos = null;         File file = null;         file = new File("d://test.java");          if (!file.getParentFile().exists()){              //文件夹不存在 生成              file.getParentFile().mkdirs();          }          fos = new FileOutputStream(file);          bos = new BufferedOutputStream(fos);          bos.write(fileEncrypt.getEncryptFileByte());          bos.close();          fos.close();        System.out.println(fileEncrypt); }}

  • 数字信封解密
数字信封解密
/**    *     * @param privateKey   私钥     * @param file 加密后的文件     * @param keyString   加密后的秘钥  */   public static void decrypt(PrivateKey privateKey,File file,String keyString) throws IOException, InvalidCipherTextException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException {     byte[] keyByte = Base64Utils.decode(keyString);      FileInputStream fileInputStream = new FileInputStream(file);     ByteArrayOutputStream output = new ByteArrayOutputStream();      byte[] buffer = new byte[4096];      int n = 0;       while (-1 != (n = fileInputStream.read(buffer))) {          output.write(buffer, 0, n);       }      byte[] byteArray = output.toByteArray();        //用私钥解密秘钥     byte[] key = SM2Util.decrypt((BCECPrivateKey)privateKey, keyByte);       byte[] decryptEcbPadding = Sm4Utils.decryptEcbPadding(key, byteArray);                //将解密后的文件输出到本地       OutputStream out = new FileOutputStream("D:\\bbb.txt");        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(decryptEcbPadding);     byte[] buff = new byte[1024];            int len = 0;         while((len=byteArrayInputStream.read(buff))!=-1){               out.write(buff, 0, len);          }         byteArrayInputStream.close();         out.close();  }

以上就是数字信封的加解密操作的全部内容, 想要代码中其他工具类的朋友可以加我微信或者访问我的gitee,所有的代码都在里面.

gitee地址: https://gitee.com/saxonkiku/encrypt_and_decrypt_file.git

SM2SM4实现字符串和文件的数字信封(小文件不支持超过堆内存的大文件)相关推荐

  1. SM2SM4实现字符串和文件的数字信封(不限制文件大小)

    相比于以前的实现方式,处理了文件超过堆内存限制的文件做数字信封.现在的支持任何大小的数字信封.速度的话基本上1G的文件加密在50s秒左右! 上期的数字信封SM4工具类如果文件太大会报 OutOfMem ...

  2. 附加的文件超过了服务器,将大文件附加到 Outlook 邮件或事件

    将大文件附加到 Outlook 邮件或事件 2021/8/12 本文内容 使用 Microsoft Graph API,可将最大 150 MB 的文件附加到 Outlook 邮件或 事件项目. 根据文 ...

  3. html大文件占用内存,[Flutter] 大文件上传之随传随处理(避免占用大量内存)

    今天碰到一个上传较大的视频文件到S3引发闪退的问题.经查此问题产生的原因是内存溢出,连个闪退日志都没有. 这个上传使用的是第三方的插件,我是用 uploadFileStream 来上传文件的,查看其实 ...

  4. Linux fs清理文件,linux找出已经删除但磁盘空间未释放的大文件并清空

    linux找出已经删除但磁盘空间未释放的大文件并清空 1.找出已经删除但磁盘空间未释放的文件 如果文件已经删除,但实际的磁盘空间未释放,这个时候文件句柄fd相关信息还在内存中,可以通过lsof命令找出 ...

  5. vue 文件及描述信息一起上传_用Vue实现一个大文件上传和断点续传

    前言 这段时间面试官都挺忙的,频频出现在博客文章标题,虽然我不是特别想蹭热度,但是实在想不到好的标题了-.-,蹭蹭就蹭蹭 :) 事实上我在面试的时候确实被问到了这个问题,而且是一道在线 coding ...

  6. Qt反射内存读取大文件

    近期写程序,需要对大文件进行读写操作,使用传统的QFile发现效率及其地下,于是想到了内存映射. QFile写文件: QFile f("c:\\test.txt"); if(!f. ...

  7. 哪里有免费大文件传输平台?通过这4个网站免费来进行大文件传输

    使用电子邮件发送大文件时,可能会遇到大小文件传输的限制.这四个免费大文件传输网站让大文件传输变得轻而易举.有许多大文件传输网站,但是通常您必须经过一些步骤才能使用它们,例如创建帐户,验证电子邮件地址或 ...

  8. PHP有限内存处理大文件(从两个文件提取相同行)

    面试题: 有两个文件文件,大小都超过了1G,一行一条数据,每行数据不超过500字节,两文件中有一部分内容是完全相同的,请写代码找到相同的行,并写到新文件中.PHP最大允许内内为256M. 解题步骤 遇 ...

  9. java里怎么实现播放文件_java程序,一步实现音乐文件的播放(小应用:听你想听)-nrg文件怎么播放...

    java学习分享 ~java完整代码如下~ package one; //包名随意 import java.awt.*; import java.applet.*; import java.awt.e ...

最新文章

  1. RANSAC算法原理与实现
  2. 【转】C#对象的深拷贝与浅拷贝
  3. 石川es6课程---5、函数-参数
  4. 【设计模式】中介者模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
  5. JavaScript对象的创建之动态原型方式
  6. linux命令解释程序实验,实验二 命令解释程序的使用
  7. 飘逸的python - 命令行漂亮的显示json数据
  8. 对datatable类型列名排序_表格数据的排序功能(支持多列)
  9. 13分钟,教你python可视化分析20W数据,找到妹子最爱的内衣
  10. 【笔记】VUE学习笔记
  11. windows c语言 sata 序列号,【Delphi】获取IDE/SATA硬盘序列号
  12. 学完python可以当黑客吗_想当黑客吗?我教你啊!精心整理最简单的黑客入门——PYTHON教程,免费系统又经典...
  13. dp动态规划解题套路 剑指offer 42连续子数组的最大和
  14. 组成计算机cpu的两大部件是,组成计算机的cpu的两大部分是什么
  15. Screeps入门: harvest,upgrader,builder初级自动化
  16. vb.net 生成随机数
  17. 140套高清、超优秀的PPT模板----毕业设计、毕业答辩主题
  18. win10 删除无用的bios引导
  19. 最浅显易懂kerberos认证和黄金白银票据
  20. windows中无法删除文件,报无法删除****,找不到指定文件,请确定指定的路径及文件名是否正确的解决

热门文章

  1. 桃园 更新完列表 不显示服务器,11月12日桃园等合服列表与规则
  2. linux解压zip文件命令
  3. 我所喜欢的女子    毕淑敏
  4. web大作业 静态网页 HTML+CSS+JavaScript橙色的时尚服装购物商城
  5. 6款精挑细选的黑科技APP,每一款都是极品黑科技
  6. 放假去哪里好玩?用python帮你分析
  7. 2021,“韭零后”的智商税涌向了哪里?
  8. linux自学笔记(二)
  9. 在公司如何防止监控上网记录
  10. html自动开门特效,15个超酷的CSS3代码特效展示