Java使用国密算法

这篇具有很好参考价值的文章主要介绍了Java使用国密算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java使用国密算法

什么是国密算法

国密算法是指 SM2 SM3 SM4 这3套含数据对称加解密,数据签名,数据非对称加解密功能的数据加密算法。其中 SM4 算法用于数据对称加密和解密;SM3算法用于计算数据的摘要签名;SM2算法用于数据 非对称加密和解密。
在政务行业的一些政务项目或产品中,会要求使用国密算法来替代 RSA,MD5,DES等算法。

在Java项目中使用国密算法

引入相关依赖

这里我使用的是jdk1.8 的maven项目,需要在pom.xml里引入以下依赖

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.8</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk15on</artifactId>
            <version>1.69</version>
        </dependency>

Java使用SM4算法对称加密解密

package cn.demo.sm;


import cn.hutool.core.date.StopWatch;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4;

public class SM4Test {
    /**
     * sm4 对称加密 ,需要1个加密key
     * @param args
     */
    public static void main(String[] args) {
        //SM4 requires a 128 bit key
        //需要一个长度为16的字符串 16*8=128 bit
        String key = RandomUtil.randomString(16);
        System.err.println("生成1个128bit的加密key:"+key);

        //原文
        String str = "hello";
        System.err.println("原文:"+str);

        StopWatch sw = StopWatch.create("q11");
        sw.start();

        SM4 sm41 = SmUtil.sm4(key.getBytes());
        //加密为Hex
        String hexPass = sm41.encryptHex(str);
        System.err.println("Hex形式的密文:"+hexPass);
        sw.stop();
        System.err.println(sw.getLastTaskInfo().getTimeSeconds());

        sw.start();
        //加密为base64
        String base64Pass = sm41.encryptBase64(str);
        System.err.println("base64形式的密文:"+base64Pass);
        sw.stop();
        System.err.println(sw.getLastTaskInfo().getTimeSeconds());

        System.err.println("--------------");
        //hex解密
        String s = sm41.decryptStr(hexPass);
        System.out.println(s);

        System.out.println("--------------");
        //base64解密
        String s2 = sm41.decryptStr(base64Pass);
        System.out.println(s2);
    }
}

测试结果

生成1个128bit的加密key:jsimjrby3wqb7dbq
原文:hello
Hex形式的密文:a18a4bbea96ca3103192d20650f8f190
1.19635956
base64形式的密文:oYpLvqlsoxAxktIGUPjxkA==
0.001947113
--------------
hello
--------------
hello

可以看出SM4加密需要1个128bit的加密key ,后面进行加密和解密都需要这个key。

SM4加密时有2种密文形式,一种是hex,一种是base64。

经测试发现SM4返回Hex形式的密文更耗时,所以建议开发中使用SM4返回base64形式的密文。

Java使用SM3算法计算数据的摘要签名

package cn.demo.sm;
import cn.hutool.crypto.SmUtil;

public class SM3Test {
    /**
     * sm3 摘要签名算法
     * @param args
     */
    public static void main(String[] args) {
        String str = "hello2023";
        /**
         * str重复执行sm3签名后的值 是相同的
         */
        String s = SmUtil.sm3(str);
        System.out.println(s);
    }
   
}    

测试结果

69f5c5c5413eaf9543b1e35ce6aa60d0eab217764e3f9d621e30785c8471e08f

可以看出SM3摘要签名算法 是可以重复执行,且多次执行结果一致的。

需要注意的是SM3 算法是不可逆的,只能从原文得到摘要签名,不能从摘要签名 反向得到原文,

这一点和MD5算法是相似的。

Java使用SM2算法进行非对称加密解密

