Crypto++ Init-Update-Final 获取密码输出

Crypto++ Init-Update-Final get cipher output

为了使用 Crypto++ 加密大文件,我正在使用 Java-like Init-Update-Final in Crypto++

进行加密

演示代码似乎有效,每次调用 Put 时,输出字节都会打印到屏幕上:

encoder.Put(buffer, ready);

但无论如何我都找不到得到所有密文的输出。例如

'H' -> print 01 to screen 
'E' -> print A9 to screen 
'L' -> print 5J to screen 
'L' -> print 13 to screen 
'O' -> print 3d to screen ...

但我无法将完整结果检索到字节数组 01A95J133d...

一个问题in here与使用 Init-Update-Final 加密大文件有关,但似乎还没有提供有效的解决方案。

这是完整的演示代码:

enum { ENCRYPT_MODE = 1, DECRYPT_MODE = 2 };
struct JavaAlgorithmParameter
{
    JavaAlgorithmParameter()
        : key(NULL), ksize(0), iv(NULL), vsize(0) {}

    const byte* key;
    size_t ksize;
    const byte* iv;
    size_t vsize;
};

/////////////////////////
/////////////////////////

class JavaCipher
{
public:
    static JavaCipher* getInstance(const std::string& transformation);

    void init(int opmode, const JavaAlgorithmParameter& params);
    size_t update(const byte* in, size_t isize, byte* out, size_t osize);
    size_t final(byte* out, size_t osize);

    std::string getAlgorithm() const;

protected:
    JavaCipher(const std::string& transformation);

private:
    std::string m_transformation;
    member_ptr<SymmetricCipher> m_cipher;
    member_ptr<StreamTransformationFilter> m_filter;
};

/////////////////////////
/////////////////////////

JavaCipher* JavaCipher::getInstance(const std::string& transformation)
{
    return new JavaCipher(transformation);
}

JavaCipher::JavaCipher(const std::string& transformation)
    : m_transformation(transformation) { }

std::string JavaCipher::getAlgorithm() const
{
    return m_transformation;
}

/////////////////////////
/////////////////////////

size_t JavaCipher::final(byte* out, size_t osize)
{
    m_filter.get()->MessageEnd();

    if (!out || !osize || !m_filter.get()->AnyRetrievable())
        return 0;

    size_t t = CryptoPP::STDMIN(m_filter.get()->MaxRetrievable(), (word64)osize);
    t = m_filter.get()->Get(out, t);
    return t;
}

/////////////////////////
/////////////////////////

size_t JavaCipher::update(const byte* in, size_t isize, byte* out, size_t osize)
{
    if (in && isize)
        m_filter.get()->Put(in, isize);

    if (!out || !osize || !m_filter.get()->AnyRetrievable())
        return 0;

    size_t t = STDMIN(m_filter.get()->MaxRetrievable(), (word64)osize);
    t = m_filter.get()->Get(out, t);
    return t;
}

/////////////////////////
/////////////////////////

