国密SM2算法密钥派生函数KDF的实现

前段时间需要实现国密算法SM2的签名、验签、加密、解密等功能,加解密过程使用到的密钥派生函数(KDF),从网上搜到的代码不符合《GMT 0003.4-2012 SM2椭圆曲线公钥密码算法 》的规定,不能直接使用,没法满足项目需要,后来决定自行实现,整理如下,欢迎大家讨论:

密钥派生函数算法逻辑

《GMT 0003.4-2012 SM2椭圆曲线公钥密码算法 》中 关于 密钥派生函数的规定如下:

密钥派生函数

密钥派生函数的C语言实现

代码实现:

//函数名称:my_KDF
//函数功能:实现国密SM2加解密算法中的密钥派生函数kdf
//输入参数:cdata      -用于计算的数据串(二进制值)
//        datalen    -内容长度
//        keylen     -需要派生得到的长度
//输出参数:retdata    -计算后返回的内容(二进制值),分配空间至少为需要keylen
//返回值:int 0表示成功,其他表示失败
int my_KDF(const char* cdata, int datalen, int keylen, char* retdata)
{
    int nRet = -1;
    unsigned char *pRet;
    unsigned char *pData;

    if(cdata==NULL || datalen<=0 || keylen<=0)
    {
        goto err;
    }

    if(NULL == (pRet=(unsigned char *)malloc(keylen)))
    {
        goto err;
    }

    if(NULL == (pData=(unsigned char *)malloc(datalen+4)))
    {
        goto err;
    }

    memset(pRet,  0, keylen);
    memset(pData, 0, datalen+4);

    unsigned char cdgst[32]={0}; //摘要
    unsigned char cCnt[4] = {0}; //计数器的内存表示值
    int nCnt  = 1;  //计数器
    int nDgst = 32; //摘要长度

    int nTimes = (keylen+31)/32; //需要计算的次数
    int i=0;
    memcpy(pData, cdata, datalen);
    for(i=0; i<nTimes; i++)
    {
        //cCnt
        {
            cCnt[0] =  (nCnt>>24) & 0xFF;
            cCnt[1] =  (nCnt>>16) & 0xFF;
            cCnt[2] =  (nCnt>> 8) & 0xFF;
            cCnt[3] =  (nCnt    ) & 0xFF;
        }
        memcpy(pData+datalen, cCnt, 4);
        sm3(pData, datalen+4, cdgst);

        if(i == nTimes-1) //最后一次计算,根据keylen/32是否整除,截取摘要的值
        {
            if(keylen%32 != 0)
            {
                nDgst = keylen%32;
            }
        }
        memcpy(pRet+32*i, cdgst, nDgst);

        i    ++;  //
        nCnt ++;  //
    }

    if(retdata != NULL)
    {
        memcpy(retdata, pRet, keylen);
    }

    nRet = 0;
err:
    if(pRet)
        free(pRet);
    if(pData)
        free(pData);

    return nRet;
}
  • 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
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79

特别说明:代码中 sm3( ) 为 国密算法中的 密码杂凑算法sm3,已有前辈共享了实现代码,直接拿来使用,请自行搜索。

示例数据1: 
输入数据 cdata : 00000000000000000000000000000000, 
派生长度keylen:32, 
返回内容retdata:2744A6D84E20D493696906799924577BEF6E900E40629D55F2D9677C825D64B2

示例数据2: 
输入数据 cdata : 11223344556677881122334455667788, 
派生长度keylen:32, 
返回内容retdata:7EA06CE33DE666F0DDABFD22F6FA57F843059CA717F712150E2ACCC71F82317B

阅读更多
换一批

没有更多推荐了,返回首页