Add a safe encryption class.

This commit is contained in:
KingToolbox 2020-07-28 02:05:46 +08:00
parent 516b5aaa1f
commit 479b939b54
3 changed files with 134 additions and 0 deletions

91
src/Cryptographic.cpp Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright 2020, WindTerm.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Cryptographic.h"
#include <QByteArray>
#include <qpassworddigestor.h>
#include <QRandomGenerator>
#include "openssl/evp.h"
constexpr int AES_256_IV_LENGTH = 16;
constexpr int AES_256_KEY_LENGTH = 32;
constexpr int PBKDF2_LENGTH = AES_256_IV_LENGTH + AES_256_KEY_LENGTH;
constexpr int PBKDF2_ITERATION_COUNT = 100000;
QByteArray Cryptographic::decrypt(const QByteArray &data, const QByteArray &pbkdf2) {
return doCrypt(QByteArray::fromBase64(data), Cryptographic::key(pbkdf2), Cryptographic::iv(pbkdf2), 0);
}
QByteArray Cryptographic::doCrypt(QByteArray data, const QByteArray &key, const QByteArray &iv, int enc) {
QByteArray crypted(data.length() + EVP_MAX_BLOCK_LENGTH, '\0');
int cryptedLength = 0;
int length;
EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
EVP_CipherInit_ex(
ctx,
EVP_aes_256_cbc(),
nullptr,
reinterpret_cast<const uchar *>(key.constData()),
reinterpret_cast<const uchar *>(iv.constData()),
enc
);
EVP_CipherUpdate(
ctx,
reinterpret_cast<uchar *>(crypted.data()),
&length,
reinterpret_cast<const uchar *>(data.constData()),
data.length()
);
cryptedLength += length;
EVP_CipherFinal_ex(ctx, reinterpret_cast<uchar *>(crypted.data() + cryptedLength), &length);
cryptedLength += length;
EVP_CIPHER_CTX_free(ctx);
crypted.resize(cryptedLength);
return crypted;
}
QByteArray Cryptographic::encrypt(const QByteArray &data, const QByteArray &pbkdf2) {
QByteArray encrypted = doCrypt(data, Cryptographic::key(pbkdf2), Cryptographic::iv(pbkdf2), 1);
return encrypted.toBase64();
}
QByteArray Cryptographic::iv(const QByteArray &pbkdf2) {
Q_ASSERT(pbkdf2.length() == PBKDF2_LENGTH);
return QByteArray::fromRawData(pbkdf2.constData() + AES_256_KEY_LENGTH, AES_256_IV_LENGTH);
}
QByteArray Cryptographic::key(const QByteArray &pbkdf2) {
Q_ASSERT(pbkdf2.length() == PBKDF2_LENGTH);
return QByteArray::fromRawData(pbkdf2.constData(), AES_256_KEY_LENGTH);
}
QByteArray Cryptographic::pbkdf2(const QByteArray &password, const QByteArray &salt) {
return QPasswordDigestor::deriveKeyPbkdf2(QCryptographicHash::Sha3_512, password, salt, PBKDF2_ITERATION_COUNT, PBKDF2_LENGTH);
}
QByteArray Cryptographic::salt() {
QByteArray number = QByteArray::number(QRandomGenerator::system()->generate64());
QByteArray numberHash = QCryptographicHash::hash(number, QCryptographicHash::Sha512);
return numberHash.toBase64();
}

39
src/Cryptographic.h Normal file
View File

@ -0,0 +1,39 @@
/*
* Copyright 2020, WindTerm.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CRYPTOGRAPHIC_H
#define CRYPTOGRAPHIC_H
#pragma once
class QByteArray;
class Cryptographic {
public:
Cryptographic() = default;
static QByteArray decrypt(const QByteArray &data, const QByteArray &pbkdf2);
static QByteArray encrypt(const QByteArray &data, const QByteArray &pbkdf2);
static QByteArray pbkdf2(const QByteArray &password, const QByteArray &salt);
static QByteArray salt();
private:
static QByteArray doCrypt(QByteArray data, const QByteArray &key, const QByteArray &iv, int enc);
static QByteArray iv(const QByteArray &pbkdf2);
static QByteArray key(const QByteArray &pbkdf2);
};
#endif // CRYPTOGRAPHIC_H

View File

@ -8,6 +8,10 @@ Below is a list of (some) WindTerm components in alphabetical order, along with
A quick circular buffer template class.
## Cryptographic.h/cpp
A very safe encryption class using the PBKDF2-algorithm as defined in RFC 8018. WindTerm uses this class together with the user's master password to protect user data, including passwords, private keys and so on.
## Onigmo
An improved version based on Onigmo 5.13.5. In particular, **the addition of iterator makes it possible to match gap buffer or nonadjacent memory blocks.** Please refer to the sample files for how to use.