1

我试图制作一个通过 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 变成了一些完全不同的字符。有什么办法可以阻止这种情况(我想减小代码的大小)?

对于 1-4 个问题的答案,我将非常感激。

麦卡罗尔

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;
   }
4

1 回答 1

0

AES 密钥是固定长度的字节数组,而不是可变长度的字符串。当你调用 AES_set_decrypt_key() 时,你给它一个 13 个字符的长字符串,加上一个空字节,所以我们知道是 14 个字节。然后该函数将使用 (32-14) -> 18 个剩余字节作为其密钥。这18个字节的内容是什么,多半是运气的结果

我怀疑这是你的问题。

于 2013-02-16T22:37:43.343 回答