使用 Java Bouncy Castle实现国密算法SM4、SM3以及SM2的加密

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

国密算法的实现借助了Java库函数 Bouncy Castle,加密库安装使用教程请参考链接

SM4

简介

SM4,又称为商密算法,是一种分组密码算法,于2012年由中国密码技术研究中心(中国密码学会成员)发布,目前已成为我国国家密码算法,并在多个领域得到了广泛的应用。SM4算法采用了32轮迭代结构,密钥长度为128位,分组长度为128位,支持ECB、CBC等多种分组模式,在安全性、效率和适用性上都得到了良好的平衡。SM4算法具有高速度、高安全性、硬件实现简单等特点,可以在多种安全场景中使用,比如对称加密、消息认证码等方面。同时,SM4算法已经经过了严格的国际标准测试,成为ISO/IEC 18033-4标准。

注意:代码加解密对象为文件,测试时请自行替换

代码

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import java.security.Security;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class SM4 {
    private static final String name="SM4";                               //算法名字
    private static final String transformation="SM4/CBC/PKCS5Padding";    //加密模式以及短快填充方式
    private static final String Default_iv="0123456789abcdef";            //加密使用的初始向量

/**
 * 加载指定文件,对其进行加密,并将加密结果写入指定输出文件中
 * @param inputFile 要加密的输入文件路径
 * @param outputFile 加密后的输出文件路径
 * @param key 加密所需的密钥
 * @throws Exception 如果文件读取、加密或写入时出现错误,则抛出异常
 */
private static void encodeFile(String inputFile, String outputFile, String key) throws Exception {
    // 读取输入文件中的所有字节
    byte [] inputBytes = Files.readAllBytes(Paths.get(inputFile));
    // 对输入字节数组进行加密
    byte [] encodeByte = encode(inputBytes, key.getBytes(StandardCharsets.UTF_8));
    // 将加密后的字节数组写入指定输出文件中
    Files.write(Paths.get(outputFile),encodeByte);
    System.out.println("File encoded successfully.");
}
    /**
     * 使用指定的加密算法和密钥对给定的字节数组进行加密
     * @param inputByte 要加密的字节数组
     * @param key 加密所需的密钥
     * @return 加密后的字节数组
     * @throws Exception 如果加密时发生错误,则抛出异常
     */
    public static byte [] encode(byte [] inputByte, byte [] key) throws Exception {
        // 获取加密实例
        Cipher c = Cipher.getInstance(transformation);
        // 根据密钥的字节数组创建 SecretKeySpec
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, name);
        // 创建 IvParameterSpec 对象,使用默认向量和字符集
        IvParameterSpec ivParameterSpec = new IvParameterSpec(Default_iv.getBytes(StandardCharsets.UTF_8));
        // 初始化加密实例
        c.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
        // 返回加密后的字节数组
        return c.doFinal(inputByte);
    }

    public static void decodeFile(String inputFilePath, String outputFilePath, String key) throws Exception {
        byte[] inputBytes = Files.readAllBytes(Paths.get(inputFilePath));
        byte[] decodeBytes = decode(inputBytes, key.getBytes(StandardCharsets.UTF_8));
        Files.write(Paths.get(outputFilePath), decodeBytes);
        System.out.println("File decode successfully.");
    }



    private static byte[] decode(byte[] inputBytes, byte[] key) throws Exception {
        Cipher cipher = Cipher.getInstance(transformation);
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, name);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(Default_iv.getBytes(StandardCharsets.UTF_8));
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
        return cipher.doFinal(inputBytes);
    }

    public static void main(String[] args) throws Exception {
        Security.addProvider(new BouncyCastleProvider());
        String inputFile="Test.txt";              //需要加密的文件
        String enFile="Encode.txt";               //加密后的文件
        String deFile="Decode.txt";               //解密后的文件
        String key="0123456789ABCDEF";            //加密密钥,注意必须是128bits,即16个字节
        encodeFile(inputFile,enFile,key);
        decodeFile(enFile,deFile,key);


    }
}

结果(部分截图)

Test.txt

java sm4,国密算法,java,开发语言

Encode.txt

java sm4,国密算法,java,开发语言

Decode.txt

java sm4,国密算法,java,开发语言

SM3

简介

SM3是一种国家密码算法,也称为商用密码算法,是我国的一种哈希函数,用于信息安全领域。它基于Merkle–Damgård结构,采用了与SHA-256类似的位操作,并且设计了一个可调节的消息扰动函数。SM3保证了生日攻击下的安全强度,并提供了碰撞和预图攻击的防护。

