ESP加密封包

aes-cbc 密码 加密key iv三者的关系(在不使用salt的情况下)

key = md5(passwd)   key的值是passwd的md5值

iv = md5(key+passwd)   iv值是计算key和passwd合并后的字符串的md5值

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <gcrypt.h>
#include <stdbool.h>
#include <sys/stat.h>

int md5_algo = GCRY_MD_MD5;
void compute_md5(char *input, char *output)
{
    gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
    gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
    gcry_md_hd_t hd;
    gcry_md_open(&hd, md5_algo, 0);
    gcry_md_write(hd, input, strlen(input));
    memcpy(output, gcry_md_read(hd, md5_algo), gcry_md_get_algo_dlen(md5_algo));
    gcry_md_close(hd);
}

char passwd[32] = {0};   
char encryption_key[256] = {0};
compute_md5(passwd, encryption_key); //passwd得赋值,passwd赋值后,计算md5,encryption_key就是key
char tmp[256] = {0};
memcpy(tmp, encryption_key, esp_encr_key_len);
memcpy(tmp + esp_encr_key_len, passwd, strlen(passwd));  //将key和密码拼在一起,计算iv
compute_md5(tmp, iv);

 使用gcrypt库进行aes-cbc加密

1.安装gcrypt

安装wget工具

yum install wget -y

安装bzip2工具

yum install bzip2 -y

安装依赖包libgpg-error

cd /usr/local/src

wget https://www.gnupg.org/ftp/gcrypt/libgpg-error/libgpg-error-1.36.tar.bz2

tar -jxvf libgpg-error-1.36.tar.bz2

cd libgpg-error-1.36

./configure

make && make install

安装libgcrypt-1.8.5

cd /usr/local/src

wget https://www.gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-1.8.5.tar.bz2

tar -jxvf libgcrypt-1.8.5.tar.bz2

cd libgcrypt-1.8.5/

./configure

make && make install

验证版本

libgcrypt-config --version

显示  1.8.5

2.程序链接libgcrypt.so库

1.在/etc/ld.so.conf.d/下创建一个local-x86_64.conf文件,内容是

/usr/local/lib

因为libgcrypt.so库在/usr/local/lib下

2.ldconfig   更新缓存

3.ldconfig -p |grep gcrypt  确认是否正确加载了libgcrypt.so库

4.调用gcrypt.h库时,程序编译加上-lgcrypt  参数

ESP加密封装包

1.结合报文实际分析

ESP将传输层数据+padding(填充数据)+pad_len+next_header,这几部分数据进行加密。

next_header:如果要加密的传输层数据是TCP,就等于6,如果是UDP,就等于17

pad_len:填充数据的字节数。

整个要加密的数据的长度,是16的倍数

key和iv就是用第一节所说的方式进行计算的。input是输入数据,加密后,input里的内容就变为了加密后的数据。

假设原始传输层数据长度为orig_data_len,加密块block_size=16

那么pad_len = block_size - orig_data_len%block_size - 2   (减2,是因为pad_len长度为1字节,next_header长度为1字节,这俩得放进去)

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <gcrypt.h>
#include <stdbool.h>
#include <sys/stat.h>

int crypt_algo_libgcrypt = GCRY_CIPHER_AES128;
int crypt_mode_libgcrypt = GCRY_CIPHER_MODE_CBC;  //分组密码模式
void aes_cbc_encrypt(char *key, char *iv, char *input, int encrypt_len)
{
    gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
    gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
    gcry_error_t cipher_err;
    gcry_cipher_hd_t cipher_hd;
    cipher_err = gcry_cipher_open(&cipher_hd, crypt_algo_libgcrypt, crypt_mode_libgcrypt, 0);
    if(cipher_err)
    {
        printf("<IPsec/ESP Dissector> Error in Algorithm %s Mode %d, grcy_open_cipher failed: %s\n",
                                   gcry_cipher_algo_name(crypt_algo_libgcrypt), crypt_mode_libgcrypt, gcry_strerror(cipher_err));
        return;
    }
    //set key
    size_t key_size = gcry_cipher_get_algo_keylen(crypt_algo_libgcrypt);
    cipher_err = gcry_cipher_setkey(cipher_hd, key, strlen(key));
    if(cipher_err)
    {
        printf("gcry_cipher_setkey failed: %s\n", gcry_strerror(cipher_err));
        return;
    }
    //set iv
    cipher_err = gcry_cipher_setiv(cipher_hd, iv, strlen(iv));
    cipher_err = gcry_cipher_encrypt(cipher_hd, input, encrypt_len, NULL, 0);
    if(cipher_err)
    {
        printf("gcry_cipher_encrypt failed:%s\n", gcry_strerror(cipher_err));
    }
    gcry_cipher_close(cipher_hd);
}

2.加密后,ESP包由esp头(4字节的SPI + 4字节的seq) + iv(第一步里介绍的iv值,16个字节)+ 加密后的数据。  将此时的esp包封装一个ip头和以太头就是一个完整的包了。

3.如果需要校验值,就将第二步里的整个esp包作为输入数据,计算icv值



void generate_hmac_sha1_96(const unsigned char *key, const unsigned char *data, size_t data_len, unsigned char *icv) 
{
    int auth_algo_libgcrypt = GCRY_MD_SHA1;
    //int icv_type = ICV_TYPE_HMAC;
    int esp_icv_len = 12;
    size_t key_len = strlen(key);
    gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
    gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
    gcry_error_t cipher_err;
    gcry_md_hd_t hd;
    gcry_md_open(&hd, auth_algo_libgcrypt, GCRY_MD_FLAG_HMAC);
    gcry_md_setkey(hd, key, key_len);
    gcry_md_write(hd, data, data_len);
    memcpy(icv, gcry_md_read(hd, auth_algo_libgcrypt), esp_icv_len);
    gcry_md_close(hd);
}

char icv[256] = {0};
generate_hmac_sha1_96(encryption_key, hash_input, input_len, icv);  //encryption_key就是校验用的key,也是16字节,icv就是计算后的值

4.icv取前12个字节,封在esp包末尾。这样就是一个完整的即加密,又有完整性校验的esp包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值