1)数据格式
明文按64位分组,密钥要求是64位长度
2)明文填充方式
DES加密算法中要求明文长度必须是8个字节对齐。如果对于任意一段数据,加密前需要对最后一块
填充到8个字节,解密后需要删除填充的数据
填充有三种模式有
ZeroPadding,数据长度不对齐,填充0,对于明文以/0结束,可以区分出来
PKCS7Padding,假设数据长度需要填充n(n>0)个字节对齐,那么填充n个字节,每个字节都是n;如果数据本身已经对齐,则
填充一块长度为块大小的数据,每个字节都是块大小。
PKCS5Padding, PKCS7Padding的子集,块大小固定为8个字节
提供一段PKCS5Padding填充代码
ch = 8 - nlen % 8;
memset(src + nlen, ch, ch);//padding5填充
说明nlen是明文长度,src + nlen是明文最后的指针, nlen%8有多少个字节没有对齐,然后8 - nlen%8补充这么多的字节数
3)向量
在CBC(不光是DES算法)模式下,iv通过随机数(或伪随机)机制产生是一种比较常见的方法。iv的作用主要是用于产生密文的第一个block,以使最终生成的密文产生差异(明文相同的情况下),使密码***变得更为困难,除此之外iv并无其它用途。最大的好处是,即使相同的明文,相同的密钥,也能产生不同的密文。
4)一般情况下,通过DES加密之后,发送出去都需要进行十六进制编码,有的还需要进行Base64编码,这一点要切记!
调用OpenSSL加密的算法
在这里明文的长度限制为4096,主要是里面保存对齐后明文的数据长度是硬编码导致的
bool EncryptDataByDESOfIV(std::string& key, std::string& iv, char* input_data, unsigned char* encrypt_data, int *data_len)
{
if (key.size() != 8) return false;
DES_key_schedule ks;
DES_cblock ivec = { 0 };
int i = 0;
int len = 0;
int nlen = 0;
char *data = (char *)input_data; /* 原始明文, 十六进制字符串 */
char *okey = (char *)key.c_str(); /* 原始密钥, 十六进制字符串 */
memcpy(&ivec, iv.c_str(), iv.size());
unsigned char ch = '\0';
unsigned char *ptr = NULL;
unsigned char src[4096] = { 0 };
unsigned char *dst = nullptr;
DES_set_key_unchecked((const_DES_cblock*)okey, &ks);
/* 分析补齐明文所需空间及补齐填充数据 */
nlen = strlen((char *)data);
//len = (nlen / 8 + (nlen % 8 ? 1 : 0)) * 8;
len = nlen + 8 - (nlen % 8);
dst = (unsigned char *)calloc(1, len);
memcpy(src, data, len);
ch = 8 - nlen % 8;
memset(src + nlen, ch, 8 - nlen % 8);//padding7填充
//printf("加密之前: ");
//for (i = 0; i < len; i++) {
// printf("%.2X", *(src + i));
//}
//printf("\n");
/* 加密块链式加密 */
DES_ncbc_encrypt(src, dst, len, &ks, &ivec, DES_ENCRYPT);
memcpy(encrypt_data, dst, len);
*data_len = len;
//printf("加密之后: ");
//for (i = 0; i < len; i++) {
// printf("%.2X", *(dst + i));
//}
//printf("\n");
free(dst);
return true;
}
提供一种在线解密工具,验证加密是否正确: http://tool.chacuo.net/cryptdes
引用
https://www.cnblogs.com/chenggang816/p/10542673.html
https://www.cnblogs.com/azbane/p/10179660.html