国密算法—SM2介绍及基于BC的实现

国密算法—SM2介绍及基于BC的实现

简介

SM2密码算法是一种椭圆(非对称)密码算法

  • 加密强度:256位(私钥长度);
  • 公私钥长度:公钥长度为64字节(512位),私钥32字节(256位);
  • 支持签名最大数据量及签名结果长度:最大签名数据量长度无限制;签名结果为64字节(但由于签名后会做ASN.1编码,实际输出长度为70-72字节);
  • 支持加密最大数据量及加密后结果长度:支持最大近128G字节数据长度;加密结果(C=C1C3C2)增加96字节【C1(64字节) + C3(32字节)】(如果首个字节为0x04则增加97字节,实际有效96字节)
私钥

SM2私钥是一个大于1且小于n-1的整数(n为SM2算法的阶,其值参见GM/T 0003),简记为k,长度为256位(32字节)。

公钥

SM2公钥是SM2曲线上的一个点,由横坐标和纵坐标两个分量来表示,记为(x,y),简记为Q,每个分量的长度为256位,总长度为512位(64字节,不包含公钥标识)。

数据格式
密钥数据格式
私钥数据格式

SM2算法私钥数据格式的ASN.1定义为:

SM2PrivateKey::=INTEGER
公钥数据格式

SM2算法公钥数据格式的ASN.1定义为:

SM2PublicKey::=BIT STRING

SM2PublicKey为BIT STRING类型,内容为04||X|||Y,其中X和Y分别标示公钥的x分量和y的分量,其长度各位256位。04用来标示公钥为非压缩格式(压缩格式用02标识)。

加密数据格式

SM2算法加密后的数据格式的ASN.1定义为:

SM2Cipher::= SEQENCE{
  XCoordinate		INTEGER,					--x 分量 32字节(256位)
  YCoordinate		INTEGER,					--y 分量 32字节(256位)
  HASH				OCTET STRING SIZE(32),	 	--杂凑值 32字节(256位)
  CipherText		OCTET STRING 				--密文   等于明文长度	
}

其中,HASH为使用SM3算法对明文数据运算得到的杂凑值,其长度固定为256位。CipherText是与明文等长的密文。因此SM2加密后的密文长度比明文长度增加了97字节(1字节04标识 + 32字节x分量 + 32字节y分量 + 32字节Hash

签名数据格式

SM2算法签名数据格式的ASN.1定义为:

SM2Signature::={
	R		INTEGER,	--签名值的第一部分 32字节(256位)
	S		INTEGER		--签名值的第二部分  32字节(256位)
}

R和S的长度各位32字节。因此签名后的数据长度为固定的64字节

计算过程
生成密钥

SM2密钥生成是指生成SM2算法的密钥对的过程,该密钥对包括私钥与之对应的公钥。其中,私钥长度为256位,公钥长度为512位。

  • 输入

  • 输出

    k SM2PrivateKey SM2私钥 256位

    Q SM2PublicKey SM2公钥 512位

详细计算过程参见GM/T 0003

加密

SM2加密是指使用指定的公开密钥对明文进行特定的加密计算,生成相应密文的过程。该密文只能由该指定公开密钥对应的私钥解密。

  • 输入

    Q SM2PublicKey SM2公钥

    m 字节串 待加密的明文数据

  • 输出

    c SM2Cipher 密文

其中:

  1. 输出参数c的格式由本规范7.2中定义;

  2. 输出参数c中的XCoordinateYCoordinate俗称C1)为随机产生的公钥的x分量和y分量256位;

  3. 输出参数c中的HASH俗称C3)的计算公式为HASH = SM3(x||m||y),其中,x,y为公钥Q的x分量和y分量;

  4. 输出参数c中的CipherText俗称C2)为加密密文,其长度等于明文长度。

详细的计算过程参见GM/T 0003GM/T 0004

解密

SM2解密是指使用指定的私钥对密文进行解密计算,还原对应明文的过程。

  • 输入

    d SM2PrivateKey SM2私钥

    c SM2Cipher 密文

  • 输出

    m 字节串 与密文对应的明文

m为SM2Cipher经过解密运算得到明文,该明文的长度与输入参数c中的CipherText(俗称C2)的长度相同。

详细的计算过程参见GM/T 0003

预处理
预处理1

预处理1是指使用签名方的用户身份标识和签名方公钥,通过运算得到Z指的过程。Z值用于预处理2,也用于SM2密钥协商协议。

  • 输入

    ID 字节串 用户身份标识

    Q SM2PublicKey 用户的公钥

  • 输出

    Z 字节串 预处理1的输出

计算公式为:

Z = SM3(ENTL||ID||a||b||XG||yG||XA||yA)

其中:

  • ENTL 为由2个字节标示的ID的比特长度;
  • ID 为用户身份标识;
  • a、b 为系统曲线参考;
  • XG、yG 为基点;
  • XA、yA 为用户公钥;

详细计算过程参见GM/T 0003GM/T 0004

预处理2

预处理2是指使用Z值和待签名消息,通过SM3运算得到的杂凑值H的过程。杂凑值H用于SM2数字签名。

  • 输入

    Z 字节串 预处理2的输入

    M 字节串 待签名消息

  • 输出

    H 字节串 杂凑值

计算公式为:

H = SM3(Z||M)

详细计算过程参见GM/T 0003GM/T 0004

数字签名

SM2签名是指使用预处理的结果和签名者的私钥,通过签名计算得到签名结果的过程。

  • 输入

    d SM2Privatekey 签名者私钥

    H 字节串 预处理2的结果

  • 输出

    sign SM2Signature 签名值

详细计算过程参见GM/T 0003

签名验证

SM2签名验证是指使用预处理2的结果、签名值和签名者的公钥。通过验签计算确定签名是否通过验证的过程。

  • 输入

    H 字节串 预处理2的结果

    sign SM2Signature 签名值

    Q PublicKey 签名者的公钥

  • 输出

    :表示验证通过;为:表示验证不通过

详细计算过程参见GM/T 0003

Java基于BC实现SM2加解密

BouncyCastle在1.57版本已经提供对SM椭圆曲线密码算法的支持,不过对SM2仅提供C1C2C3模式的加解密。在1.62+版本中已经增加了对C1C3C2模式加解密的支持。

 public enum Mode
    {
   
   
        C1C2C3, C1C3C2;
    }

这里使用BouncyCastle 1.68版本进行测试

@SpringBootTest
class DemoApplicationTests {
   
   
  
   @Test
    void contextLoads() {
   
   
        testSM2();
    }
  
   static void testSM2() {
   
   
        String publicKeyHex = null;
        String privateKeyHex = null;
        KeyPair keyPair = createECKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        if (publicKey instanceof BCECPublicKey) {
   
   
            //获取65字节非压缩缩的十六进制公钥串(0x04)
            publicKeyHex = Hex.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值