簡體   English   中英

使用 OpenSSL EVP。 如何加密字符串並將加密的字符串、密鑰和 IV 保存到文件中? 然后打開文件並解密回字符串?

[英]Using OpenSSL EVP. How to Encrypt a string and save the Encrypted string, key and IV to a file? Then Open the file and Decrypt back to string?

大家好,我已經苦苦掙扎了幾天,無法弄清楚這一點。 我是 C++ 的新手,我正在嘗試加密一個字符串。 然后將加密的字符串、密鑰和 IV 保存到文件中。

加密有效,我生成一個密鑰和 IV。 然后繼續加密字符串。 然后我想將數據保存到文件中,如下所示。

我想將加密的字符串保存在文件的第一行,將密鑰保存在第二行,將 IV 保存在第三行。

我正在努力正確保存數據。

從那里,我想閱讀文件。 將第一行設置為要解密的字符串,第二行設置為密鑰,第三行設置為 IV。

我認為我遇到的問題是將數據保存/寫入文件並讀回數據以解密數據的正確方法。

有人可以幫我找到正確的方向。

這是我到目前為止所得到的:

加密.h

#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/evp.h>
#include <iostream>
#include <fstream>
using namespace std;



class Encryption {

    public:

    static std::string encodeText(const std::string &rawText, uint8_t key, uint8_t ivs)
    {
        uint8_t Keyt[32] = { key };
        uint8_t IV[AES_BLOCK_SIZE] = { ivs }; // Generate an AES Key

        // Make a copy of the IV to IVd as it seems to get destroyed when used
        uint8_t IVd[AES_BLOCK_SIZE];
        for (int i = 0; i < AES_BLOCK_SIZE; i++) {
            IVd[i] = IV[i];
        }

        /** Setup the AES Key structure required for use in the OpenSSL APIs **/
        AES_KEY* AesKey = new AES_KEY();
        AES_set_encrypt_key(Keyt, 256, AesKey);

        /** take an input string and pad it so it fits into 16 bytes (AES Block Size) **/
        const int UserDataSize = (const int)rawText.length();   // Get the length pre-padding
        int RequiredPadding = (AES_BLOCK_SIZE - (rawText.length() % AES_BLOCK_SIZE));   // Calculate required padding
        std::vector<unsigned char> PaddedTxt(rawText.begin(), rawText.end());   // Easier to Pad as a vector
        for (int i = 0; i < RequiredPadding; i++) {
            PaddedTxt.push_back(0); //  Increase the size of the string by
        }                           //  how much padding is necessary

        unsigned char* UserData = &PaddedTxt[0];// Get the padded text as an unsigned char array
        const int UserDataSizePadded = (const int)PaddedTxt.size();// and the length (OpenSSl is a C-API)

        /** Peform the encryption **/
        unsigned char EncryptedData[512] = { 0 }; // Hard-coded Array for OpenSSL (C++ can't dynamic arrays)
        AES_cbc_encrypt(UserData, EncryptedData, UserDataSizePadded, (const AES_KEY*)AesKey, IV, AES_ENCRYPT);

        string en = hex_print(EncryptedData, sizeof(EncryptedData));
        //string en = toIntStingFromChar(enh, sizeof(enh));

        return en;
    }

    static std::string decodeText(const std::string& rawText, uint8_t key, uint8_t ivs)
    {
        uint8_t Keyt[32] = {key};
        uint8_t IV[AES_BLOCK_SIZE] = {ivs}; // Generate an AES Key

        // Make a copy of the IV to IVd as it seems to get destroyed when used
        uint8_t IVd[AES_BLOCK_SIZE];
        for (int i = 0; i < AES_BLOCK_SIZE; i++) {
            IVd[i] = IV[i];
        }

        /** take an input string and pad it so it fits into 16 bytes (AES Block Size) **/
        const int UserDataSize = (const int)rawText.length();   // Get the length pre-padding
        int RequiredPadding = (AES_BLOCK_SIZE - (rawText.length() % AES_BLOCK_SIZE));   // Calculate required padding
        std::vector<unsigned char> PaddedTxt(rawText.begin(), rawText.end());   // Easier to Pad as a vector

        unsigned char* UserData = &PaddedTxt[0];// Get the padded text as an unsigned char array
        const int UserDataSizePadded = (const int)PaddedTxt.size();// and the length (OpenSSl is a C-API)

        /** Setup an AES Key structure for the decrypt operation **/
        AES_KEY* AesDecryptKey = new AES_KEY(); // AES Key to be used for Decryption
        AES_set_decrypt_key(Keyt, 256, AesDecryptKey);   // We Initialize this so we can use the OpenSSL Encryption API

        /** Decrypt the data. Note that we use the same function call. Only change is the last parameter **/
        unsigned char DecryptedData[512] = { 0 }; // Hard-coded as C++ doesn't allow for dynamic arrays and OpenSSL requires an array
        AES_cbc_encrypt(UserData, DecryptedData, UserDataSizePadded, (const AES_KEY*)AesDecryptKey, IVd, AES_DECRYPT);

        string de = hex_print(DecryptedData, sizeof(DecryptedData)-1);

        return de;
    }

