GmSSL介绍

GmSSL是一个开源的密码工具箱,支持SM2/SM3/SM4/SM9/ZUC等国密(国家商用密码)算法。

从   GmSSL  官网处得到的下载链接为  GitHub - guanzhi/GmSSL: 支持国密SM2/SM3/SM4/SM9/SSL的密码工具箱

GmSSL的下载编译如下:

# git clone https://github.com/guanzhi/GmSSL.git
# cd GmSSL
# mkdir build
# cd build/
# cmake ..
# make
# ls bin/
aeadtest          demo_sm2_encrypt            demo_sm2_sign_ctx            demo_sm4_cbc_encrypt_update  demo_sm9_sign  hash_drbgtest    libsdf_dummy.so      pemtest     sm3test       x509_exttest
aestest           demo_sm2_keygen             demo_sm3                     demo_sm4_cbc_padding         demo_zuc       hextest          libsdf_dummy.so.3    pkcs8test   sm4test       x509_oidtest
asn1test          demo_sm2_keyparse           demo_sm3_hmac                demo_sm4_ctr                 digesttest     hkdftest         libsdf_dummy.so.3.1  sha224test  sm9test       x509_reqtest
base64test        demo_sm2_private_key        demo_sm3_kdf                 demo_sm4_ctr_encrypt_update  ectest         hmactest         libskf_dummy.so      sha256test  tls13test     x509_strtest
block_ciphertest  demo_sm2_private_key_parse  demo_sm4                     demo_sm4_gcm                 gcmtest        libgmssl.so      libskf_dummy.so.3    sha384test  tlstest       x509test
chacha20test      demo_sm2_public_key         demo_sm4_cbc                 demo_sm9_encrypt             gf128test      libgmssl.so.3    libskf_dummy.so.3.1  sha512test  x509_algtest  zuctest
cmstest           demo_sm2_sign               demo_sm4_cbc_decrypt_update  demo_sm9_keygen              gmssl          libgmssl.so.3.1  pbkdf2test           sm2test     x509_crltest

在编译过程中会遇到报错,为小错误,请自行修改

/home/GMSSL/GmSSL/src/sm9_alg.c: In function ‘sm9_fn_from_hash’:
/home/GMSSL/GmSSL/src/sm9_alg.c:2318:11: error: redeclaration of ‘i’ with no linkage
  for (int i = 0; i < 10; i++) {
           ^
/home/GMSSL/GmSSL/src/sm9_alg.c:2315:6: note: previous declaration of ‘i’ was here
  int i, j;
      ^
/home/GMSSL/GmSSL/src/sm9_alg.c:2318:2: error: ‘for’ loop initial declarations are only allowed in C99 mode
  for (int i = 0; i < 10; i++) {
  ^
/home/GMSSL/GmSSL/src/sm9_alg.c:2318:2: note: use option -std=c99 or -std=gnu99 to compile your code
/home/GMSSL/GmSSL/src/sm9_alg.c:2319:3: error: ‘for’ loop initial declarations are only allowed in C99 mode
   for (int j = 0; j < 4; j++) {
   ^

ZUC算法介绍

ZUC算法是一个面向字的流加密算法。算法介绍可见 ZUC-256 流密码算法

根据include/gmssl/zuc.h头文件里提供的算法接口,主要的算法接口有算法初始化,产生密钥流,加密。计算校验值等。其中ZUC根据塞入的key和iv,产生密钥流,算法加密即是将密钥流与明文进行异或操作得到密文,解密即是将密钥流与密文进行异或操作得到明文。接口分为zuc 128位算法与zuc 256位算法,即塞入的key与iv长度差异。

ZUC256算法实例

工程目录:

# ls
libgmssl.so  libgmssl.so.3  Makefile  test.c  zuc.h

其中库和头文件是从上述编译好的GmSSL里拿出来的。

test.c

#include <stdio.h>
#include <string.h>

#include "zuc.h"

void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
    int i;
    printf("%s[%d]", info, len);
    for (i = 0; i < len; i++) {
        printf("%s%02X%s", i % 16 == 0 ? "\n     ":" ",
               buf[i], i == len - 1 ? "\n":"");
    }
}

int main()
{
    int ret;
    uint8_t key[32], iv[32];
    uint32_t out[32];
    uint8_t mac_out[4];
    uint8_t msg[32];

    ZUC256_STATE state;
    ZUC256_MAC_CTX ctx;

    /* stream */
    memset(&state, 0x0, sizeof(ZUC256_STATE));
    memset(key, 0x0, 32);
    memset(iv, 0x0, 32);
    memset(msg, 0xFF, 32);

    zuc256_init(&state, key, iv);

    zuc256_generate_keystream(&state, 32, out);

    dump_buf("keystream out:", out, 32*4);

    /* MAC */
    memset(&ctx, 0x0, sizeof(ZUC256_MAC_CTX));
    memset(key, 0x0, 32);
    memset(iv, 0x0, 32);
    memset(msg, 0xFF, 32);

    zuc256_mac_init(&ctx, key, iv, ZUC256_MAC32_SIZE*8);
    zuc256_mac_update(&ctx, msg, 32);
    zuc256_mac_finish(&ctx, NULL, 0, mac_out);

    dump_buf("mac32 out:", mac_out, 4);

    return 0;
}

Makefile

test:
        gcc -g test.c -I. -L. -lgmssl -o test
clean:
        rm -rf test

编译并测试

# make
gcc -g test.c -I. -L. -lgmssl -o test
test.c: In function ‘main’:
test.c:37:5: warning: passing argument 2 of ‘dump_buf’ from incompatible pointer type [enabled by default]
     dump_buf("keystream out:", out, 32*4);
     ^
test.c:6:6: note: expected ‘uint8_t *’ but argument is of type ‘uint32_t *’
 void dump_buf(char *info, uint8_t *buf, uint32_t len)
      ^
# ./test
keystream out:[128]
     D6 3A D0 58 E2 2C 03 2E 3A 68 FC DA 03 CB BD 39
     67 BC A2 52 74 DE B7 F1 A1 E3 3C 16 58 55 EF 01
     5B D7 39 96 1B 68 FA 95 F7 0D 09 7F CC 1C 39 56
     12 76 3B 90 4C 54 4D 74 AD 3F BC 17 08 3B 16 8B
     0B 7C 78 21 B8 5B 77 97 BB C6 43 49 FD 8A AD E8
     B1 B2 FC 7D AB C9 CB 2B 2E FD 1B F4 FF 10 C8 16
     DE 11 AB 8F 67 6C A6 76 DE 7C 50 45 E0 4B F0 21
     62 75 FD 63 4E 84 80 62 5C 9E 8D D8 D9 8C 04 10
mac32 out:[4]
     88 0D 51 7C
02-03 06:58