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