    // Convert Hex to string
    static std::string hex_print(const void* pv, size_t len)
    {
        std::string r;
        const unsigned char* p = (const unsigned char*)pv;
        if (NULL == pv)
            r = "null";
        else
        {
            size_t i = 0;
            for (i; i < len; ++i)
                r += ("%02X ", *p++);
        }
        return r;
    }

    // Generate a Key
    static unsigned char *generateKey(unsigned char *buf, size_t length) {
        
        if (!RAND_bytes(buf, length)) {
            return NULL;
        }
        return buf;
    }

    // Generate a IV
    static unsigned char* generateIv(unsigned char* buf, size_t length) {

        if (!RAND_bytes(buf, length)) {
            return NULL;
        }
        return buf;
    }

    // Convert int to string
    static std::string toIntSting(uint8_t Keyt[], int length) {
        
        std::string k;
        for (size_t i = 0; i < length; i++)
        {
            k += std::to_string(Keyt[i]);
        } 
        wxString s(k);
        wxLogDebug(s);
        return k;
    }

    // Convert int to string from a Char
    static std::string toIntStingFromChar(unsigned char* test, int length) {

        std::string k;
        for (size_t i = 0; i < length; i++)
        {
            k += std::to_string(test[i]);
        }
        wxString s(k);
        wxLogDebug(s);
        return k;
    }

    // Write the data to a file
    static void writeToFile(std::string text, std::string Keyt, std::string IV) {
        ofstream myfile;
        myfile.open("example.txt");
        myfile << text;
        myfile << "\n";
        myfile << Keyt;
        myfile << "\n";
        myfile << IV;
        myfile.close();
    }

    // Open the file With the encrypted data
    static std::string* OpenFile() {

        static string myArray[3];

        ifstream myfile("example.txt");
        if (myfile.is_open())
        {
            for (int i = 0; i < 3; ++i)
            {
                // line 1 = text to decrypt
                // line 2 = key
                // line 3 = IV
                myfile >> myArray[i];
            }
            myfile.close();
        }

        return myArray;
    }
};

我使用它如下

// Encrpyt
    uint8_t Keyt[32];
    uint8_t IV[AES_BLOCK_SIZE]; 
    // Generate an AES Key, IV
    Encryption::generateKey(Keyt, sizeof(Keyt));
    Encryption::generateKey(IV, sizeof(IV));

    // Convert the Key to a string for saving to a file
    wxString p = Encryption::toIntSting(Keyt, sizeof(Keyt));
    wxLogDebug(p);

    // Convert the IV to a string for saving to a file
    wxString i = Encryption::toIntSting(IV, sizeof(IV));
    wxLogDebug(i);

    // Encrypt the string
    string response = Encryption::encodeText("password to encrypt", *Keyt, *IV);
    wxString r(response);

    // Save / write to a file
    Encryption::writeToFile(r.ToStdString(), p.ToStdString(), i.ToStdString());


    // Decrypt
    // Open File and return
    // line 1 = text to decrypt
    // line 2 = key
    // line 3 = IV
    string data[3] = { *Encryption::OpenFile() };    
    
    unsigned char key[32] = { (unsigned char)data[1].c_str() };
    unsigned char ivss[32] = { (unsigned char)data[2].c_str() };

   string de = Encryption::decodeText(data[0].c_str(), *key, *ivss);

    wxString d = de;
    wxLogDebug(d);

當它寫入文件時,我得到如下內容:example.txt

b‡f‡2É>ƒ}ã[Å8kH° [¥%WÔù¡dÃy ¼                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
17892143551869940267171785144164159149238210130121845322513358186346341616556
246140155172213011360214244852359123919

有時加密文本(第一行)會占用兩行已經不正確的行。 我的頭到處都是,我什至不知道如何繼續/再看下去。 我在溢出和其他博客等上找到的所有示例僅將數據打印到屏幕上,而不是關於如何將數據保存到文件中。

謝謝你。

我想做的就是加密一個字符串。 然后將加密的字符串、密鑰和 IV 保存到文件中。 然后打開文件並解密數據。

為了能夠讀取可變長度的二進制數據(就像您在第一行中所做的那樣),您需要為第一行編寫必須讀取的數據量,以下內容也是如此。

size data

二進制size (例如int )。

然后分兩步讀取長度和數據。

char * buf;
file.read ((char*)&len, sizeof(int));
buf = new [len];
file.read (buf, len);
string = buf;
delete [] buf;

這適用於每一行。

考慮到作為字符串處理的二進制數據可能會導致問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM