最近项目需要用到3des加解密,python写的3des加密速度太慢,所以考虑用c/c++完成,项目是在linux部署,而linux中openssl中包括3des加密,而且自己写的肯定没有大神们都用的openssl好用,所以决定使用openssl中的加密模块。
起初,是想用python直接调用,但是需要加载openssl的so库,并且部署的机器上还得安装openssl-devel,比较麻烦。而且3des只是openssl其中一个模块,没必要把整个openssl都引用,所以决定把其中的3des模块摘出来,编译成so库。最后发现,还是编译成python可识别的c扩展比较方便。本文记录在其中遇到的问题。
第一步:把3des模块,从openssl中摘出来,比较简单需要一点耐心。3des模块,把这5个函数摘出来即可:DES_decrypt3, DES_encrypt3, DES_encrypt2, DES_set_key,DES_ecb3_encrypt。要把引用的宏定义头文件挑出来,基本都在这4个头文件中:des.h,e_os2.h,des_locl.h,opensslconf.h。如果有漏掉的,去找出来就行。在这几个头文件没用的函数定义,编译的时候谁出错,削了谁,注释掉就行。千万别自己写宏,说不准那就报错了。
第二步:新建c文件,引用Python.h,编写几个对Python函数接口,具体的python c扩展,可以去百度一下,这里不在赘述。上代码:
#################des3.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <time.h>
#include "des3.h"
#include "Python.h"
#define LEN_OF_KEY 24
int get_rand_key(unsigned char *pKey, int len)//unsigned char *pKeyEncrpt,
{
int i = 0;
while (i < len)
{
pKey[i] = (unsigned char)(rand()%256);
i++;
}
return 0;
}
int des_encrypt_3(unsigned char *data, unsigned char *k, unsigned char *en_data, int data_len)
{
if (data == NULL || k == NULL ||en_data == NULL)
return 1;
unsigned char *src = NULL; /* 补齐后的明文 */
int ch = 0;
int len = (data_len + 7)/8*8;
src = (unsigned char *)malloc(len+1);
if (NULL == src)
return 2;
/* 构造补齐后的加密内容 */
memset(src, ch, len+1);
memcpy(src, data, data_len);
//memcpy(src + data_len, ch, 8 - data_rest);
/* 密钥置换 */
unsigned char block_key[9];
DES_key_schedule ks,ks2,ks3;
memset(block_key, 0, sizeof(block_key));
memcpy(block_key, k + 0, 8);
DES_set_key((DES_cblock*)block_key, &ks);
memset(block_key, 0, sizeof(block_key));
memcpy(block_key, k + 8, 8);
DES_set_key((DES_cblock*)block_key, &ks2);
memset(block_key, 0, sizeof(block_key));
memcpy(block_key, k + 16, 8);
DES_set_key((DES_cblock*)block_key, &ks3);
unsigned char in[8];
unsigned char out[8];
int count = 0;
int i = 0;
count = len / 8;
for (i = 0; i < count; i++)
{
memset(in, 0, 8);
memset(out, 0, 8);
memcpy(in, src + 8 * i, 8);
/* 加密 */
DES_ecb3_encrypt((DES_cblock*)in, (DES_cblock*)out, &ks, &ks2, &ks3, DES_ENCRYPT);
/* 将加密的内容拷贝到加密后的数据 */
memcpy(en_data + 8 * i, out, 8);
}
if (NULL != src)
{
free(src);
src = NULL;
}
return 0;
}
int des_decrypt_3(unsigned char *data, unsigned char *k, unsigned char *de_data, int data_len)
{
if (data == NULL || k == NULL ||de_data == NULL)
return 1;
unsigned char *src = NULL; /* 补齐后的明文 */
int ch = 0;
int len = (data_len + 7)/8*8;
src = (unsigned char *)malloc(len+1);
if (NULL == src)
return 2;
/* 构造补齐后的加密内容 */
memset(src, ch, len+1);
memcpy(src, data, data_len);
//memcpy(src + data_len, ch, 8 - data_rest);
/* 密钥置换 */
unsigned char block_key[9];
DES_key_schedule ks,ks2,ks3;
memset(block_key, 0, sizeof(block_key));
memcpy(block_key, k + 0, 8);
DES_set_key((DES_cblock*)block_key, &ks);
memset(block_key, 0, sizeof(block_key));
memcpy(block_key, k + 8, 8);
DES_set_key((DES_cblock*)block_key, &ks2);
memset(block_key, 0, sizeof(block_key));
memcpy(block_key, k + 16, 8);
DES_set_key((DES_cblock*)block_key, &ks3);
unsigned char in[8];
unsigned char out[8];
int count = 0;
int i = 0;
count = len / 8;
for (i = 0; i < count; i++)
{
memset(in, 0, 8);
memset(out, 0, 8);
memcpy(in, src + 8 * i, 8);
/* 加密 */
DES_ecb3_encrypt((DES_cblock*)in, (DES_cblock*)out, &ks, &ks2, &ks3, DES_DECRYPT);
/* 将加密的内容拷贝到加密后的数据 */
memcpy(de_data + 8 * i, out, 8);
}
if (NULL != src)
{
free(src);
src = NULL;
}
return 0;
}
static PyObject * Des3_get_rand_key(PyObject *self, PyObject *args)
{
unsigned char *key;
int len;
if (!PyArg_ParseTuple(args, "si", &key, &len))
{
return NULL;
}
return (PyObject *)Py_BuildValue("i", get_rand_key(key, len));
}
static PyObject * Des3_des_encrypt_3(PyObject *self, PyObject *args)
{
unsigned char *data;
int data_len;
unsigned char *key;
int key_len;
int en_len;
unsigned char *en_data;
PyObject *retval;
if (!PyArg_ParseTuple(args, "z#z#z#", &data, &data_len, &key, &key_len, &en_data, &en_len))
{
return NULL;
}
retval = (PyObject *)Py_BuildValue("i", des_encrypt_3(data, key, en_data, data_len));
return retval;
}
static PyObject * Des3_des_decrypt_3(PyObject *self, PyObject *args)
{
unsigned char *data;
int data_len;
unsigned char *key;
int key_len;
int de_len;
unsigned char *de_data;
PyObject *retval;
if (!PyArg_ParseTuple(args, "z#z#z#", &data, &data_len, &key, &key_len, &de_data, &de_len))
{
return NULL;
}
retval = (PyObject *)Py_BuildValue("i", des_decrypt_3(data, key, de_data, data_len));
return retval;
}
int test(void)
{
unsigned char *data = "FVmJTZAFHAEJRF1gzXVkLWFM%2FXT4DIgY9ATJQNgU7C3VSb1chBzIOUVMADjIHb1YaBRBbR"; /* 明文 */
// FILE *fp = NULL;
// fp = fopen("/opt/encrypt_transport/data/zx_zx010002_210d_20160509041117_000563c1", "r");
// fseek(fp,0,SEEK_SET);
// char * data = (char *)malloc(4097);
// while (!feof(fp)){
// memset(data, 0, 4097);
// fread(d