Java实现加密(六)国密SM2算法

news2024/9/22 9:40:56

目录

    • 一、SM2 简介
      • 1.1 概述
      • 1.2 国密与国际密的对应关系
      • 1.3 优势
      • 1.4 ECC加密算法 vs RSA加密算法
    • 二、SM2 应用场景
      • 2.1 数据加密
      • 2.2 密钥协商
      • 2.3 数字签名
    • 三、Java 实现 SM2 的两种方式
      • 3.1 Maven 依赖
      • 3.2 实现方式一
        • 1)SM2Utils.java
        • 2)SignatureSM2Util.java
        • 3)Param.java
        • 4)测试示例
        • 5)测试结果
      • 3.3 实现方式二
        • 1)SM2Utils.java
        • 2)SM2KeyPair.java
        • 3)测试示例
        • 4)测试结果
      • 3.4 两种实现方式比较
        • 第一种实现方式:
        • 第二种实现方式:
        • 比较:

一、SM2 简介

1.1 概述

SM2 算法是基于 ECC(Elliptic Curve Cryptography)椭圆曲线密码非对称加密 算法,其密钥长度为 256bit。该算法由 国家密码管理局 于 2010年12月17号发布

国密算法,即 国家商用密码算法。是由 国家密码管理局 认定和公布的密码算法标准及其应用规范,其中部分密码算法已经称为国际标准。如:SM系列 密码,SM 代表 商密,即商业密码,是指用于商业的、不涉及国家秘密的密码技术。

国密算法包括:SM1(SCB2)、SM2、SM3、SM4、SM7、SM9,以及 ZUC(祖冲之密码)等。

其中:

  • 1) SM1、SM4、SM7、ZUC(祖冲之密码)属于 对称算法
  • 2) SM2、SM9 属于 非对称算法
  • 3) SM3 属于 杂凑算法

1.2 国密与国际密的对应关系

加密方式 国密 国际密
对称加密 SM1 AES(Advanced Encryption Standard)
非对称加密 SM2 RSA(Ron Rivest、Adi Shamir、Leonard Adleman)三人姓氏首字母拼在一起
摘要算法(杂凑) SM3 MD5(Message-Digest Algorithm)
SHA系列(Secure Hash Algorithm)
对称加密 SM4 DES(Data Encryption Standard)

1.3 优势

SM2 算法作为一种自主创新的密码算法,具有以下优势:

  1. 安全性高: 基于 椭圆曲线离散对数难题,安全性比较高,能够有效地防止黑客攻击。
  2. 效率高: 具有较高地运算效率,能够满足大量数据加密、解密和数字签名的需求。
  3. 灵活性好: 支持多种密钥长度,可根据实际需求灵活选择密钥长度,适用于不同的应用场景。
  4. 自主创新: SM2算法是我国自主创新的密码算法,具有独立的只是产权,能够保障国家关键信息系统的信息安全。

1.4 ECC加密算法 vs RSA加密算法

SM2算法 是基于 ECC 椭圆曲线算法 实现的,采用 256位 密钥长度,它的安全强度相对较高,在工程应用中难以实现,破译或求解难度基本上是指数级的。因此,SM2 算法可以用较少的计算能力提供比 RSA算法 更高的安全强度,而所需的密钥长度却远比 RSA算法低。

对比项目 ECC加密算法 RSA加密算法
密钥长度 246位 2048位
CPU占用 较少 较高
内存占用 较少 较高
网络小号 较低 较高
加密效率 较高 一般
破解难度 具有数据特性,破解难度大 相对ECC理论上容易些
抗攻击性 一般
可扩展性 一般
兼容范围 支持新版浏览器和操作系统,单存在少数不支持平台,例如:cPanel 广泛支持

二、SM2 应用场景

2.1 数据加密

  • 在非对称加密算法中,可对外公布的密钥称为 公钥,只有持有者所知的密钥称为 私钥。发送者使用接收者的公钥来加密信息,接收者用自己的私钥解密和读取该信息。

使用 SM2 非对称加密算法加解密数据的过程:

2.2 密钥协商

利用 SM2 算法进行密钥协商的过程:

  • 1) 会话双方生成自己的私钥(随机数);

  • 2) 会话双方由私钥、ECC椭圆曲线参数 G 各自计算出公钥;

  • 3) 会话双方将自己的公钥传递给对方,传递过程公开;

    (由于椭圆曲线的计算复杂性高,破解难度大,因此攻击者难以通过公钥和椭圆曲线参数 G 反推出私钥)

  • 4) 双方将自己的 私钥 与对方的 公钥 进行运算,最终得到相同的会话密钥,该会话密钥可作为共享密钥用于对称加密(例如:SM4算法)通信。

