使用 libTomCrypt 实现 AES、HMAC、HKDF 运算

56 篇文章 5 订阅
42 篇文章 2 订阅
使用 libTomCrypt 实现 AES、HMAC、HKDF 运算

Qidi 2017.11.06 (Markdown & Haroopad)


1、libTomCrypt 简介

libTomCrypt 是一个使用 C 语言编写的开源加解密算法库,使用 WTF 协议进行授权,支持 AES、HMAC、HKDF、RSA、PRNG、BASE64 等常用加解密算法。


2、基础文件

我们在使用 libTomCrypt 时会发现,调用某一类算法时总是要依赖几个特定头文件和源文件。我称这些头文件/源文件为该类算法的基础文件。
  对于 AES 算法来说,这些基础文件是:

tomcrypt.h    tomcrypt_argchk.h    tomcrypt_cipher.h
aes.c    aes_tab.c    compare_testvector.c
crypt_argchk.c    crypt_cipher_descriptor.c    crypt_cipher_is_valid.c
crypt_find_cipher.c    crypt_register_cipher.c    crypt_unregister_cipher.c
zeromem.c

对于 HMAC 和 HKDF 算法来说,这些基础文件是:

tomcrypt.h    tomcrypt_argchk.h    tomcrypt_cipher.h
aes.c    aes_tab.c    compare_testvector.c
crypt_argchk.c    crypt_hash_descriptor.c   crypt_hash_is_valid.c
crypt_find_hash.c    crypt_register_hash.c    crypt_unregister_hash.c
zeromem.c

3、AES 算法调用流程

使用 AES 算法时一般可以分为以下几个步骤:

  • 注册算法描述符:
 register_cipher(&aes_desc);
  • 获取算法描述符:
 idx = find_cipher("aes");
  • 初始化算法结构体:
 XXX_start(idx, IV,
            key, key_len,
            num_rounds,
            symmetric_XXX *XXX);
  • 加密:
 XXX_encrypt(*plain_text, *crypted_text,
              len, symmetric_XXX *XXX);
  • 解密:
 XXX_decrypt(*crypted_text, *plain_text,
              len, symmetric_XXX *XXX);
  • 结束运算:
 XXX_done(symmetric_XXX *XXX);
  • 释放资源:
 zeromem(key, sizeof(key));
 zeromem(XXX, sizeof(XXX));

3.1、实现 AES-128-ECB 加解密