代码

import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.util.encoders.Hex;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class SM3Test {
    /**
     * 使用SM3算法计算给定输入的摘要值
     * @param inputBytes 要进行摘要计算的输入字符串
     * @return 给定输入的摘要值
     */
    private static byte[] calculateSM3Digest( byte [] inputBytes) {
        //创建 SM3Digest 对象
        SM3Digest digest = new SM3Digest();
        //将输入字符串转为字节数组,并使用该字节数组更新摘要对象的内部状态,以便进行计算
       // byte[] inputBytes = input.getBytes();
        digest.update(inputBytes, 0, inputBytes.length);
        //创建一个输出字节数组,调用 doFinal 方法完成哈希计算,并将结果存入输出数组
        byte[] output = new byte[digest.getDigestSize()];
        digest.doFinal(output, 0);
        //返回摘要字节数组
        return output;
    }
    public static void main(String[] args) {
        String filePath = "src/Test.java";
        try {
           
            byte [] inputBytes = Files.readAllBytes(Paths.get(filePath));
            byte[] digest = calculateSM3Digest(inputBytes);
            String hexDigest = Hex.toHexString(digest);
            System.out.println("SM3 Digest: " + hexDigest);
        } catch (IOException e) {
            System.out.println("An error occurred while reading the file: " + e.getMessage());
        }
    }
    
}

结果

java sm4,国密算法,java,开发语言

SM2

简介

SM2是一种我国的国家密码算法,采用基于椭圆曲线密码学的公钥密码体制,在数字签名、密钥协商、密钥交换和公钥加密场景中可广泛使用。其密钥长度为256位,安全等级高于普遍采用的RSA或DSA算法。在SM2算法中,密钥交换、数字签名和公钥加密均采用同一种椭圆曲线和同一种哈希算法,具有自主知识产权、高效率和安全性高等特点。并且SM2算法已经成为国际标准ISO/IEC 14888-3并得到了广泛应用。

代码



public class SM2 {

