Openssl AES crypt C ++函数。解码后,我只有16个字符来自主字符串

时间:2013-02-16 20:19:44

标签: c++ openssl base64 aes

我已经尝试制作一个程序,它将通过AES加密来加密字符串。在查看了stackoverflow和许多其他论坛后,我最终得到了这个。但是代码存在一些问题:

1.有时加密有时不起作用(20次尝试,2次失败)。怎么解决?它与ivec或textLength有关吗?

2.加密和解密后,我的主要人物只有16个第一个字符 字符串。之后我有一些随机字符。可以解密我的所有字符串,或者我必须剪切到16个字符?

3.我需要融合一些字符,所以我做了这个:

    char ivec[16];
    for(int i=0;i<16;i++)
    {
    ivec[i]=iveccreate[i];
    }

但毕竟char ivec [16]有55个字符。知道为什么吗?

4.在功能AES_cbc_encrypt后,我的ivec改为一些完全不同的char。有没有办法阻止这个(我想减少代码的大小)?

我将非常感谢1-4个问题的答案。

MKAROL

PS:我来自波兰所以我的英语不太好。遗憾。

有价值的代码:

#include <string.h>
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <openssl/aes.h>
#include <time.h>
#include <stdlib.h>
#include <vector>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>
#include <openssl/rand.h>
using namespace std;

string AESencode(string Text,string Key);
void AESdecode(string in,string Key);
char *encode(unsigned char *input, int length);
char *decode(unsigned char *input,int lenght);

void main
{
string out=AESencode("String,which I want to encrypt.\0","encryptionkey");
AESdecode(out,"encryptionkey");
return 0;
}

string AESencode(string Text,string Key)
{
   //Creating 16 random ive
   srand((unsigned int) time(NULL));
   unsigned char ive[16];
   for(int i=0; i<16; i++){
   ive[i] = (unsigned char) rand();
   }

//I'm losing null by encode ive
char *iveccreate=encode(ive,16);

//Copying 16 first chars from iveccreate(16 random letters,numbers)
char ivec[16];
   for(int i=0;i<16;i++)
   {
   ivec[i]=iveccreate[i];
   }

//Saving ivec,because I need to fuse ivec with output later
//and after encode I lose orginal ivec
char* ivec1=decode((unsigned char*)iveccreate,strlen((const char*)iveccreate));

// Round up to AES_BLOCK_SIZE
size_t textLength = ((Text.length() / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE;

//If necessary adding null to the Key(full 32 bytes)
if(Klucz.length() < 32){
    Key.append(32 - Key.length(), '\0');
}

//Creating space for the output
unsigned char *aesoutput = new unsigned char[textLength];

//Create and set AESkey
AES_KEY *aesKey = new AES_KEY;
AES_set_encrypt_key((unsigned char*)Key.c_str(), 256, aesKey);

//Encrypting
AES_cbc_encrypt((unsigned char*)Text.c_str(), aesoutput, Text.length()+ 1, aesKey, (unsigned char*)ivec, AES_ENCRYPT);

//Fusing ivec with aesoutput
char wyjsciowy[strlen((const char*)Wyjscie)+16];
    for(int i=0;i<16;i++){
        fuse[i]=ivec1[i];
    }
    for(int i=0;i<strlen((const char*)Wyjscie);i++)        {
        fuse[i+16]=aesouput[i];
    }

//Encode the fuse
char* out=encode((unsigned char*)wyjsciowy,strlen(wyjsciowy));

//Saving chars to string
string mychar((char*)out);

//Creating normal string from the base64 encode output
//String is 65 chars, new line, 65 chars
//so I'm looking for the number of not 65, ending chars of the string
int res=mychar.length()%65;

string allstr;
//Fuse strings without new line charater
for(int i=0;i<(mychar.length()-res);i+=65)
{
    allstr+=mychar.substr(i,64);
}

//Fuse string with the ending string.If res==0 it will add nothing.
allstr+=mychar.substr((mychar.length()-res),res);

//Returnig string
return allstr;
}

//Base64 encode function
char *encode(unsigned char *input, int length)
{
BIO *bmem, *b64;
BUF_MEM *bptr;
b64 = BIO_new(BIO_f_base64());
bmem = BIO_new(BIO_s_mem());
b64 = BIO_push(b64, bmem);
BIO_write(b64, input, length);
BIO_flush(b64);
BIO_get_mem_ptr(b64, &bptr);
char *buff = (char *)malloc(bptr->length+1);
memcpy(buff, bptr->data, bptr->length);
buff[bptr->length] = 0;
BIO_free_all(b64);
return buff;
}

//Base64 decode function
char *decode(unsigned char *input, int length)
{
BIO *b64, *bmem;
char *buffer = (char *)malloc(length);
memset(buffer, 0, length);
b64 = BIO_new(BIO_f_base64());
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
bmem = BIO_new_mem_buf(input, length);
bmem = BIO_push(b64, bmem);
BIO_read(bmem, buffer, length);
BIO_free_all(bmem);
return buffer;
}


void AESdecode(string in,string Key)
{
    //Decode the input string with Base64
    char* dec=decode((unsigned char*)in.c_str(),in.length());

    //Getting ivec
    unsigned char ivec[16];
    {

        //Getting first 16 bytes from dec
        unsigned char preivec[16];
        for(int i=0;i<16; i++){
            preivec[i] = dec[i];
        }

        //Encode these 16 bytes
        char *ppiv=encode(preivec,16);

        //Now we have 25 chars text
        //And ivec is only fist 16
        for(int i=0;i<25; i++){
            ivec[i] = ppiv[i];
        }
    }

    //Getting aesouput bytes
    char data[strlen(dec)-16];
    for(int i=16;i<(strlen(dec));i++){
        data[i-16]=dec[i];
    }

   //If necessary adding null to the Key(full 32 bytes)
    if(Key.length()< 32){
        Key.append(32-Key.length(),'\0');
    }   

    //Creating space for the output
    unsigned char *output = new unsigned char[strlen(data)];

    //Create and set new AESkey
    AES_KEY *aesKey = new AES_KEY;
    AES_set_decrypt_key((unsigned char*)Key.c_str(), 256, aesKey);
    // key length is in bits, so 32 * 8 = 256

    //Deccrypting
    AES_cbc_encrypt((unsigned char*)data, output, strlen(data), aesKey,ivec, AES_DECRYPT);

    //And there should be full primary string
    cout<<"OUTPUT: "<<output<<endl;
   }

1 个答案:

答案 0 :(得分:0)

AES密钥是固定长度的字节数组,而不是可变长度字符串。当你调用AES_set_decrypt_key()时,你给它一个13个字符长的字符串,添加一个空字节,所以我们知道14个字节。然后该功能将使用(32-14) - &gt;其密钥的剩余18个字节。这18个字节的内容主要是幸运的结果

我怀疑这是你的问题。