keepassxc

Форк
0
/
CryptoHash.cpp 
125 строк · 3.4 Кб
1
/*
2
 *  Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
3
 *  Copyright (C) 2010 Felix Geyer <debfx@fobos.de>
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation, either version 2 or (at your option)
8
 *  version 3 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
#include "CryptoHash.h"
20

21
#include <QScopedPointer>
22

23
#include <botan/hash.h>
24
#include <botan/mac.h>
25

26
class CryptoHashPrivate
27
{
28
public:
29
    QScopedPointer<Botan::HashFunction> hashFunction;
30
    QScopedPointer<Botan::MessageAuthenticationCode> hmacFunction;
31
};
32

33
CryptoHash::CryptoHash(Algorithm algo, bool hmac)
34
    : d_ptr(new CryptoHashPrivate())
35
{
36
    Q_D(CryptoHash);
37

38
    switch (algo) {
39
    case CryptoHash::Sha256:
40
        if (hmac) {
41
            d->hmacFunction.reset(Botan::MessageAuthenticationCode::create("HMAC(SHA-256)").release());
42
        } else {
43
            d->hashFunction.reset(Botan::HashFunction::create("SHA-256").release());
44
        }
45
        break;
46
    case CryptoHash::Sha512:
47
        if (hmac) {
48
            d->hmacFunction.reset(Botan::MessageAuthenticationCode::create("HMAC(SHA-512)").release());
49
        } else {
50
            d->hashFunction.reset(Botan::HashFunction::create("SHA-512").release());
51
        }
52
        break;
53
    default:
54
        Q_ASSERT(false);
55
        break;
56
    }
57
}
58

59
CryptoHash::~CryptoHash()
60
{
61
    Q_D(CryptoHash);
62
    delete d;
63
}
64

65
void CryptoHash::addData(const QByteArray& data)
66
{
67
    Q_D(CryptoHash);
68

69
    if (data.isEmpty()) {
70
        return;
71
    }
72

73
    try {
74
        if (d->hmacFunction) {
75
            d->hmacFunction->update(reinterpret_cast<const uint8_t*>(data.data()), data.size());
76
        } else if (d->hashFunction) {
77
            d->hashFunction->update(reinterpret_cast<const uint8_t*>(data.data()), data.size());
78
        }
79
    } catch (std::exception& e) {
80
        qWarning("CryptoHash::update failed to add data: %s", e.what());
81
        Q_ASSERT(false);
82
    }
83
}
84

85
void CryptoHash::setKey(const QByteArray& data)
86
{
87
    Q_D(CryptoHash);
88

89
    if (d->hmacFunction) {
90
        try {
91
            d->hmacFunction->set_key(reinterpret_cast<const uint8_t*>(data.data()), data.size());
92
        } catch (std::exception& e) {
93
            qWarning("CryptoHash::setKey failed to set HMAC key: %s", e.what());
94
            Q_ASSERT(false);
95
        }
96
    }
97
}
98

99
QByteArray CryptoHash::result() const
100
{
101
    Q_D(const CryptoHash);
102

103
    Botan::secure_vector<uint8_t> result;
104
    if (d->hmacFunction) {
105
        result = d->hmacFunction->final();
106
    } else if (d->hashFunction) {
107
        result = d->hashFunction->final();
108
    }
109
    return {reinterpret_cast<const char*>(result.data()), int(result.size())};
110
}
111

112
QByteArray CryptoHash::hash(const QByteArray& data, Algorithm algo)
113
{
114
    CryptoHash cryptoHash(algo);
115
    cryptoHash.addData(data);
116
    return cryptoHash.result();
117
}
118

119
QByteArray CryptoHash::hmac(const QByteArray& data, const QByteArray& key, Algorithm algo)
120
{
121
    CryptoHash cryptoHash(algo, true);
122
    cryptoHash.setKey(key);
123
    cryptoHash.addData(data);
124
    return cryptoHash.result();
125
}
126

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.