    public SM2(){ }
    static {  //加载BC驱动
        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null)
            new BouncyCastleProvider();
    }

    // 生成sm2密钥对
    public KeyPair createECKeyPair() {
        //使用标准名称创建EC参数生成的参数规范
        final ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");

        // 获取一个椭圆曲线类型的密钥对生成器
        final KeyPairGenerator kpg;
        try {
            kpg = KeyPairGenerator.getInstance("EC", new BouncyCastleProvider());
// 使用SM2算法域参数集初始化密钥生成器(默认使用最高优先级安装的提供者的 SecureRandom 的实现作为随机源)
            // kpg.initialize(sm2Spec);
            // 使用SM2的算法域参数集和指定的随机源初始化密钥生成器
            kpg.initialize(sm2Spec, new SecureRandom());
            // 通过密钥生成器生成密钥对
            return kpg.generateKeyPair();

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

    /*
     *公钥加密
     * @param publicKey SM2公钥
     * @param data      明文数据
     * @param modeType  加密模式
     * @return          密文数据
     */
    public byte[] encode(String publicKeyHex, byte[] inputBytes, int modeType){
        //加密模式
        //
        BCECPublicKey publicKey = getECPublicKeyByPublicKeyHex(publicKeyHex);
        SM2Engine.Mode mode;
        if (modeType == 1) {//采用新模式加密标准
            mode = SM2Engine.Mode.C1C3C2;
        } else {//采用旧模式加密标准
            mode = SM2Engine.Mode.C1C2C3;
        }
        //通过公钥对象获取公钥的基本域参数。
        ECParameterSpec ecParameterSpec = publicKey.getParameters();
        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
                ecParameterSpec.getG(), ecParameterSpec.getN());
        //通过公钥值和公钥基本参数创建公钥参数对象
        ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(publicKey.getQ(), ecDomainParameters);
        //根据加密模式实例化SM2公钥加密引擎
        SM2Engine sm2Engine = new SM2Engine(mode);
        //初始化加密引擎
        sm2Engine.init(true, new ParametersWithRandom(ecPublicKeyParameters, new SecureRandom()));

        byte[] arrayOfBytes = null;
        try {
            //通过加密引擎对字节数串行加密
            arrayOfBytes = sm2Engine.processBlock(inputBytes, 0, inputBytes.length);
        } catch (Exception e) {
            System.out.println("SM2加密时出现异常:" + e.getMessage());
            e.printStackTrace();
        }
        return arrayOfBytes;
    }
    /**
     * 私钥解密
     *
     * @param privateKeyHex  SM私钥
     * @param cipherBytes 密文数据
     * @param modeType 加密模式
     * @return           解密后的明文
     */
    public static byte[] decode(String privateKeyHex, byte[] cipherBytes, int modeType) {
        //解密模式
        SM2Engine.Mode mode;
        BCECPrivateKey privateKey = getBCECPrivateKeyByPrivateKeyHex(privateKeyHex);
        if (modeType == 1) {
            mode = SM2Engine.Mode.C1C3C2;
        } else {
            mode = SM2Engine.Mode.C1C2C3;
        }

        //通过私钥对象获取私钥的基本域参数。
        ECParameterSpec ecParameterSpec = privateKey.getParameters();
        ECDomainParameters ecDomainParameters = new ECDomainParameters(ecParameterSpec.getCurve(),
                ecParameterSpec.getG(), ecParameterSpec.getN());

        //通过私钥值和私钥基本参数创建私钥参数对象
        ECPrivateKeyParameters ecPrivateKeyParameters = new ECPrivateKeyParameters(privateKey.getD(),
                ecDomainParameters);

        //通过解密模式创建解密引擎并初始化
        SM2Engine sm2Engine = new SM2Engine(SM2Engine.Mode.C1C3C2);
        sm2Engine.init(false, ecPrivateKeyParameters);

        byte[] arrayOfBytes = null;
        try {
            //通过解密引擎对密文字节串进行解密
            arrayOfBytes = sm2Engine.processBlock(cipherBytes, 0, cipherBytes.length);
        } catch (Exception e) {
            System.out.println("SM2解密时出现异常" + e.getMessage());
        }
        return arrayOfBytes;
    }


    //椭圆曲线ECParameters ASN.1 结构
    private static X9ECParameters x9ECParameters = GMNamedCurves.getByName("sm2p256v1");
    //椭圆曲线公钥或私钥的基本域参数。
    private static ECParameterSpec ecDomainParameters = new ECParameterSpec(x9ECParameters.getCurve(), x9ECParameters.getG(), x9ECParameters.getN());

    /**
     * 公钥字符串转换为 BCECPublicKey 公钥对象
     *
     * @param pubKeyHex 64字节十六进制公钥字符串(如果公钥字符串为65字节首字节为0x04:表示该公钥为非压缩格式,操作时需要删除)
     * @return BCECPublicKey SM2公钥对象
     */

    public static BCECPublicKey getECPublicKeyByPublicKeyHex(String pubKeyHex) {
        //截取64字节有效的SM2公钥(如果公钥首字节为0x04)
        if (pubKeyHex.length() > 128) {
            pubKeyHex = pubKeyHex.substring(pubKeyHex.length() - 128);
        }
        //将公钥拆分为x,y分量(各32字节)
        String stringX = pubKeyHex.substring(0, 64);
        String stringY = pubKeyHex.substring(stringX.length());
        //将公钥x、y分量转换为BigInteger类型
        BigInteger x = new BigInteger(stringX, 16);
        BigInteger y = new BigInteger(stringY, 16);
        //通过公钥x、y分量创建椭圆曲线公钥规范
        ECPublicKeySpec ecPublicKeySpec = new ECPublicKeySpec(x9ECParameters.getCurve().createPoint(x, y), ecDomainParameters);
        //通过椭圆曲线公钥规范,创建出椭圆曲线公钥对象(可用于SM2加密及验签)
        return new BCECPublicKey("EC", ecPublicKeySpec, BouncyCastleProvider.CONFIGURATION);
    }

    /**
     * 私钥字符串转换为 BCECPrivateKey 私钥对象
     *
     * @param privateKeyHex: 32字节十六进制私钥字符串
     * @return BCECPrivateKey:SM2私钥对象
     */
    public static BCECPrivateKey getBCECPrivateKeyByPrivateKeyHex(String privateKeyHex) {
        //将十六进制私钥字符串转换为BigInteger对象
        BigInteger d = new BigInteger(privateKeyHex, 16);
        //通过私钥和私钥域参数集创建椭圆曲线私钥规范
        ECPrivateKeySpec ecPrivateKeySpec = new ECPrivateKeySpec(d, ecDomainParameters);
        //通过椭圆曲线私钥规范,创建出椭圆曲线私钥对象(可用于SM2解密和签名)
        return new BCECPrivateKey("EC", ecPrivateKeySpec, BouncyCastleProvider.CONFIGURATION);
    }

    public static void main(String[] args) throws Exception {
        String Sm4Key="0123456789abcdef";
        String sm2PublicKeyHex=null;
        String sm2PrivateKeyHex=null;

        SM2 sm2=new SM2();
        // 生成SM2密钥
        KeyPair keyPair = sm2.createECKeyPair();
        PrivateKey privateKey = keyPair.getPrivate();
        PublicKey publicKey = keyPair.getPublic();
        if (publicKey instanceof BCECPublicKey){
            //获取65字节非压缩的十六进制公钥串(0x04)
            byte[] publicKeyBytes = ((BCECPublicKey) publicKey).getQ().getEncoded(false);
            sm2PublicKeyHex = Hex.toHexString(publicKeyBytes);

        }
        if (privateKey instanceof BCECPrivateKey) {
            //获取32字节十六进制私钥串
            sm2PrivateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);

        }
        //Sm2加密密钥
        byte [] keyBytes=Sm4Key.getBytes("utf-8");
        byte[] encodeBytes = sm2.encode(sm2PublicKeyHex, keyBytes, 1);
        String encodeKey = Hex.toHexString(encodeBytes);
        //Sm2解密密钥
        byte [] decodeBytes=sm2.decode(sm2PrivateKeyHex,encodeBytes,1);
        String deKey=new String(decodeBytes,"utf-8");
        System.out.println("\ninitial key:"+Sm4Key+"\nencode key:"+encodeKey+"\ndecode key:"+deKey);
        System.out.println("complete!");
    }
}

