I am working on a C++ Qt application. To assist the user in case of a failure of the application or the device it is connected to, the program exports all the internal settings and stores them in a ordinary file (csv at the moment). This file is then sent to the company (eg. per mail).
To avoid unnoticed manipulations of the exported settings (eg. from the user by hand after the export), I need some kind of mechanismus to detect this.
The method sould be as simple as possible, since this is not a very critical information, but still effective.
All I can think of would be a hash or encryption, but I am pretty sure there is already a simple and elegant solution available for this.
You can use one of a variety kinds of digests or cryptographic signature schemes. Since this must work off-line, your executable must contain a secret - be it a public key used for public-key encryption, or otherwise, but you can never protect yourself that way against a determined attacker. A simple scheme that can't be bypassed without reverse-engineering will be sufficient; if someone can reverse-engineer, you're done for anyway.
A simplest scheme would be to hash to contents of the file with a private secret appended (or prepended), and append the hash to the end of the file. At the receiving end, you skip the hash, add the secret, re-hash, and compare.
If the checking tool should be stand-alone and simple to use, there are two options:
Build Qt to be linked statically, and linked statically to the C++ runtime. Then build the tool using that build of Qt: it will be quite small, well under 1MB, and will have no dependencies.
Offer the verifier as a single html file, and have it use the JavaScript File API. The user opens the html file in their web browser, drops the file onto a drop area, and gets an instant response. These days it will work on any common browser, i.e. Edge, Chrome, Safari, Firefox, Konqueror, ...
An easy way of doing it in Qt would be to append the contents with a hex representation of a SHA-256 of the contents with a secret appended to them:
static const kHexSealSize = 2+64; // hex SHA-256
static QByteArray kSecret { "Things taste bad without salt." };
QByteArray sealHash(const QByteArray & data, int size = -1) {
if (size < 0) size = data.size();
QCryptographicHash hash(QCryptographicHash::Sha256);
hash.addData(data.constData(), size);
hash.addData(kSecret);
auto seal = QByteArray("\r\n") + hash.result().toHex();
Q_ASSERT(hex.size() == kHexSealSize);
return seal;
}
QByteArray seal(const QByteArray & data) {
return data + sealHash(data);
}
/// Returns whether a seal is valid
bool checkSeal(const QByteArray & data) {
if (data.size() < kHexSealSize) return false;
auto hexSrc = data.right(kHexSealSize);
auto hexCmp = sealHash(data, data.size() - kHexSealSize);
return hexSrc == hexCmp;
}
To prevent/detect modification, the standard way is perform message signing. Whether it is easy or not depends on what tool/library you use to perform such tasks. For instant, openssl provide file signing function as both command line or library function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With