我正在开发一个google chrome NaCl扩展,它涉及使用openssl库函数加密和解密数据。加密工作完美,解密也可以正常工作,但为此,我不得不进行一种黑客攻击,但我不确定这是否是处理它的正确方法。
else if(action == "decryption")
{
pp::Var content = dict_message.Get("content");
//aes decryption starts here
pp::VarArrayBuffer buffer(content);
const char *password = "password";
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
int cipherlen = buffer.ByteLength();
int len = cipherlen + EVP_MAX_BLOCK_LENGTH;
unsigned char *plaintext = (unsigned char*)malloc(len*sizeof(unsigned char));
unsigned char* ciphertext = static_cast<unsigned char*>(buffer.Map());
aes_init(password, (int)strlen(password), key, iv);
len = decrypt(ciphertext, cipherlen, key, iv, plaintext);
buffer.Unmap();
plaintext[len]='\0'; //fix a bug of overshooting plaintext sent
//aes decryption ends here
pp::VarDictionary reply;
reply.Set("action","decryption");
reply.Set("plaintext", (char*)plaintext);
reply.Set("fileSize", len);
PostMessage(reply);
free(plaintext);
}
现在,此代码解密数据并发送回扩展页面上的javascript。请注意第plaintext[len]='\0';
行,如果我没有说出来,那么有时我会在plaintext
中的正确解密文本之后收到垃圾,并在我的javascript中反映为null
。那么处理错误的正确方法是什么?
答案 0 :(得分:3)
正如其他人所提到的那样,您使用的C字符串必须以NULL结尾。当您调用pp :: VarDictionary :: Set,the parameters are pp::Vars时,您正在利用implicit conversion constructor from C-string to pp::Var.
如果您将明文设为std::string
或使用pp::VarArrayBuffer
,则无需进行此操作。 PostMessage()
已针对大型VarArrayBuffers
进行了优化,因此无论如何您应该更喜欢这样做。所以我建议更换这一行:
unsigned char *plaintext = (unsigned char*)malloc(len*sizeof(unsigned char));
有类似的东西:
pp::VarArrayBuffer plaintext(len);
...并将您的解密行更改为:
len = decrypt(ciphertext, cipherlen, key, iv,\b
static_cast<unsigned char*>(plaintext.Map()));
注意,这会将JavaScript从字符串接收的类型更改为ArrayBuffer。如果您希望它保留为字符串,则可以使用std :: string代替:
std::string plaintext(len, '\0');
并使用operator []访问字符串的缓冲区。所以解密的调用看起来像这样(我假设len> 0):
len = decrypt(ciphertext, cipherlen, key, iv, &plaintext[0]);
答案 1 :(得分:2)
'\0'
是C中所有字符串的终结符。由于输出是字符串,如果缺少'\0'
字符,程序将不知道字符串的结束位置,因此在使用它时可能会移动到字符串之外的区域,这对应于接近结尾的垃圾值。
每当声明字符串时,'\0'
都放在最后。但是,您首先为解密的文本分配内存,然后写入其中。在这种情况下,你必须注意最后的字符串终止字符。
字符串终止字符存在的原因是字符串以C中的字符数组的形式存储,并且只有指向字符串开头的指针才能知道数组的大小。
答案 2 :(得分:1)
如果{-1}}不在c-string的末尾,代码将不知道字符串何时结束并将走向未知的内存部分。 null终止符让程序知道“这是我的字符串的结尾”。如果没有这个,您将在程序中邀请未定义的行为。