结果

java sm4,国密算法,java,开发语言文章来源地址https://www.toymoban.com/news/detail-586345.html

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

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

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

相关文章

  • Python实现国家商用密码算法sm2/sm3/sm4/sm9(国密)

    2010 年开始,我国国家密码管理局就已经开始陆续发布了一系列国产加密算法,这其中就包括 SM1、SM2、SM3 、SM4、SM7、SM9、ZUC(祖冲之加密算法)等,SM 代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。SM1 和 SM7 的算法不公开,其余算法都已成为 ISO/IEC

    2024年02月15日
    浏览(48)
  • react+vue 前端国密算法sm2、sm3 、sm4的js ts实现

    1. 简单介绍下SM2 和 SM3 SM2 算法:是一种公钥加密算法,它的密钥长度为 256 位,安全性较高。可用于数字签名、密钥协商等场景。 SM3 算法:是一种对称加密算法,用于消息摘要和数字签名等场景。它的密钥长度为 256 位,安全性较高。SM3 算法与 SM2 算法相互配合,提高了整体

    2024年01月19日
    浏览(41)
  • 国密算法概述、及算法的集成应用(sm2、sm3、sm4)

    由于项目的需求,需要集成国密加解密,于是对国密又温故知新了一遍。同时整理了一下国密的一些算法。 本文主要从国密相关算法的简介、应用系统的集成、工具类的封装等方面入手,对国密进行深入的学习。 为了保障商用密码的安全性,国家密码局制定了一系列密码标

    2024年02月14日
    浏览(72)
  • 新手入门 | 掌握国密算法:新手指南: SM2 / SM3 / SM4密码算法详解

    在密码学领域,有多种加密与签名算法,它们在信息安全领域发挥着举足轻重的作用。如今,随着互联网的快速发展,网络安全已经成为各类信息系统完整性、可用性、保密性的重要保障,越来越多的国产密码算法得到了广泛的应用与关注。在本文中,我们将重点介绍三个经

    2024年02月12日
    浏览(157)
  • 前端国密加解密使用方法SM2、SM3、SM4

       国密算法,即国家商用密码算法。是由国家密码管理局认定和公布的密码算法标准及其应用规范,其中部分密码算法已经成为国际标准。如SM系列密码,SM代表商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。      不多废话直接上干货 项目中 可能存在

    2023年04月09日
    浏览(51)
  • vue普通加密以及国密SM2、SM3、sm4的使用

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

    2023年04月09日
    浏览(44)
  • 国密商用密码SM3杂凑算法原理分析与Java实现

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

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

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

    2024年03月27日
    浏览(54)
  • 国密算法SM2、SM3的使用

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

    2024年02月06日
    浏览(47)
  • 国密算法SM2/3/4简单比较,以及基于Java的SM4(ECB模式,CBC模式)对称加解密实现

    常用的国密算法包含SM2,SM3,SM4。以下针对每个算法使用场景进行说明以比较其差异 SM2:非对称加密算法,可以替代RSA 数字签名,SM2为非对称加密,加解密使用一对私钥和公钥,只有签名发行者拥有私钥,可用于加密,其他需要验证解密或验签者使用公钥进行。如果使用公

    2024年04月13日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包