0
\$\begingroup\$

I need to build something that is not very complicated, but efficient. I don't have much time to debug.

I don't know if this method is strong enough to encrypt a data to be displayed in a Qr code.

It will be compiled in Qt.

    #include <botan/botan.h>
    #include <botan/aes.h>
    #include <botan/kdf.h>
    #include <botan/pbkdf2.h>
    #include <botan/hmac.h>
    #include <botan/sha160.h>

    using namespace std;
    using namespace Botan;

    // .....

    bool BotanWrapper::EncryptFile(QString Source, QString Destination)
    {
    try
    {
    //Setup the key derive functions
    PKCS5_PBKDF2 pbkdf2(new HMAC(new SHA_160));
    const u32bit PBKDF2_ITERATIONS = 8192;

    //Create the KEY and IV
    KDF* kdf = get_kdf("KDF2(SHA-1)");

    //Create the master key
    SecureVector<byte> mMaster = pbkdf2.derive_key(48, mPassword.toStdString(), &mSalt[0], mSalt.size(),PBKDF2_ITERATIONS).bits_of();
    SymmetricKey mKey = kdf->derive_key(32, mMaster, "salt1");
    InitializationVector mIV = kdf->derive_key(16, mMaster, "salt2");

    string inFilename = Source.toStdString();
    string outFilename = Destination.toStdString();
    std::ifstream in(inFilename.c_str(),std::ios::binary);
    std::ofstream out(outFilename.c_str(),std::ios::binary);

    Pipe pipe(get_cipher("AES-256/CBC/PKCS7", mKey, mIV,ENCRYPTION),new DataSink_Stream(out));
    pipe.start_msg();
    in >> pipe;
    pipe.end_msg();

    out.flush();
    out.close();
    in.close();

    return true;
   }
   catch(...)
   {
    return false;
    }
   }
\$\endgroup\$
  • \$\begingroup\$ You should indent the code. It is easy to read then. \$\endgroup\$ – coder Nov 1 '19 at 6:08
2
\$\begingroup\$

I don't know the Botan library, so I'll stick to some general recommendations.


Don't include whole namespaces at global scope, especially the std namespace.


The only use of Qt in this function is to accept QString arguments, with which we do nothing but convert to standard strings. So why not remove the dependency, and allow the function to be used in non-Qt projects, by accepting the filenames as const std::string&? We can keep the interface by providing a (header-only, trivially inlinable) wrapper separately as a convenience for use with Qt:

//encrypt.h
bool EncryptFile(const std::string& source, const std::string& destination);
//encrypt-qt.h
bool EncryptFile(QString source, QString destination)
{ return EncryptFile(source.toStdString(), destination.toStdString(); }

There's certainly no need to use c_str() when passing to the streams' constructors - a std::string is fine (and expected) there.


I'd probably go one further with the overloads, and provide a version that accepts a pair of streams, so that we could use this for network streaming or in-memory encryption:

//encrypt.h
bool EncryptFile(std::istream& source, std::ostream& destination);

bool EncryptFile(const std::string& source, const std::string& destination);
{
    try {
        std::ifstream in(source, std::ios::binary);
        std::ofstream out(destination, std::ios::binary);
        return EncryptFile(in, out);
    } catch (...) {
        return false;
    }
}

Why do we return true, even if writing the output failed? For example, try passing /dev/full as the destination. We could fix that:

return in && out;

Alternatively, we could arrange for the streams to throw exceptions:

    in.exceptions(std::ifstream::failbit | std::ifstream::bad);
    out.exceptions(std::ifstream::failbit | std::ifstream::bad);
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.