[使用Crypto ++在Base64字符串中连接IV和数据?

问题描述 投票:2回答:1

我需要将字符串加密为AES / CBC。为了以后能够解密它,我必须将IV存储在最终结果中,该结果必须是base64字符串。

我设法使用此answer和Crypto ++示例:

std::string String::AESEncryptString(std::string str, std::string key)
{
    std::string encoded;
    std::string b64Result = "";

    AutoSeededRandomPool prng;

    unsigned char iv[AES::BLOCKSIZE];
    prng.GenerateBlock(iv, sizeof(iv));

    StringSink output(encoded);

    // Put the IV at the begining of the output
    StringSource(iv, sizeof(iv), true,
        new Redirector(output)
    );

    try {
        CBC_Mode<AES>::Encryption encryptor((unsigned char *)key.c_str(), key.length(), iv);

        StringSource s(str, true, 
            new StreamTransformationFilter(encryptor, 
                new Redirector(output), StreamTransformationFilter::PKCS_PADDING
            )
        );

        // Convert to b64
        StringSource (encoded, true,
            new Base64Encoder(
                new StringSink(b64Result),
                false // do not append a newline
            )
        );

        return b64Result;
    } catch (const Exception& e) {
        return "";
    }
}

要解密base64字符串,我首先提取IV,然后解密其余数据:

std::string String::AESDecryptString(std::string str, std::string key)
{
    unsigned char iv[AES::BLOCKSIZE];

    std::string b64decoded;
    std::string decoded;

    try {
        StringSource(str, true,
            new Base64Decoder(
                new StringSink(b64decoded)
            )
        );

        StringSource ss(b64decoded, false);

        // Get the IV
        ArraySink ivSink(iv, sizeof(iv));
        ss.Attach(new Redirector(ivSink));
        ss.Pump(AES::BLOCKSIZE);


        CBC_Mode<AES>::Decryption decryptor((unsigned char *)key.c_str(), key.length(), iv);


        ByteQueue queue;
        ss.Detach(
            new StreamTransformationFilter(decryptor,
                new Redirector(queue)
            )
        );
        ss.PumpAll(); // Pump remainder bytes

        StringSink decodedSink(decoded);
        queue.TransferTo(decodedSink);
        return decoded;
    }
    catch (const Exception& e) {
        return "";
    }
}

一切正常,但是当我发现Crypto ++和流水线范例时,我觉得我可能已经完成了太多步骤来实现我想要的。

是否有更简洁或更有效的方法?

encryption base64 aes crypto++ cbc-mode
1个回答
0
投票

如果您真的喜欢恐怖故事,请考虑以下因素:

#include <iostream>
#include <string>
#include <cstdlib>
#include <cryptopp/osrng.h>
#include <cryptopp/base64.h>
#include <cryptopp/aes.h>
#include <cryptopp/filters.h>
#include <cryptopp/modes.h>
#include <cryptopp/cryptlib.h>

const std::string seckey = "this-has-16-char";

/**
* Encode : return encoded
*
*/
bool Encode(const std::string& input, std::string& output)
{
    if (seckey.length()!=CryptoPP::AES::DEFAULT_KEYLENGTH) return false;
    unsigned char iv[CryptoPP::AES::BLOCKSIZE];
    // CryptoPP::AutoSeededRandomPool prng;
    // prng.GenerateBlock(iv, sizeof(iv));
    memcpy(iv, "this-also-has-16", CryptoPP::AES::BLOCKSIZE);
    output.clear();
    CryptoPP::StringSink outstr(output);
    // Put the IV at the begining of the output
    CryptoPP::StringSource(iv, sizeof(iv), true, new CryptoPP::Redirector(outstr));

    try {
        CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encryptor((unsigned char *)seckey.c_str(), seckey.length(), iv);
        // encode, Convert to b64, do not append a newline
        CryptoPP::StringSource (
            input, true, new CryptoPP::StreamTransformationFilter(
                encryptor, new CryptoPP::Base64Encoder( new CryptoPP::StringSink(output), false),
                CryptoPP::StreamTransformationFilter::PKCS_PADDING));

    }
    catch (const CryptoPP::Exception& e) {
        return false;
    }
    return true;
}

/**
* Decode : return decoded
*
*/
bool Decode(const std::string& input, std::string& output)
{
    if (seckey.length()!=CryptoPP::AES::DEFAULT_KEYLENGTH) return false;
    if (input.length()<=CryptoPP::AES::BLOCKSIZE) return false; // no iv
    unsigned char iv[CryptoPP::AES::BLOCKSIZE];
    memcpy(iv, input.c_str(), CryptoPP::AES::BLOCKSIZE);
    try {
        // Convert from b64 and decode
        CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decryptor((unsigned char *)seckey.c_str(), seckey.length(), iv);
        CryptoPP::StringSource ((const CryptoPP::byte*)&input[CryptoPP::AES::BLOCKSIZE], input.length()-CryptoPP::AES::BLOCKSIZE,
                                true,new CryptoPP::Base64Decoder(
                                    new CryptoPP::StreamTransformationFilter( decryptor, new CryptoPP::StringSink(output))
                                ));

    }
    catch (const CryptoPP::Exception& e) {
        return false;
    }
    return true;
}

int main()
{

    std::string input = "this is the data";
    std::string output;
    bool status = Encode(input,output);
    if (status) std::cerr << "Encoded: " << ": " << output << std::endl;
    input.clear();
    status = Decode(output,input);
    if (status) std::cerr << "Decoded: " << input << std::endl;

}
© www.soinside.com 2019 - 2024. All rights reserved.