跳到主要内容

ZUC 128-EIA3 例子

构建

构建 Tongsuo 时需要开启 ZUC 算法,例如:

./config enable-zuc

示例程序

使用 EVP 接口的代码示例如下:

#include <stdio.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>

int main(int argc, char *argv[])
{
EVP_MD_CTX *mctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *pkey = NULL;
unsigned char *got = NULL;
size_t got_len;
char *mac;
int rv;
const char key[] = {
0xc9, 0xe6, 0xce, 0xc4, 0x60, 0x7c, 0x72, 0xdb,
0x00, 0x0a, 0xef, 0xa8, 0x83, 0x85, 0xab, 0x0a
};
/*
* EIA3 的 iv 只有5个字节(只用到38bit),不是随机构造,构造方法如下:
* |----------32bit----------|-----5bit-----|---1bit---|
* | count | bearer | direction|
*/
const char *iv = "a94059da54";
const char msg[] = {
0x98, 0x3b, 0x41, 0xd4, 0x7d, 0x78, 0x0c, 0x9e,
0x1a, 0xd1, 0x1d, 0x7e, 0xb7, 0x03, 0x91, 0xb1,
0xde, 0x0b, 0x35, 0xda, 0x2d, 0xc6, 0x2f, 0x83,
0xe7, 0xb7, 0x8d, 0x63, 0x06, 0xca, 0x0e, 0xa0,
0x7e, 0x94, 0x1b, 0x7b, 0xe9, 0x13, 0x48, 0xf9,
0xfc, 0xb1, 0x70, 0xe2, 0x21, 0x7f, 0xec, 0xd9,
0x7f, 0x9f, 0x68, 0xad, 0xb1, 0x6e, 0x5d, 0x7d,
0x21, 0xe5, 0x69, 0xd2, 0x80, 0xed, 0x77, 0x5c,
0xeb, 0xde, 0x3f, 0x40, 0x93, 0xc5, 0x38, 0x81,
0x00
};
size_t msg_len = 73;

/*
* 将 EIA3 的 key 转换成 EVP_PKEY
*/
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_EIA3, NULL, key, 16);
if (pkey == NULL)
goto end;

mctx = EVP_MD_CTX_new();
if (mctx == NULL)
goto end;

if (!EVP_DigestSignInit(mctx, &pctx, NULL, NULL, pkey))
goto end;

/*
* 设置 EIA3 的 iv,其中 iv 是十六进制的字符串形式
* 也可以设置 hexkey 来修改 key,同样是十六进制的字符吕形式
*/
rv = EVP_PKEY_CTX_ctrl_str(pctx, "iv", iv);
if (rv <= 0)
goto end;

if (!EVP_DigestSignUpdate(mctx, msg, msg_len))
goto end;

if (!EVP_DigestSignFinal(mctx, NULL, &got_len))
goto end;

got = OPENSSL_malloc(got_len);
if (got == NULL)
goto end;

if (!EVP_DigestSignFinal(mctx, got, &got_len))
goto end;

/*
* EIA3 的 mac 值为4个字节,这里打印出来
*/
mac = OPENSSL_buf2hexstr(got, got_len);
printf("MAC=%s\n", mac);

OPENSSL_free(mac);

end:
EVP_MD_CTX_free(mctx);
OPENSSL_free(got);
EVP_PKEY_free(pkey);

return 0;
}

输出结果:

MAC=24:A8:42:B3