Note that there are some explanatory texts on larger screens.

plurals
  1. POCan anyone explain why my crypto++ decrypted file is 16 bytes short?
    primarykey
    data
    text
    <p>In order that I might feed AES encrypted text as an <code>std::istream</code> to a parser component I am trying to create a <code>std::streambuf</code> implementation wrapping the vanilla crypto++ encryption/decryption.</p> <p>The <code>main()</code> function calls the following functions to compare my wrapper with the vanilla implementation:</p> <ul> <li><code>EncryptFile()</code> - encrypt file using my streambuf implementation</li> <li><code>DecryptFile()</code> - decrypt file using my streambuf implementation</li> <li><code>EncryptFileVanilla()</code> - encrypt file using vanilla crypto++</li> <li><code>DecryptFileVanilla()</code> - decrypt file using vanilla crypto++</li> </ul> <p>The problem is that whilst the encrypted files created by <code>EncryptFile()</code> and <code>EncryptFileVanilla()</code> are identical. The decrypted file created by <code>DecryptFile()</code> is incorrect being 16 bytes short of that created by <code>DecryptFileVanilla()</code>. Probably not coincidentally the block size is also 16.</p> <p>I think the issue must be in <code>CryptStreamBuffer::GetNextChar()</code>, but I've been staring at it and the crypto++ documentation for hours.</p> <p>Can anybody help/explain?</p> <p>Any other comments about how crummy or naive my <code>std::streambuf</code> implementation are also welcome ;-)</p> <p>Thanks,</p> <p>Tom</p> <pre><code>// Runtime Includes #include &lt;iostream&gt; // Crypto++ Includes #include "aes.h" #include "modes.h" // xxx_Mode&lt; &gt; #include "filters.h" // StringSource and // StreamTransformation #include "files.h" using namespace std; class CryptStreamBuffer: public std::streambuf { public: CryptStreamBuffer(istream&amp; encryptedInput, CryptoPP::StreamTransformation&amp; c); CryptStreamBuffer(ostream&amp; encryptedOutput, CryptoPP::StreamTransformation&amp; c); ~CryptStreamBuffer(); protected: virtual int_type overflow(int_type ch = traits_type::eof()); virtual int_type uflow(); virtual int_type underflow(); virtual int_type pbackfail(int_type ch); virtual int sync(); private: int GetNextChar(); int m_NextChar; // Buffered character CryptoPP::StreamTransformationFilter* m_StreamTransformationFilter; CryptoPP::FileSource* m_Source; CryptoPP::FileSink* m_Sink; }; // class CryptStreamBuffer CryptStreamBuffer::CryptStreamBuffer(istream&amp; encryptedInput, CryptoPP::StreamTransformation&amp; c) : m_NextChar(traits_type::eof()), m_StreamTransformationFilter(0), m_Source(0), m_Sink(0) { m_StreamTransformationFilter = new CryptoPP::StreamTransformationFilter(c, 0, CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING); m_Source = new CryptoPP::FileSource(encryptedInput, false, m_StreamTransformationFilter); } CryptStreamBuffer::CryptStreamBuffer(ostream&amp; encryptedOutput, CryptoPP::StreamTransformation&amp; c) : m_NextChar(traits_type::eof()), m_StreamTransformationFilter(0), m_Source(0), m_Sink(0) { m_Sink = new CryptoPP::FileSink(encryptedOutput); m_StreamTransformationFilter = new CryptoPP::StreamTransformationFilter(c, m_Sink, CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING); } CryptStreamBuffer::~CryptStreamBuffer() { if (m_Sink) { delete m_StreamTransformationFilter; // m_StreamTransformationFilter owns and deletes m_Sink. } if (m_Source) { delete m_Source; // m_Source owns and deletes m_StreamTransformationFilter. } } CryptStreamBuffer::int_type CryptStreamBuffer::overflow(int_type ch) { return m_StreamTransformationFilter-&gt;Put((byte)ch); } CryptStreamBuffer::int_type CryptStreamBuffer::uflow() { int_type result = GetNextChar(); // Reset the buffered character m_NextChar = traits_type::eof(); return result; } CryptStreamBuffer::int_type CryptStreamBuffer::underflow() { return GetNextChar(); } CryptStreamBuffer::int_type CryptStreamBuffer::pbackfail(int_type ch) { return traits_type::eof(); } int CryptStreamBuffer::sync() { // TODO: Not sure sync is the correct place to be doing this. // Should it be in the destructor? if (m_Sink) { m_StreamTransformationFilter-&gt;MessageEnd(); // m_StreamTransformationFilter-&gt;Flush(true); } return 0; } int CryptStreamBuffer::GetNextChar() { // If we have a buffered character do nothing if (m_NextChar != traits_type::eof()) { return m_NextChar; } // If there are no more bytes currently available then pump the source if (m_StreamTransformationFilter-&gt;MaxRetrievable() == 0) { m_Source-&gt;Pump(1024); } // Retrieve the next byte byte nextByte; size_t noBytes = m_StreamTransformationFilter-&gt;Get(nextByte); if (0 == noBytes) { return traits_type::eof(); } // Buffer up the next character m_NextChar = nextByte; return m_NextChar; } void InitKey(byte key[]) { key[0] = -62; key[1] = 102; key[2] = 78; key[3] = 75; key[4] = -96; key[5] = 125; key[6] = 66; key[7] = 125; key[8] = -95; key[9] = -66; key[10] = 114; key[11] = 22; key[12] = 48; key[13] = 111; key[14] = -51; key[15] = 112; } /** Decrypt using my CryptStreamBuffer */ void DecryptFile(const char* sourceFileName, const char* destFileName) { ifstream ifs(sourceFileName, ios::in | ios::binary); ofstream ofs(destFileName, ios::out | ios::binary); byte key[CryptoPP::AES::DEFAULT_KEYLENGTH]; InitKey(key); CryptoPP::ECB_Mode&lt;CryptoPP::AES&gt;::Decryption decryptor(key, sizeof(key)); if (ifs) { if (ofs) { CryptStreamBuffer cryptBuf(ifs, decryptor); std::istream decrypt(&amp;cryptBuf); int c; while (EOF != (c = decrypt.get())) { ofs &lt;&lt; (char)c; } ofs.flush(); } else { std::cerr &lt;&lt; "Failed to open file '" &lt;&lt; destFileName &lt;&lt; "'." &lt;&lt; endl; } } else { std::cerr &lt;&lt; "Failed to open file '" &lt;&lt; sourceFileName &lt;&lt; "'." &lt;&lt; endl; } } /** Encrypt using my CryptStreamBuffer */ void EncryptFile(const char* sourceFileName, const char* destFileName) { ifstream ifs(sourceFileName, ios::in | ios::binary); ofstream ofs(destFileName, ios::out | ios::binary); byte key[CryptoPP::AES::DEFAULT_KEYLENGTH]; InitKey(key); CryptoPP::ECB_Mode&lt;CryptoPP::AES&gt;::Encryption encryptor(key, sizeof(key)); if (ifs) { if (ofs) { CryptStreamBuffer cryptBuf(ofs, encryptor); std::ostream encrypt(&amp;cryptBuf); int c; while (EOF != (c = ifs.get())) { encrypt &lt;&lt; (char)c; } encrypt.flush(); } else { std::cerr &lt;&lt; "Failed to open file '" &lt;&lt; destFileName &lt;&lt; "'." &lt;&lt; endl; } } else { std::cerr &lt;&lt; "Failed to open file '" &lt;&lt; sourceFileName &lt;&lt; "'." &lt;&lt; endl; } } /** Decrypt using vanilla crypto++ */ void DecryptFileVanilla(const char* sourceFileName, const char* destFileName) { byte key[CryptoPP::AES::DEFAULT_KEYLENGTH]; InitKey(key); CryptoPP::ECB_Mode&lt;CryptoPP::AES&gt;::Decryption decryptor(key, sizeof(key)); CryptoPP::FileSource(sourceFileName, true, new CryptoPP::StreamTransformationFilter(decryptor, new CryptoPP::FileSink(destFileName), CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING ) // StreamTransformationFilter ); // FileSource } /** Encrypt using vanilla crypto++ */ void EncryptFileVanilla(const char* sourceFileName, const char* destFileName) { byte key[CryptoPP::AES::DEFAULT_KEYLENGTH]; InitKey(key); CryptoPP::ECB_Mode&lt;CryptoPP::AES&gt;::Encryption encryptor(key, sizeof(key)); CryptoPP::FileSource(sourceFileName, true, new CryptoPP::StreamTransformationFilter(encryptor, new CryptoPP::FileSink(destFileName), CryptoPP::BlockPaddingSchemeDef::PKCS_PADDING ) // StreamTransformationFilter ); // FileSource } int main(int argc, char* argv[]) { EncryptFile(argv[1], "encrypted.out"); DecryptFile("encrypted.out", "decrypted.out"); EncryptFileVanilla(argv[1], "encrypted_vanilla.out"); DecryptFileVanilla("encrypted_vanilla.out", "decrypted_vanilla.out"); return 0; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload