我试图在openssl上构建使用DES CBC EDE的修改示例。我在ubuntu 10.04上使用gcc版本4.4.6(Buildroot 2012.02)编译arm(不是我的编译器选择)。这是一个问题:当指针声明被取消注释时 - 一切正常。测试消息解密。但是当指针声明被注释时 - 测试消息在解密后只显示2个第一个字母。我只是无法理解什么可以做一个未使用指针的声明。这是代码:
#include <openssl/des.h>
#include <cstring>
#define BUFSIZE 512
using namespace std;
int main(int argc, char *argv[]) {
unsigned char in[BUFSIZE] = {};
unsigned char out[BUFSIZE] = {};
unsigned char back[BUFSIZE] = {};
unsigned char *strangePointer = &out[0]; // what is wrong with it?
int len;
DES_cblock key1, key2, key3;
DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};
DES_cblock ivecLocal;
DES_key_schedule ks1, ks2, ks3;
const char* key = "0A0A0B0B0C0C0A0A0B0B0C0C";
memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key2,key + 16,8);
DES_set_odd_parity(&key1);
DES_set_odd_parity(&key2);
DES_set_odd_parity(&key3);
DES_set_key((C_Block *)key1, &ks1);
DES_set_key((C_Block *)key2, &ks2);
DES_set_key((C_Block *)key3, &ks3);
const char* message = "Now is the time for all men to stand up and be counted";
/* 64 bytes of plaintext */
len = strlen(message);
memcpy(in,message,len);
printf("Plaintext: [%s]\n", in);
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivecLocal, DES_ENCRYPT);
int lenout = 0;
while(out[lenout] != '\0') ++lenout;
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(out, back, lenout, &ks1, &ks2, &ks3, &ivecLocal, DES_DECRYPT);
printf("Decrypted Text: [%s]\n", back);
return 0;
}
答案 0 :(得分:3)
您的代码中有几个不正确的内容。我先从简单的答案开始:
您的第三个密钥甚至没有填充关键数据。它是本地激活堆栈上的随机数据。
memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key2,key + 16,8); // <<=== NOTE still key2
哦,复制粘贴,你们是一个残酷而无情的笨蛋。无论如何,通过删除你要注释的变量,这个键在内存中向上移动(或向下,取决于你的实现)堆栈,结果是一个不同的值。但最重要的是,你正在使用第三把钥匙的不确定数据。
但这不是整个问题。密钥的这种变化暴露了另一个问题,你是输出长度计算,这也是错误的。这样:
int lenout = 0;
while(out[lenout] != '\0') ++lenout;
假设通过搜索0
字节可以找到输出密码的长度。 DES算法可以轻松地在加密块中的任何地方发送字节。这是完全错误的。 DES_ede3_cbc_encrypt
加密操作的输出大小始终是块大小的倍数,对于DES是8个字节(不一定是DES_cblock
的大小),输出缓冲区的正确计算大小是:
int lenout = ((len + sizeof(DES_cblock) - 1)/sizeof(DES_cblock))*sizeof(DES_cblock);
这可能看起来像一个helluva很多,但最后这一切都是四舍五入到块长度的最接近的倍数。此外,您甚至不需要 input
缓冲区。如果您只是传递输入数据消息及其真实长度,API将为您进行计算。但是我留给你完成(提示:只需删除input
并传递message
)。
结果是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/des.h>
#define BUFSIZE 512
int main(int argc, char *argv[])
{
unsigned char in[BUFSIZE] = {};
unsigned char out[BUFSIZE] = {};
unsigned char back[BUFSIZE] = {};
int len;
DES_cblock key1, key2, key3;
DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};
DES_cblock ivecLocal;
DES_key_schedule ks1, ks2, ks3;
const char* key = "0A0A0B0B0C0C0A0A0B0B0C0C";
memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key3,key + 16,8);
DES_set_odd_parity(&key1);
DES_set_odd_parity(&key2);
DES_set_odd_parity(&key3);
DES_set_key(&key1, &ks1);
DES_set_key(&key2, &ks2);
DES_set_key(&key3, &ks3);
const char* message = "Now is the time for all men to stand up and be counted";
len = strlen(message);
memcpy(in,message,len);
printf("Plaintext: [%s]\n", in);
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivecLocal, DES_ENCRYPT);
int lenout = ((len + sizeof(DES_cblock) - 1)/sizeof(DES_cblock))*sizeof(DES_cblock);
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(out, back, lenout, &ks1, &ks2, &ks3, &ivecLocal, DES_DECRYPT);
printf("Decrypted Text: [%s]\n", back);
return 0;
}
<强>输出强>
Plaintext: [Now is the time for all men to stand up and be counted]
Decrypted Text: [Now is the time for all men to stand up and be counted]
答案 1 :(得分:0)
您很可能遇到缓冲区溢出。 len
的声明出现在堆栈上的back
之后。如果back
溢出,则len
将被覆盖。在中间添加另一个变量(strangePointer
)会在堆栈上添加一个间隙,阻止len被覆盖。
可能会增加BUFSIZE
来解决您的问题。