package cn.demo.sm;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import java.io.*;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class SM2Utils {

    static final BouncyCastleProvider bc = new BouncyCastleProvider();

    public static Map<String,Object> generateKey(){
        KeyPair pair = SecureUtil.generateKeyPair("SM2");
        Map<String,Object> map = new HashMap<>();
        map.put("publicKey",pair.getPublic());
        map.put("privateKey",pair.getPrivate());
        return map;
    }

    public static String encrypt(String body, PublicKey aPublic){
        SM2 sm2 = SmUtil.sm2();
        sm2.setPublicKey(aPublic);
        String s = sm2.encryptBcd(body, KeyType.PublicKey);
        return s;
    }

    public static String decrypt(String data, PrivateKey privateKey){
        SM2 sm2obj = SmUtil.sm2();
        sm2obj.setPrivateKey(privateKey);
        String decStr = StrUtil.utf8Str(sm2obj.decryptFromBcd(data,KeyType.PrivateKey));
        return decStr;
    }


    /**
     * 从字符串中读取 私钥 key
     * @param privateKeyStr String
     * @return PrivateKey
     */
    public static PrivateKey strToPrivateKey(String privateKeyStr){
        PrivateKey privateKey = null;
        try {
            byte[] encPriv = Base64.decode(privateKeyStr);
            KeyFactory keyFact = KeyFactory.getInstance("EC", bc);
            privateKey = keyFact.generatePrivate(new PKCS8EncodedKeySpec(encPriv));

        }catch (Exception e){
            e.printStackTrace();
        }
        return privateKey;
    }

    /**
     * 从字符串中读取 公钥 key
     * @param publicKeyStr String
     * @return PublicKey
     */
    public  static PublicKey strToPublicKey(String publicKeyStr){
        PublicKey publicKey =  null;
        try {
            byte[] encPub = Base64.decode(publicKeyStr);
            KeyFactory keyFact = KeyFactory.getInstance("EC", bc);
            publicKey = keyFact.generatePublic(new X509EncodedKeySpec(encPub));
        }catch (Exception e){
            e.printStackTrace();
        }
        return publicKey;
    }


    /**
     * 公钥 key  转文件
     * @param publicKey PublicKey
     * @param path String
     */
    public static void exportPublicKey(PublicKey publicKey,String path){
        File file = new File(path);
        try {
            if (!file.exists()){
                file.createNewFile();
            }
            byte[] encPub = publicKey.getEncoded();
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(encPub);
            fos.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    /**
     * 私钥 key 转文件
     * @param privateKey PrivateKey
     * @param keyPath String
     */
    public static void exportPrivateKey(PrivateKey privateKey, String keyPath){
        File file = new File(keyPath);
        try {
            if (!file.exists()){
                file.createNewFile();
            }
            byte[]  encPriv = privateKey.getEncoded();
            FileOutputStream fos = new FileOutputStream(file);
            fos.write(encPriv);
            fos.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }


    public static PublicKey importPublicKey(String path){
        File file = new File(path);
        try {
            if (!file.exists()){
                return null;
            }
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[16];
            int size;
            while ((size = fis.read(buffer)) != -1){
                baos.write(buffer,0,size);
            }
            fis.close();
            byte[] bytes = baos.toByteArray();
            String publicKeyStr = Base64.encode(bytes);

            return strToPublicKey(publicKeyStr);
        }catch (IOException e){
            e.printStackTrace();
        }
        return null;
    }


    public static PrivateKey importPrivateKey(String keyPath){
        File file = new File(keyPath);
        try {
            if (!file.exists()){
                return null;
            }
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte buffer[] = new byte[16];
            int size;
            while ((size = fis.read(buffer)) != -1){
                baos.write(buffer,0,size);
            }
            fis.close();

            byte[]  bytes = baos.toByteArray();
            String privateKeyStr = Base64.encode(bytes);

            return strToPrivateKey(privateKeyStr);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}
package cn.demo.sm;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;

public class SM2Test {

    public static void test1(){
        String text = "测试aaaaaaaaa";

        SM2 sm2 = SmUtil.sm2();

        //第一种 使用随机密钥对
        String s = sm2.encryptBcd(text, KeyType.PublicKey);
        System.out.println(s);
        String s1 = StrUtil.utf8Str(sm2.decryptFromBcd(s, KeyType.PrivateKey));
        System.out.println(s1);
    }

    public static void test2(){
        String text = "测试aaaaaaaaa";

        System.err.println(text);

        //第二种  使用自定义密钥对
        KeyPair keyPair = SecureUtil.generateKeyPair("SM2");
        byte[] priKey = keyPair.getPrivate().getEncoded();
        byte[] pubKey = keyPair.getPublic().getEncoded();

        System.err.println("=====================================");
        SM2 sm2obj = SmUtil.sm2(priKey,pubKey);
        //公钥加密,私钥解密
        String encStr = sm2obj.encryptBcd(text,KeyType.PublicKey);
        System.err.println(encStr);

        String decStr = StrUtil.utf8Str(sm2obj.decryptFromBcd(encStr,KeyType.PrivateKey));
        System.err.println(decStr);
    }


    public static void main(String[] args) {
        //第一种 使用随机密钥对
//        test1();

        //第二种  使用自定义密钥对
//        test2();

        //第三种 生成pem文件,从pem文件里 读取 公钥 和 私钥,再进行 公钥加密,私钥解密
        test3();
    }

    /**
     * SM2非对称加密
     */
    public static void test3() {
        String text = "测试aaaaaaaaa";
        System.err.println(text);

        KeyPair pair = SecureUtil.generateKeyPair("SM2");

        PublicKey aPublic = pair.getPublic();
        PrivateKey aPrivate = pair.getPrivate();
        //公钥 key 和私钥 key 转文件
        SM2Utils.exportPublicKey(aPublic,"F:/sm2/public_key.pem");
        SM2Utils.exportPrivateKey(aPrivate,"F:/sm2/private_key.pem");

        //从pem文件里 读取 公钥 和 私钥
        PublicKey pubk2 = SM2Utils.importPublicKey("F:/sm2/public_key.pem");
        PrivateKey priK2 = SM2Utils.importPrivateKey("F:/sm2/private_key.pem");

        //公钥加密
        SM2 sm2 = SmUtil.sm2();
        sm2.setPublicKey(pubk2);
        String encStr = sm2.encryptBcd(text, KeyType.PublicKey);

        System.err.println(encStr);


        //私钥解密
        SM2 sm2obj = SmUtil.sm2();
        sm2obj.setPrivateKey(priK2);
        String decStr = StrUtil.utf8Str(sm2obj.decryptFromBcd(encStr,KeyType.PrivateKey));

        System.err.println(decStr);

    }

}

测试结果

测试aaaaaaaaa
04A278AAF9E455BAA2B09EA635DA71342ED507CC72F4D8E616D156BF378206CF1BC319146B863DA0C76784B1DC637E72BFA21D98A82169816AEF98B83F0F29AC97AC951FFF72300B64A9D438749C7F6D7AEFC7581D314CB01C9ABA96DD7591E0DF3990069E1BB8E7923B29B0F5FF12AD
测试aaaaaaaaa

SM2算法的加密和解密过程类似于RSA加解密。

可以看出SM2加密需要1个密钥对 ,后面进行加密和解密都需要这个密钥对,

这个密钥对可以分开保存成2个pem文件,

程序员可以从pem文件里 读取 公钥 和 私钥,再进行 公钥加密,私钥解密。文章来源地址https://www.toymoban.com/news/detail-494017.html

到了这里,关于Java使用国密算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 国密SM2算法(JS加密,C#、Java解密)

    常见的渗透测试会将网站登录时密码使用明文传输视为风险。推荐使用国密算法或者RSA算法对密码进行加密传输。 RSA加密(JS加密,C#、Java解密)请参考《RSA对称加密(JS加密,C#、Java解密)》​​​​​​ 本文描述国密SM2算法的实现。 一、工作原理 前端js使用公钥进行加密

    2024年02月02日
    浏览(43)
  • 国密算法:利用python进行sm2非对称算法的实现,国密算法库gmssl的使用

    我们继续来进行国密算法的演示。 本篇演示sm2非对称算法的实现,国密算法库gmssl的使用。 sm2: 即椭圆曲线公钥密码算法,是由国家密码管理局发布的; 非对称加密算法,即有一对不一样的密钥:公钥和私钥,公钥用来加密,私钥用来解密; 公钥和私钥:公钥,可以公开。

    2024年02月06日
    浏览(47)
  • 国密商用密码SM3杂凑算法原理分析与Java实现

    国密SM3算法是我国自研设计的商用密码杂凑算法,是在SHA-256的基础上进行改造的,其安全性与SHA-256相当。《SM3密码杂凑算法》于2010年12月份由国家密码管理局首次发布。后于2012年发布为密码行业标准《GM/T 0004-2012 SM3密码杂凑算法》,2016年发布为国家密码杂凑算法标准《GB

    2024年02月04日
    浏览(33)
  • RESTful 风格是指什么

    RESTful( Representational State Transfer )是一种基于 HTTP 协议的软件架构风格,用于设计网络应用程序的接口。它的设计理念是利用 HTTP 协议中的方法(如 GET、POST、PUT、DELETE 等)来对资源进行 CRUD ,使得客户端和服务器之间的通信变得简单、灵活和可扩展。 下面是 RESTful 风格的

    2024年02月21日
    浏览(32)
  • java运用SM4国密算法对文件的加密与解密的实现

    首先我们在idae开发工具导入导入pom.xml的两个必要依赖  jar包下载地址:百度网盘 请输入提取码   npn8  图上systemPath 为jar包的文件路径,我们需要使用以下的路径存储jar包。(也可以自己设置) java包的文件路径如图所示 然后创建所需要加密的文件 ,需要加密的文件内容,

    2024年03月27日
    浏览(31)
  • 国密算法(SM2)java语言的实现:利用bcprov库来实现SM2算法,非对称算法

    随着密码技术和计算机技术的发展,目前常用的1024位RSA算法面临严重的安全威胁,我们国家密码管理部门经过研究,决定采用SM2椭圆曲线算法替换RSA算法。 SM2是非对称加密算法; SM2是基于椭圆曲线密码的公钥密码算法标准; SM2是国密算法,用于替换RSA/DH/ECDSA/ECDH等国际算法

    2024年02月03日
    浏览(32)
  • 保护国家机密:Java国密加解密算法在信息安全中的应用与挑战

    目录 1、简介 1.1 信息安全的重要性 1.2 Java国密加解密算法的概述 2、Java国密加解密算

    2024年01月19日
    浏览(29)
  • java 国密算法工具类(支持SM2 SM3 SM4)

    前言 工具采用BC库实现,支持前后端加解密,前端建议使用sm-crypto 引入pom依赖 基本使用如下 国密SM2算法 国密SM3算法 国密SM4算法使用

    2024年02月13日
    浏览(34)
  • 云计算的云是指什么?最简单的解释是什么?

    云计算是指通过网络云将巨大的数据库逐渐分解成为几个小程序,再分别进行计算,将得出的计算结果及时反馈给客户,计算的时间是非常短的,但是精确度很高。虽然我们已经知道了什么是云计算,但具体云计算的云是指什么?最简单的解释是什么? 云计算的云是指什么?

    2024年02月12日
    浏览(26)
  • 国密算法SM2、SM3的使用

    1. SM2是非对称加密算法         它是基于椭圆曲线密码的公钥密码算法标准,其秘钥长度256bit,包含数字签名、密钥交换和公钥加密,用于替换RSA/DH/ECDSA/ECDH等国际算法。可以满足电子认证服务系统等应用需求,由国家密码管理局于2010年12月17号发布。 2.SM3是一种密码杂凑

    2024年02月06日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包