SM3国密算法标准中两个实例的实现

来源于CSDN博客:https://blog.csdn.net/ErErFei/article/details/50998162
代码新增内容:在原博客的基础上,整合了各个类的方法,同时增添了SM3国密标准中的第二个案例的验证,并尝试将原代码中的缓冲区长度修改为64*2,本代码作者是在命令行里面运行通过的,未曾在eclipse环境中运行。如有运行问题,请各位能够反馈,互相学习;

public class ren_SM3
{
/**IV为256比特初始值,32个字节,修饰为静态最终变量,不可改变,比如0x80值(128)范围超过byte表示范围(-128~127),所以需要强制转换*/
private static final byte[] IV = { 0x73, (byte)0x80, 0x16, 0x6f, 0x49, 0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7, (byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30, (byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3, (byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte)0xfb, (byte)0x0e, 0x4e };

/**由于IV不可改变,而在64次迭代过程中需要一个不断改变的V,所以重新定义一个。*/
private byte[] V= IV.clone();

/** SM3分组长度 */
private static final int BLOCK_LENGTH = 64;

/** 缓冲区长度 */
private static final int BUFFER_LENGTH = BLOCK_LENGTH * 2;

/*缓冲区偏移量*/
private int xBufOff;

/*缓冲区,缓冲区长度是64,这个缓冲区指的什么?指的明文进入内存后,算法中要求需要将消息进行512比特分组,
然后对每组进行迭代,由于对消息原文是不能有改变的,所以需要将分组后的消息进行复制一份。*/
private byte[] xBuf = new byte[BUFFER_LENGTH];

private int cntBlock = 0;//用于记录明文分组的个数,计算消息长度时需要用到。

public static int[] Tj = new int[64];

static
{
    for (int i = 0; i < 16; i++)
    {
        Tj[i] = 0x79cc4519;
    }

    for (int i = 16; i < 64; i++)
    {
        Tj[i] = 0x7a879d8a;
    }
}
/*
*@param in明文输入缓冲区
*@param inOff明文输入缓冲区偏移量
*@param len明文输入长度
*/
public void update(byte[] in,int inOff)
{

    int inputLen = in.length;//明文的长度
    int dPos = inOff;//明文输入缓冲区偏移量,一开始是0
    if(BUFFER_LENGTH<inputLen)//如果缓冲区长度小于明文长度
    {
        System.arraycopy(in,dPos,xBuf,0,BUFFER_LENGTH);
        inputLen =  inputLen - BUFFER_LENGTH;//明文输入长度减去进入缓冲区后剩下的长度
        dPos = dPos+ BUFFER_LENGTH;
        doUpdate();
        while(inputLen>BUFFER_LENGTH)
        {
            System.arraycopy(in,dPos,xBuf,0,BUFFER_LENGTH);
            inputLen = inputLen - BUFFER_LENGTH;
            dPos = dPos+BUFFER_LENGTH;
            doUpdate();
        }
    }
    if(inputLen>0)
    {
        System.arraycopy(in,dPos,xBuf,0,inputLen);
        xBufOff = inputLen;
    }
}
public void doUpdate()//将缓冲区的内容复制到一份新的字节数组中。然后对字节数组作用。
{
    byte [] B = new byte[BLOCK_LENGTH];
    for(int i=0;i<BUFFER_LENGTH;i=i+BLOCK_LENGTH)
        {
            System.arraycopy(xBuf,i,B,0,BLOCK_LENGTH);
            doHash(B);
        }
    xBufOff=0;
}
private void doHash(byte[] B)
{
    V = CF(V,B);
    //System.arraycopy(tmp,0,V,0,V.length);

    cntBlock++;
}
private byte[] CF(byte[] V,byte[] B)
{
    int[] v,b;
    v = convert(V);
    b = convert(B);
    return convert(CF(v,b));
}
private int[] convert(byte[] arr)
{
    int[] out = new int[arr.length/4];
    byte[] tmp = new byte[4];
    for(int i =0;i<arr.length;i+=4)
        {
            System.arraycopy(arr,i,tmp,0,4);
            out[i/4]=bigEndianByteToInt(tmp);
        }
        return out;
}
private int bigEndianByteToInt(byte[] in)
{
    int num = 0;
    int temp;
    temp = (0x000000ff & (in[3])) << 0;
    num = num | temp;
    temp = (0x000000ff & (in[2])) << 8;
    num = num | temp;
    temp = (0x000000ff & (in[1])) << 16;
    num = num | temp;
    temp = (0x000000ff & (in[0])) << 24;
    num = num | temp;
    return num;
}
public int[] CF(int[] v,int[] n)
{
    int a,b,c,d,e,f,g,h;
    int ss1,ss2,tt1,tt2;
    a = v[0];
    b=v[1];
    c=v[2];
    d=v[3];
    e=v[4];
    f=v[5];
    g=v[6];
    h=v[7];
    System.out.println(getHexString(bigEndianIntToByte(a))+getHexString(bigEndianIntToByte(b))+" "
                      +getHexString(bigEndianIntToByte(c))+getHexString(bigEndianIntToByte(d))+" "
                      +getHexString(bigEndianIntToByte(e))+getHexString(bigEndianIntToByte(f))+" "
                      +getHexString(bigEndianIntToByte(g))+getHexString(bigEndianIntToByte(h)));
    int[][]arr = expand(n);
    int []W=arr[0];
    int []W1 = arr[1];
    System.out.println("扩展后W[]的值为:");
    for(int j =0;j<68;j++)
    {
        System.out.print(getHexString(bigEndianIntToByte(W[j]))+" ");
        if((j+1)%8==0)
            System.out.println();
    }
    System.out.println();
    System.out.println("扩展后W1[]的值为:");
    for(int j =0;j<64;j++)
    {
        System.out.print(getHexString(bigEndianIntToByte(W[j]))+" ");
        if((j+1)%8==0)
            System.out.println();
    }
    System.out.println();
    for(int j =0;j<64;j++)
    {
        ss1 = bitCycleLeft(a,12)+e+bitCycleLeft(Tj[j],j%32);
        ss1 = bitCycleLeft(ss1,7);
        ss2 = ss1^bitCycleLeft(a,12);
        tt1 = FFj(a,b,c,j)+d+ss2+W1[j];
        tt2 = GGj(e,f,g,j)+h+ss1+W[j];
        d=c;
        c = bitCycleLeft(b,9);
        b=a;
        a = tt1;
        h=g;
        g=bitCycleLeft(f,19);
        f=e;
        e=P0(tt2);
        System.out.println(j+":  "+getHexString(bigEndianIntToByte(a))+getHexString(bigEndianIntToByte(b))+" "
                          +getHexString(bigEndianIntToByte(c))+getHexString(bigEndianIntToByte(d))+" "
                          +getHexString(bigEndianIntToByte(e))+getHexString(bigEndianIntToByte(f))+" "
                          +getHexString(bigEndianIntToByte(g))+getHexString(bigEndianIntToByte(h)));
    }
    int []out = new int[8];
    out[0] = a^v[0];
    out[1] = b^v[1];
    out[2] = c^v[2];
    out[3]= d^v[3];
    out[4] = e^v[4];
    out[5] = f^v[5];
    out[6] = g^v[6];
    out[7] = h^v[7];
    return out;
}
public int[][] expand(int[] b)
{
    int []W =new int[68];
    int[] W1 = new int[64];
    for(int i=0;i<16;i++)
    {
        W[i] = b[i];
    }
    for(int i =16;i<68;i++)
    {
    W[i] = P1(W[i-16]^W[i-9]^bitCycleLeft(W[i-3],15))^bitCycleLeft(W[i-13],7)^W[i-6];
    }
    for(int i =0;i<64;i++)
    {
        W1[i] = W[i]^W[i+4];
    }
    int[][] arr = new int[][]{W,W1};
    return arr;
}
public int bitCycleLeft(int target,int bitLen)
{
    byte[] tmp = bigEndianIntToByte(target);
    int byteLen = bitLen/8;
    int len = bitLen%8;
    if(byteLen>0)
    {
        tmp = byteCycleLeft(tmp,byteLen);
    }
    if(len>0)
    {
        tmp = bitSmall8CycleLeft(tmp,len);
    }
    return bigEndianByteToInt(tmp);
}
public byte[] bigEndianIntToByte(int n)
{
    byte[] tmp = new byte[4];
    tmp[3] = (byte)(n>>0);
    tmp[2] = (byte)(n>>8);
    tmp[1] = (byte)(n>>16);
    tmp[0] = (byte)(n>>24);
    return tmp;
}
public byte[] byteCycleLeft(byte[] in,int n)
{
    byte[] tmp = new byte[in.length];
    System.arraycopy(in, n, tmp, 0, in.length - n);
    System.arraycopy(in, 0, tmp, in.length - n, n);
    return tmp;
}
public byte[] bitSmall8CycleLeft(byte[] in,int n)
{
    byte[] tmp = new byte[in.length];
    int t1, t2, t3;
    for(int j=0;j<tmp.length;j++)
    {
        t1 = (byte)((in[j])<<n);
        t2 = (byte)(((in[(j+1)%tmp.length])&0x000000ff)>>(8-n));
        t3 = (byte)(t1|t2);
        tmp[j]=(byte)t3;
    }
    return tmp;
}
public int FFj(int a,int b ,int c,int j)
{
    if(j>=0&&j<=15)
    {
        return a^b^c;
    }
    else
    {
        return (a&b)|(a&c)|(b&c);
    }
}
public int GGj(int a,int b ,int c,int j)
{
    if(j>=0&&j<=15)
    {
        return a^b^c;
    }
    else
    {
        return (a&b)|(~a&c);
    }
}
public int P0(int a)
{
    int tmp = a^bitCycleLeft(a,9)^bitCycleLeft(a,17);
    return tmp;
}
public int P1(int a)
{
    int tmp = a^bitCycleLeft(a,15)^bitCycleLeft(a,23);
    return tmp;
}
public byte[] convert(int[] v)
{
    byte[] out = new byte[v.length*4];
    int[] in = new int[v.length];
    for(int i=0;i<v.length;i++)
    {
        System.arraycopy(v,0,in,0,v.length);
        out[4*i+3] = (byte)(in[i]>>0);
        out[4*i+2] = (byte)(in[i]>>8);
        out[4*i+1] = (byte)(in[i]>>16);
        out[4*i+0] = (byte)(in[i]>>24);
    }
    return out;
}
public byte[] doFinal()
{
    byte[] B= new byte[BLOCK_LENGTH];
    byte[] buffer = new byte[xBufOff];
    System.arraycopy(xBuf,0,buffer,0,buffer.length);
    byte[] tmp = padding(buffer,cntBlock);
    for(int i=0;i<tmp.length;i+=64)//此处填充后tmp长度可能为64*2,也可能为64
    {
        System.arraycopy(tmp,i,B,0,B.length);
        doHash(B);
    }

    return V;
}
/*
*@param in需要填充的最后一组字节数组
*@param blen消息的分组次数
*return 填充后的字节数组,注意当填充前数组为64字节时,填充后数组会比原来多一组。
*/
public byte[] padding(byte[] in,int blen)
{
    long l= blen*BUFFER_LENGTH*8+in.length*8;
    int k = 448-(in.length*8+8)%512;
    if(k<0)
    {
        k= 960-(in.length*8+8)%512;
    }
    byte[] padd=new byte[k/8+1];
    padd[0]=(byte)0x80;
    byte[] out = new byte[in.length+k/8+1+64/8];
    int pos = 0;
    System.arraycopy(in,0,out,pos,in.length);
    pos = pos+in.length;
    System.arraycopy(padd,0,out,pos,k/8+1);
    pos = pos+k/8+1;
    byte[] tmp = longToBytes(l);
    System.arraycopy(tmp,0,out,pos,64/8);
    return out;
}
public byte[] longToBytes(long n)
{
    byte[] bytes = new byte[8];
    for(int i=0;i<8;i++)
    {
        bytes[7-i] = (byte)(0xff&(n>>(i*8)));
    }
    return bytes;
}
public String getHexString(byte[] bt)
{
    String str = "";
    for(int i = 0;i<bt.length;i++)
    {

        str+=String.format("%02x",bt[i]&0xff);
        if(i%4==3)
            str+=" ";
    }
    return str;
}
public static void main(String[] args)
{
            byte[] md = new byte[32];
    byte[] msg1 = {0x61,0x62,0x63};
            ren1_SM3 sm3 = new ren1_SM3();
            sm3.update(msg1, 0);
            md = sm3.doFinal();
    System.out.println("第一个例子的摘要值为"+sm3.getHexString(md));
    byte[] msg2 = {0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
                    0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
                    0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,
                    0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64,0x61,0x62,0x63,0x64};
    ren1_SM3 sm3_1 = new ren1_SM3();
    sm3_1.update(msg2, 0);
            md = sm3_1.doFinal();
    System.out.println("第二个例子的摘要值为"+sm3_1.getHexString(md));
}

}

原文地址:https://www.cnblogs.com/xpren/p/11392045.html

时间: 2024-08-29 22:05:26

SM3国密算法标准中两个实例的实现的相关文章

嵌入式设备中支持国密算法的方法

如今国密系列算法的应用已不仅仅局限于金融和电信等领域,诸如车载设备,消费类电子设备等越来越多的产品开始要求有国密算法的支持.但是国密算法的开源资料和应用案例少之又少,如何快速高效的在自己的设备中加入国密算法已经成为众多开发者必须要面对的难题.现在为大家准备了一个系列文章,介绍嵌入式设备中移植国密算法的方法.简单来说,分为三种方法:1.移植Miracl库2.移植Openssl库3.使用加密芯片下面进行简介:1.移植Miracl库MIRACL(Multiprecision Integer and R

嵌入式设备中支持国密算法的方法(二)

上一篇文章中我们为大家介绍了嵌入式设备中支持国密算法的几种方法.本篇我们详细的介绍一下第一种方法:移植Miracl库的具体操作步骤.第一步 获取源码MIRACL密码库是开源软件,可以直接到官网下载,也可在csdn等论坛中获取.第二步 利用MIRACL库函数实现SM2算法实现sm2的功能需要用到MIRACL库中的36个源文件,例如mraes.c.mrec2.c.mrarth0.c.mrcore.c.mrshs.c.mezzn2.c.mrxgcd.c.mrgcm.c.mrio1.c等.然后需要新建一

嵌入式设备中支持国密算法的方法(三)

本篇文章是介绍国密算法在嵌入式设备中应用方法系列文章的第三篇,介绍移植openssl库到嵌入式设备中的具体方法,当然最终的目的还是使我们的设备能支持国密算法.同上一篇文章中介绍的miracl密码库相比,openssl库的应用更加广泛,资料支持度更好,但是代码体量要大于miracl库.需要再次说明的是,同miracl库一样,openssl的库也并不能直接提供国密算法的接口,我们是利用库中相应的API接口(如椭圆曲线等)来构建自己的国密算法,下面我们具体介绍移植的步骤.第一步 获取库作为应用广泛的开

国密算法SM2证书制作

国密算法sm2非对称算法椭圆曲线 原文:http://www.jonllen.cn/jonllen/work/162.aspx 前段时间将系统的RSA算法全部升级为SM2国密算法,密码机和UKey硬件设备大都同时支持RSA和SM2算法,只是应用系统的加解密签名验证需要修改,这个更改底层调用的加密动态库来,原来RSA用的对称加密算法DES(AES)和摘要MD5(SHA1)也相应改变,分别对应SM1.SM3算法,SM1算法基于硬件实现,SM2.SM3算法已公开. SM2签名验证算法 SM2签名同样也

国密算法的ekey的使用--简述

一.龙脉GMTools的使用 1.产品介绍 mToken GM3000 国密身份认证锁是龙脉科技自主研发设计支持国密算法.完全遵照国家密码管理局颁布的<智能IC卡及智能密码钥匙密码应用接口规范>要求设计的USB Key,采用国产高性能智能卡芯片,内置SSF33.SM1.SM2.SM3.SM4等国产算法,支持高速数据国密算法加解密,提供CSP以及PKCS11和国密接口,完全符合国家密码管理局关于"密钥不落地"的技术规范要求,是电子政务.电子军务.CA厂商首选的USB Key产

国密算法的ekey基本使用的说明

概述 本次需要进行的实验研究是国密算法的ekey的使用.对于一个或者多个应用来说,每个应用可以包含一个或多个容器(Container),每个容器中可以存放两对分别用于加密和签名的密钥对,以及两个相应的证书或证书链.每一个容器只能为ECC或RSA一种类型,一个容器中不能混用ECC密钥和RSA密钥.根据个人的理解,ekey的作用就是生成容器,将需要加密的消息或文件利用相应的加密算法加密后,生成证书,将证书导入ekey的容器中.这样以便于在其他终端上用到该文件时,使用ekey,其容器中的对应的证书可以

国密算法

算法分类 国密即国家密码局认定的国产密码算法.主要有SM1,SM2,SM3,SM4.密钥长度和分组长度均为128位. SM1 为对称加密.其加密强度与AES相当.该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用. SM2为非对称加密,基于ECC.该算法已公开.由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA.ECC 256位(SM2采用的就是ECC 256位的一种)安全强度比RSA 2048位高,但运算速度快于RSA. SM3 消息摘要.可以用MD5作为对比理解.该算法已公

2017-2018-2 20179204《网络攻防实践》第十三周学习总结 python实现国密算法

国密商用算法是指国密SM系列算法,包括基于椭圆曲线的非对称公钥密码SM2算法.密码杂凑SM3算法.分组密码SM4算法,还有只以IP核形式提供的非公开算法流程的对称密码SM1算法等. 第1节 SM2非对称密码算法原理 国密SM2算法是商用的ECC椭圆曲线公钥密码算法,其具有公钥加密.密钥交换以及数字签名的功能.椭圆曲线参数并没有给出推荐的曲线,曲线参数的产生需要利用一定的算法产生.但在实际使用中,国密局推荐使用素数域256 位椭圆曲线,其曲线方程为y^2= x^3+ax+b.参数如下: 其中p是大

自己封装的openssl+国密算法的C++接口

Digest #ifndef _DIGESTCALC_H #define _DIGESTCALC_H /********************************** /* 使用示例:(sm3算法) /* DigestCalc hashcl; /* hashcl.Init(DigestCalc::alg_id::sm3); /* hashcl.Update(in,inl); /* vector<unsigned int> out(hashcl.GetHashLength()); /* h