2.3 数字签名

数字签名 是一种用于 验证信息完整性、真实性和来源的技术手段。它通常用于确保数据在传输或存储过程中没有被篡改,并且可以追溯到特定的发送方。

  • 发送方使用 自己的私钥 对信息进行 加密,生成数字签名。
  • 接收方使用 发送方的公钥 对签名进行 解密验证,以验证消息的完整性和真实性。

三、Java 实现 SM2 的两种方式

3.1 Maven 依赖

bouncycastle - 1.57 版本之后,加入了对我国的 SM2、SM3、SM4算法的支持

<!-- SM2加密 -->
<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.64</version>
</dependency>

3.2 实现方式一

1)SM2Utils.java
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.params.ParametersWithRandom;
import org.bouncycastle.crypto.signers.SM2Signer;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.*;

/**
 * 国密SM2算法工具类
 **/
@Slf4j
public class SM2Utils {
   
    private static final Charset CHARSETS = StandardCharsets.UTF_8;

    private static final SM2Engine.Mode DIGEST = SM2Engine.Mode.C1C3C2;

    /**
     * 私钥转换为 {@link ECPrivateKeyParameters}
     *
     * @param key key
     * @return
     * @throws InvalidKeyException
     */
    public static ECPrivateKeyParameters privateKeyToParams(byte[] key) throws InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException {
   
        if (key == null) {
   
            throw new RuntimeException("key must be not null !");
        }
        PrivateKey privateKey = generatePrivateKey(key);
        return (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(privateKey);
    }

    /**
     * 生成私钥
     *
     * @param key key
     * @return
     */
    public static PrivateKey generatePrivateKey(byte[] key) throws NoSuchAlgorithmException, InvalidKeySpecException {
   
        if (key == null) {
   
            throw new RuntimeException("key must be not null !");
        }
        KeySpec keySpec = new PKCS8EncodedKeySpec(key);
        return getKeyFactory().generatePrivate(keySpec);
    }

    /**
     * 公钥转换为 {@link ECPublicKeyParameters}
     *
     * @param key key
     * @return
     * @throws InvalidKeyException
     */
    public static ECPublicKeyParameters publicKeyToParams(byte[] key) throws InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException {
   
        if (key == null) {
   
            throw new RuntimeException("key must be not null !");
        }

        // 生成公钥
        KeySpec keySpec = new X509EncodedKeySpec(key);
        PublicKey publicKey = getKeyFactory().generatePublic(keySpec);
        return (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(publicKey);
    }

    /**
     * 获取{@link KeyFactory}
     *
     * @return {@link KeyFactory}
     */
    private static KeyFactory getKeyFactory() throws NoSuchAlgorithmException {
   
        final Provider provider = new BouncyCastleProvider();
        return KeyFactory.getInstance("EC", provider);
    }

    /**
     * 加密
     *
     * @param dataStr   数据
     * @param publicKey 公钥
     * @return 加密之后的数据
     */
    public static String encrypt(String dataStr, String publicKey) {
   
        try {
   
            return Base64.toBase64String(encrypt(dataStr.getBytes(StandardCharsets.UTF_8), Base64.decode(publicKey)));
        } catch (Exception e) {
   
            throw new RuntimeException("参数加密异常");
        }
    }

    public static byte[] encrypt(byte[] data, byte[] publicKey) throws Exception {
   
        CipherParameters pubKeyParameters = new ParametersWithRandom(publicKeyToParams(publicKey));
        SM2Engine engine = new SM2Engine(DIGEST);
        engine.init(true, pubKeyParameters);
        return engine.processBlock(data, 0, data.length);
    }


    /**
     * 解密
     *
     * @param base64Data       数据
     * @param base64PrivateKey 私钥
     * @return 解密之后的数据
     */
    public static String decrypt(String base64Data, String base64PrivateKey) throws Exception {
   
        byte[] data = Base64.decode(base64Data);
        byte[] privateKey = Base64.decode(base64PrivateKey);
        return new String(decrypt(data, privateKey), CHARSETS);
    }

    public static byte[] decrypt(byte[] data, byte[] privateKey) throws Exception {
   
        CipherParameters privateKeyParameters = privateKeyToParams(privateKey);
        SM2Engine engine = new SM2Engine(DIGEST);
        engine.init(false, privateKeyParameters);
        return engine.processBlock(data, 0, data.length);
    }

    /**
     * 签名
     *
     * @param data 数据
     * @return 签名
     */
    public static byte[] sign(byte[] data, byte[] privateKey) throws Exception {
   
        SM2Signer signer = new SM2Signer();
        CipherParameters param = new ParametersWithRandom(privateKeyToParams(privateKey));
        signer.init(true, param);
        signer.update(data, 0, data.length);
        return signer.generateSignature();
    }

    /**
     * 用公钥检验数字签名的合法性
     *
     * @param data      数据
     * @param sign      签名
     * @param publicKey 公钥
     * @return 是否验证通过
     */
    public static boolean verify(byte[] data, byte[] sign, byte[] publicKey) throws Exception {
   
        SM2Signer signer = new SM2Signer();
        CipherParameters param = publicKeyToParams

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2102850.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

界面控件DevExpress中文教程:如何使用AI扩展Excel计算?

DevExpress WinForms拥有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序&#xff0c;无论是Office风格的界面&#xff0c;还是分析处理大批量的业务数据&#xff0c;它都能轻松胜…

人工智能 | Mistral 大语言模型

Mistral AI Mistral AI team Mistral AI 是一家销售人工智能产品的法国公司。它由 Meta Platforms 和 Google DeepMind 的前员工于 2023 年 4 月创立。该公司于 2023 年 10 月筹集了 3.85 亿欧元&#xff0c;2023 年 12 月估值超过 20 亿美元 Mistral.AI 愿景与使命 我们是一…

Linux动态链接库

一、背景 我们使用Linux的过程中&#xff0c;例如安装程序或者部署一些如Python等&#xff0c;可能会遇到过如下动态链接库(共享库)报错: ImportError: libcrypto.so.10: cannot open shared object file: No such file or directory $"./lib/python3.8/lib/python3.8/ss…

同三维TM6-6 有线6级联会议麦克风详情介绍

同三维TM6-6 有线6级联会议麦克风 信息通讯类智能阵列麦克风 有线传输&#xff0c;强抗干扰、可级联、长续航、低延时 6个麦克风级联&#xff0c;通过3.5音频线级联, 可以同时使用3.5mm LINE IN/OUT、USB有线连接PC端&#xff0c;每条音频线是3米&#xff0c;可应用在视频会…

使用vscode编辑matlab完美解决方法

vscode里面的matlab插件都不好用&#xff0c;需要搭配互补一下 1先安装MATLAB 这个插件可以进行代码高亮、格式化、跳转&#xff0c;F5运行所有代码&#xff0c;或者选中要运行的代码&#xff0c;右键单独运行&#xff0c; 优点&#xff1a;运行速度很快&#xff0c;和matlab里…

idea新建父工程和添加导入新模块的步骤

如何在idea中新建一个父工程&#xff0c;然后在父工程下新建多个微服务模块&#xff1f; 一、新建父工程 1.1 新建New Project 1.2 删掉多余文件 创建好后&#xff0c;把多余的文件删掉&#xff0c;变成这样 1.3 修改pom文件 添加<packaging>pom</packaging>…

【Webpack】基本使用方法

参考视频&#xff1a; 30 分钟掌握 Webpack_哔哩哔哩_bilibili 什么是webpack 简单来说就是一个 打包工具&#xff0c; 可以将互相依赖的html、css、js以及图片字体等资源文件&#xff0c;经过处理打包成一个可执行的项目文件 &#x1f330;看例子 环境初始化 在需要使用…

ai智能写作助手批量生成文章,提升工作效率!

在当今快节奏的工作环境中&#xff0c;时间就是金钱&#xff0c;效率就是生命。对于需要大量产出文章的工作者来说&#xff0c;如何在有限的时间内创作出高质量的内容&#xff0c;成为了一个亟待解决的问题。而AI智能写作助手的出现&#xff0c;为这一问题提供了解决方案。本文…

godot开发初体验

点击加号可以创建一个新的场景 点击其它节点可以添加节点 想对某个节点添加子节点可以右键这个节点,然后点击添加子节点 在左下角的文件系统中,可以右键某个场景,并将其设置为主场景,主场景作为程序的入口 点击项目->项目设置-> 输入映射,可以添加一个新的动作,在添加新动…

游戏应用|空地模型实景融合,还原《黑神话:悟空》游戏场景

古色斑驳&#xff0c;巍峨险峻&#xff0c;是历史的低语&#xff0c;诉说着千百年的沧桑与辉煌&#xff1b;飞檐翘角&#xff0c;雕梁画栋&#xff0c;凝聚着时代的文明与智慧。在数字化浪潮下&#xff0c;我们利用实景三维技术&#xff0c;翻开了中华古建筑这本伟大的史诗。 P…

快速入门Go:Go + gin + MongoDB

Go 进阶:Go + gin + MongDB 极速搭建EcommerceSys电商系统 前言 本章节适合有一定基础的 Golang 初学者,通过简单的项目实践来加深对 Golang 的基本语法和 Web 开发的理解。 本文章持续更新中,请关注… 项目结构 项目流程图 技术栈(待补充)项目结构项目路由 (待补充) …

合宙LuatOS开发板Core_Air780EP使用说明

Core-Air780EP 开发板是合宙通信推出的基于 Air780EP 模组所开发的&#xff0c; 包含电源&#xff0c;SIM卡&#xff0c;USB&#xff0c;天线&#xff0c;音频等必要功能的最小硬件系统。 以方便用户在设计前期对 Air780EP模块进行性能评估&#xff0c;功能调试&#xff0c;软…

zeus病毒应急响应

目录 介绍步骤 介绍 Zeus病毒&#xff0c;也叫Zbot病毒&#xff0c;是一种具有高潜伏性的木马病毒&#xff0c;受影响系统为微软Windows&#xff0c;主要被用来盗窃用户银行信息。 Zeus最早于2007年被发现&#xff0c;当时它被用来盗取美国某公司的资料信息。到2009年&#x…

科技赋能,览尽千年:高科技解锁博物馆沉浸式探索!

近日&#xff0c;第十届中国博物馆及相关产品与技术博览会&#xff08;简称“博博会”&#xff09;在呼和浩特市敕勒川国际会展中心圆满落幕。 “博博会”上&#xff0c;智能化、数字化技术成为了展览的一大亮点。虚拟现实&#xff08;VR&#xff09;、增强现实&#xff08;AR…

计算机电脑共享文件和打印机共享问题:“计算机无法访问!您可能没有权限使用网络资源。请与这台服务器的管理员联系以查明您是否有访问权限。”解决办法

在Win10系统中&#xff0c;我们在访问局域网共享文件或计算机共享打印机的时候会出现“你可能没有权限使用网络资源 ”。请与这台服务器的管理员联系以查明你是的提示&#xff0c;很多用户不知道如何解决&#xff0c;下面就把正确的解决方法分享给大家&#xff0c;你可能没有权…

【数据结构篇】~链表算法题2

链表算法题2 1.返回倒数第k个节点思路解析 2.链表的回文结构​思路解析1&#xff08;空间复杂度不符合&#xff09;解析2 3.相交链表​思路解析 1.返回倒数第k个节点 OJ链接 思路 有点像高中学的相对位移 利用快慢指针&#xff0c;开始时都指向头节点&#xff0c;然后让快指…

redis之地理空间geo实战以及选项详解

redis之地理空间geo实战以及选项详解 Redis GEO Redis GEO 主要用于存储地理位置信息&#xff0c;并对存储的信息进行操作&#xff0c;该功能在 Redis 3.2 版本新增。 Redis GEO 操作方法有&#xff1a; geoadd&#xff1a;添加地理位置的坐标。 geopos&#xff1a;获取地理…

【时时三省】(C语言基础)指针进阶6

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省 例题1&#xff1a; sizeof(数组名)&#xff0d;数组名表示整个数组的&#xff0d;计算的是整个数组的大小 &数组名&#xff0d;数组名表示整个数组&#xff0c;取出的是整个数组的地址 …

SprinBoot+Vue宠物领养救助微信小程序的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue3.6 uniapp代码 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平…

Windows如何恢复已删除文件?电脑数据恢复完整指南!

无论你是要释放磁盘空间还是因为其他原因删除或误删重要文件或文件夹后&#xff0c;现在一定想知道怎么还原。其实不用担心&#xff0c;在你删除文件时&#xff0c;你的电脑并没有完全删除它们&#xff0c;只是将它们标记为已删除&#xff0c;等待新数据覆盖。所以你还有很多方…