void JavaCipher::init(int opmode, const JavaAlgorithmParameter& params)
{
    if (m_transformation == "AES/ECB/PKCSPadding" && opmode == ENCRYPT_MODE)
    {
        m_cipher.reset(new ECB_Mode<AES>::Encryption);
        m_cipher.get()->SetKey(params.key, params.ksize);
        m_filter.reset(new StreamTransformationFilter(*m_cipher.get(), NULL, BlockPaddingSchemeDef::PKCS_PADDING));
    }
    else if (m_transformation == "AES/ECB/PKCSPadding" && opmode == DECRYPT_MODE)
    {
        m_cipher.reset(new ECB_Mode<AES>::Decryption);
        m_cipher.get()->SetKey(params.key, params.ksize);
        m_filter.reset(new StreamTransformationFilter(*m_cipher.get(), NULL, BlockPaddingSchemeDef::PKCS_PADDING));
    }
    else if (m_transformation == "AES/CBC/PKCSPadding" && opmode == ENCRYPT_MODE)
    {
        m_cipher.reset(new CBC_Mode<AES>::Encryption);
        m_cipher.get()->SetKeyWithIV(params.key, params.ksize, params.iv);
        m_filter.reset(new StreamTransformationFilter(*m_cipher.get(), NULL, BlockPaddingSchemeDef::PKCS_PADDING));
    }
    else if (m_transformation == "AES/CBC/PKCSPadding" && opmode == DECRYPT_MODE)
    {
        m_cipher.reset(new CBC_Mode<AES>::Decryption);
        m_cipher.get()->SetKeyWithIV(params.key, params.ksize, params.iv);
        m_filter.reset(new StreamTransformationFilter(*m_cipher.get(), NULL, BlockPaddingSchemeDef::PKCS_PADDING));
    }
    else if (m_transformation == "AES/CTR/NoPadding" && opmode == ENCRYPT_MODE)
    {
        m_cipher.reset(new CTR_Mode<AES>::Encryption);
        m_cipher.get()->SetKeyWithIV(params.key, params.ksize, params.iv);
        m_filter.reset(new StreamTransformationFilter(*m_cipher.get(), NULL, BlockPaddingSchemeDef::NO_PADDING));
    }
    else if (m_transformation == "AES/CTR/NoPadding" && opmode == DECRYPT_MODE)
    {
        m_cipher.reset(new CTR_Mode<AES>::Decryption);
        m_cipher.get()->SetKeyWithIV(params.key, params.ksize, params.iv);
        m_filter.reset(new StreamTransformationFilter(*m_cipher.get(), NULL, BlockPaddingSchemeDef::NO_PADDING));
    }
    else
        throw NotImplemented(m_transformation + " is not implemented");
}

/////////////////////////
/////////////////////////

int main(int argc, char* argv[])
{
    try
    {
        byte key[32], iv[16];
        OS_GenerateRandomBlock(false, key, COUNTOF(key));
        OS_GenerateRandomBlock(false, iv, COUNTOF(iv));

        HexEncoder encoder(new FileSink(cout));

        JavaAlgorithmParameter params;
        params.key = key;
        params.ksize = COUNTOF(key);
        params.iv = iv;
        params.vsize = COUNTOF(iv);

        //JavaCipher* cipher = JavaCipher::getInstance("AES/CTR/NoPadding");
        JavaCipher* cipher = JavaCipher::getInstance("AES/CBC/PKCSPadding");
        cipher->init(ENCRYPT_MODE, params);

        cout << "Algorithm: " << cipher->getAlgorithm() << endl;

        cout << "Key: ";
        encoder.Put(key, COUNTOF(key));
        cout << endl;

        cout << "IV: ";
        encoder.Put(iv, COUNTOF(iv));
        cout << endl;

        char * allText = FileUtil::readAllByte("1MB.txt");
        long len = strlen(allText);

        byte buffer[64];

        size_t ready = 0;

        for (unsigned int i = 0; i <= len; i++)
        {
            byte b = allText[i];

            //cout << "Put 0x";
            encoder.Put(b);
            cout << endl;

            ready = cipher->update(&b, 1, buffer, COUNTOF(buffer));

            if (ready)
            {
                //cout << "Get: ";
                encoder.Put(buffer, ready);
                cout << endl;
            }
        }

        ready = cipher->final(NULL, 0);
        if (ready)
        {
            //cout << "Final: ";
            encoder.Put(buffer, ready);
            cout << endl;
        }

        ready = cipher->final(buffer, COUNTOF(buffer));
        if (ready)
        {
            //cout << "Final: ";
            encoder.Put(buffer, ready);
            cout << endl;
        }

        delete cipher;
        getchar();
    }
    catch (const Exception& ex)
    {
        cerr << ex.what() << endl;
    }

    return 0;
}

But I can't find anyway to get the output of all cipher text. For example

'H' -> print 01 to screen 
'E' -> print A9 to screen 
'L' -> print 5J to screen 
'L' -> print 13 to screen 
'O' -> print 3d to screen ...

But I can't retrieve the full result to a byte array 01A95J133d...

在没有输出缓冲区的情况下调用 cipher::update

cipher->update(&b, 1, NULL, 0);

然后,在调用 cipher::final:

后检索缓冲区
size_t size = <some appropriately size for the cipher text>;
byte result[size];
cipher->final(result, size);

如果您在使用 <some appropriately size for the cipher text> 时遇到问题,请将新方法添加到 class:

size_t ready() const
{
    return m_filter.get()->MaxRetrievable();
}