当前位置:   article > 正文

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

keypairgeneratorspi sm4

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

概要

        随着信息安全意识的提升,国密算法在保障数据安全方面发挥着至关重要的作用。当前趋势下,国内大部分加密机厂商均已国产算法代替了国际算法,这些厂商包括江南科友、网御星云、天融信、三未信安、山东得安、卫士通、山东渔翁、无锡江南、江南天安、江南博仁、兴唐通信、中安网脉、君众甲匠、立思辰、江南信安、山东确信、信安世纪等等。此前博主已经写了很多关于国密算法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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

2、导入公钥

2.1、介绍

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

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

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/647272
推荐阅读
相关标签
  

闽ICP备14008679号