加密机 国密算法 实现逻辑 代码演示

严重声明:本文章只做技术讲解,不会涉及商业机密,如有侵权,请联系本人删除!

概要

        随着信息安全意识的提升,国密算法在保障数据安全方面发挥着至关重要的作用。当前趋势下,国内大部分加密机厂商均已国产算法代替了国际算法,这些厂商包括江南科友、网御星云、天融信、三未信安、山东得安、卫士通、山东渔翁、无锡江南、江南天安、江南博仁、兴唐通信、中安网脉、君众甲匠、立思辰、江南信安、山东确信、信安世纪等等。此前博主已经写了很多关于国密算法SM2、SM3、SM4的代码实现,涵盖了多种开发语言之前的互通,有兴趣的可以点击主页查看置顶博客。
        再次声明,博主没有加密机的任何源码,均以伪代码代替,本篇博客主要演示讲解java代码如何实现与加密机的交互,基于1.64版本的bc算法包(其他版本可以参考博主另外一篇博客做升级降级处理,传送门java bcprov 国密 依赖 jar包 版本 升级 降级 教程),包含加密机主要功能接口,其他开发语言可以参考我之前的博客进行调整。

主要功能接口

1、生成非对称密钥

1.1、介绍

        调用加密机的生成非对称密钥对接口,不同厂商的接口ID不一样,此处不列举接口ID。该功能接口需要指定一个密钥名称,然后返回明文hex格式公钥(不同加密机厂商可能返回编码格式有区别),密文hex格式私钥(安全性),类似于java中bcprov算法包中ECKeyPairGenerator类的generateKeyPair方法,该方法得到的AsymmetricCipherKeyPair对象,从中可以获取ECPublicKeyParameters公钥值和ECPrivateKeyParameters私钥值,再转换成hex模式。

1.2、java代码演示

        生成密钥的代码博主在之前的代码中演示过,传送门java国密 C#国密 golang国密 NodeJS国密汇总(一),需要注意的是加密机的接口返回的明文公钥前面的标志位04大概率是去掉了的

import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.ECKeyGenerationParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;

import java.security.SecureRandom;

public class Sm2KeyPair {
   
    public static void main(String[] args) {
   
        // 初始化
        ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
        keyGen.init(new ECKeyGenerationParameters(Sm2Params.SM2_DOMAIN_PARAMETERS, new SecureRandom()));
        // 生成
        AsymmetricCipherKeyPair tempPair = keyGen.generateKeyPair();
        // 获取对象
        ECPublicKeyParameters pubParameters = (ECPublicKeyParameters) tempPair.getPublic();
        ECPrivateKeyParameters pvkParameters = (ECPrivateKeyParameters) tempPair.getPrivate();
        // 获取值
        byte[] privateKeyBytes = pvkParameters.getD().toByteArray();
        ECPoint q = pubParameters.getQ();
        byte[] publicKeyBytes = q.getEncoded(false);

        // 转换格式
        String privateKeyHex = Hex.toHexString(privateKeyBytes);
        System.out.println("java privateKeyHex -->" + privateKeyHex);
        String publicKeyHex = Hex.toHexString(publicKeyBytes);
        System.out.println("java publicKeyHex -->" + publicKeyHex);
        // 生成结果
        // java privateKeyHex -->00cc5ed0948826adb773cafd4b7514f5ff35ef05bd6374f07007049fec62bca144
        // java publicKeyHex  -->04b5ce6fb3a4cb301b4d06f4d53a0995caf8cbdb269af30f38868a39390139daba8f1c0daab5d73c7a0de9ed02986bb404196d035005958203abd1dc9eab7c345e
        
        // 加密机接口伪代码,根据具体情况自行调整
        // String keyName = "test";
        // String response = 加密机.生成非对称密钥(keyName);
    }
}

2、导入公钥

2.1、介绍

        这个接口主要功能是把第三方的公钥灌入加密机,也就是上一章节中生成出来的公钥导入加密机,私钥自己留存,然后根据后续业务场景再调用签名接口或者数字信封接口(下面章节会依次讲解)。请求报文中主要上送密钥名称和hex格式公钥值,响应成功或失败相关信息。

2.2、java代码演示
        // 加密机接口伪代码,根据具体情况自行调整
        // String keyName = "test";
        // String publicKey = "去掉04标志位的hex字符串";
        // String response = 加密机.导入公钥(keyName, publicKey);

3、数字信封数据加密、解密

3.1、介绍

        加密这个接口主要功能是使用对称密钥sm4Key对报文msg加密得到msgBySm4,然后使用非对称密钥sm2Key对对称密钥sm4Key加密得到sm4KeyBySm2,其中非对称密钥sm2Key就是1.2章节中生成的公钥,对称密钥sm4Key是加密机自动生成。请求报文中主要上送密钥名称、待加密的明文,响应报文中包含密文msgBySm4和密文密钥sm4KeyBySm2。解密反之,不再赘述。

3.2、java代码演示

        此前博主分别在两篇博文中演示了sm4对称加密和sm2非对称加密,传送门java国密 C#国密 golang国密 NodeJS国密汇总(四)java国密 C#国密 golang国密 NodeJS国密汇总(二)。这里演示融合后的代码。
        请仔细阅读注释和伪代码。

import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.engines.SM4Engine;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.util.BigIntegers;
import org.bouncycastle.util.encoders.Hex;

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;

public class DETest {
   
    public static void main(String[] args) {
   
        // 私钥(标志位00)
        String privateKeyHex = "00cc5ed0948826adb773cafd4b7514f5ff35ef05bd6374f07007049fec62bca144";
        // 公钥(自己使用时候,需要加上标志位04)
        String publicKeyHex = "04b5ce6fb3a4cb301b4d06f4d53a0995caf8cbdb269af30f38868a39390139daba8f1c0daab5d73c7a0de9ed02986bb404196d035005958203abd1dc9eab7c345e";

        // 明文
        String msg = "hello";

        // 数字信封加密开始

        // 加密前明文填充,PKCS7Padding,如果使用其他工具类,则无需下面这些繁琐的过程
        byte[] input = msg
  • 31
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

九二战歌

原创不易,尽量不白瓢

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值