要实现 aes-128-ecb 加解密,除了要包含(#include)和引用(Makefile 中添加)第 2 节中提到的文件外,还要引用几个 ecb 相关的源文件,如下:

ecb_decrypt.c    ecb_done.c
ecb_encrypt.c    ecb_start.c

工程中截取的代码片段如下:

    ...
    symmetric_ECB ecb;
    unsigned char key[MAXBLOCKSIZE] = "1234567890abcdef" \
                             "1234567890abcdef" \
                             "1234567890abcdef" \
                             "1234567890abcdef" \
                             "1234567890abcdef" \
                             "1234567890abcdef" \
                             "1234567890abcdef" \
                             "1234567890abcde";
    unsigned char pt[4096] = "Keep it simple and stupid.";    // plain text for encrypting, place your own content here
    unsigned char ct[4096];
    if (register_cipher(&aes_desc) < 0) {
        ALOGE("register_cipher() failed!\n");
        goto exit1;
    }
    int idx = find_cipher("aes");
    if (idx == -1) {
        ALOGE("find_cipher() failed!\n");
        goto exit1;
    }
    if (CRYPT_OK != ecb_start(idx, key, cipher_descriptor[idx].min_key_length, 0, &ecb)) {
        ALOGE("ecb_start() failed!\n");
        goto exit1;
    }
    if (CRYPT_OK != ecb_encrypt(pt, ct, sizeof(pt), &ecb)) {
        ALOGE("ecb_encrypt() failed!\n");
        goto exit1;
    }
#if SHOW_DECRYPT
    if (CRYPT_OK != ecb_decrypt(ct, at, sizeof(at), &ecb)) {
        LOG("ecb_decrypt() failed!\n");
        goto exit1;
    }
#endif
    if (CRYPT_OK != ecb_done(&ecb)) {
        LOG("ecb_done() failed!\n");
        goto exit1;
    }
    ...
exit1:
    ...

3.2、实现 AES-128-CTR 加解密

要实现 aes-128-ctr 加解密,除了要包含(#include)和引用(Makefile 中添加)第 2 节中提到的文件外,还要引用几个 ctr 相关的源文件,如下:

ctr_decrypt.c    ctr_done.c
ctr_encrypt.c    ctr_start.c

工程中截取的代码片段如下:

    ...
    if (register_cipher(&aes_desc) < 0) {
        ALOGE("Qidi - aes-128-ctr register_cipher() failed!\n");
        goto error;
    }
    idx = find_cipher("aes");
    if (idx == -1) {
        ALOGE("Qidi - aes-128-ctr find_cipher() failed!\n");
        goto error;
    }
    err = ctr_start(idx, session_iv, session_key, 16, 0, CTR_COUNTER_BIG_ENDIAN, &ctr);
    if (err != CRYPT_OK) {
        ALOGE("Qidi - ctr_start() failed!\n");
        goto error;
    }
    err = ctr_encrypt((unsigned char*)input_raw, buf, 16, &ctr);
    if (err != CRYPT_OK) {
        ALOGE("Qidi - ctr_encrypt() failed!\n");
        goto error;
    }
    // ctr 解密前需要再 start 初始化一次
    err = ctr_start(idx, session_iv, session_key, 16, 0, CTR_COUNTER_BIG_ENDIAN, &ctr);
    if (err != CRYPT_OK) {
        ALOGE("Qidi - ctr_start() failed!\n");
        goto error;
    }
    memset(input_raw, 0, 16);
    err = ctr_decrypt((unsigned char *)output_raw, (unsigned char *)input_raw, 16, &ctr);
    if (err != CRYPT_OK) {
        ALOGE("Qidi - ERROR: ctr_decrypt() failed!\n");
        goto error;
    }
    ctr_done(&ctr);
    ...
error:
    ...

4、HASH 算法一般调用流程

使用 HASH 算法时,一般可以分为以下几个步骤:

  • 注册算法描述符:
 register_hash(&aes_desc);
  • 获取算法描述符:
 idx = find_hash("aes");
  • 初始化算法结构体:
 XXX_start(idx, IV,
            key, key_len,
            num_rounds,
            symmetric_XXX *XXX);
  • 加密:
 XXX_encrypt(*plain_text, *crypted_text,
              len, symmetric_XXX *XXX);
  • 解密:
 XXX_decrypt(*crypted_text, *plain_text,
              len, symmetric_XXX *XXX);
  • 结束运算:
 XXX_done(symmetric_XXX *XXX);
  • 释放资源:
 zeromem(key, sizeof(key));
 zeromem(XXX, sizeof(XXX));

4.1、实现 HMAC 运算

要实现 hmac 加解密,除了要包含(#include)和引用(Makefile 中添加)第 2 节中提到的文件外,还要引用几个 hmac 相关的源文件,如下:

hmac_init.c    hmac_process.c
hmac_memory.c  hash_memory.c
hmac_done.c    sha256.c

工程中截取的代码片段如下:

    ...
    if (register_hash(&sha256_desc) < 0) {
        ALOGE("Qidi - ERROR: verify fw_resp register_hash(&sha256_desc) failed!\n");
        goto error;
    }
    int idx = find_hash("sha256");
    if (idx < 0) {
        ALOGE("Qidi - ERROR: verify fw_resp find_hash(sha256) failed!\n");
        goto error;
    }

    if (CRYPT_OK != hmac_memory(idx, (unsigned char*)pre_key, 32,
                               (unsigned char*)in_data, 36,
                                (unsigned char*)fw_resp, &fw_resp_len)) {
        ALOGE("ERROR: verify fw_resp hmac_memory() failed!\n");
        goto error;
    }
    ...
error:
    ...

其中 hmac_memory() 函数实际上是对 hmac_init()hmac_processhmac_done() 的封装。


4.2、实现 HKDF 运算

要实现 hkdf 加解密,除了要包含(#include)和引用(Makefile 中添加)第 2 节中提到的文件外,还要引用几个 hkdf 相关的源文件,如下:

hkdf.c    sha256.c

工程中截取的代码片段如下:

    ...
    register_hash(&sha256_desc);
    int idx = find_hash("sha256");
    ret = hkdf(idx, (unsigned char*)salt, 20,
         (unsigned char*)info, 20, (unsigned char*)in_data, 18, session_key_iv, 32);
    ...

其中 hkdf() 函数实际上是对 hkdf_extract()hkdf_expand() 的封装。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值