mirror of
https://invent.kde.org/network/falkon.git
synced 2024-11-11 01:22:10 +01:00
Add cryptographic functions for sync
Add function for HKDF using Nettle. Add function to process sessionToken. Add function to process keyFetchToken.
This commit is contained in:
parent
881a060c27
commit
d1596cff9c
|
@ -28,19 +28,18 @@
|
|||
FxALoginPage::FxALoginPage(QWidget* parent)
|
||||
: QWebEngineView(parent)
|
||||
{
|
||||
m_page = new QWebEnginePage();
|
||||
m_page = new QWebEnginePage(this);
|
||||
m_channel = new QWebChannel(m_page);
|
||||
m_page->setWebChannel(m_channel);
|
||||
m_page->load(FxALoginUrl);
|
||||
this->setPage(m_page);
|
||||
connect(m_page, SIGNAL(loadFinished(bool)), this, SLOT(pageLoadFinished(bool)));
|
||||
setPage(m_page);
|
||||
connect(m_page, &QWebEnginePage::loadFinished, this, &FxALoginPage::pageLoadFinished);
|
||||
}
|
||||
|
||||
FxALoginPage::~FxALoginPage()
|
||||
{
|
||||
delete m_communicator;
|
||||
delete m_channel;
|
||||
delete m_page;
|
||||
}
|
||||
|
||||
void FxALoginPage::pageLoadFinished(bool pageLoaded)
|
||||
|
@ -48,22 +47,22 @@ void FxALoginPage::pageLoadFinished(bool pageLoaded)
|
|||
if (pageLoaded) {
|
||||
QFile apiFile(":/qtwebchannel/qwebchannel.js");
|
||||
if (!apiFile.open(QIODevice::ReadOnly)) {
|
||||
qDebug() << "Couldn't load Qt's Webchannel API!";
|
||||
qWarning() << "Couldn't load Qt's Webchannel API!";
|
||||
}
|
||||
QString apiScript = QString::fromLatin1(apiFile.readAll());
|
||||
QString apiScript = QString::fromUtf8(apiFile.readAll());
|
||||
apiFile.close();
|
||||
m_page->runJavaScript(apiScript);
|
||||
|
||||
m_communicator = new MessageReceiver(this);
|
||||
connect(m_communicator, SIGNAL(signalMessageReceived()),
|
||||
this, SLOT(slotMessageReceived()));
|
||||
connect(m_communicator, &MessageReceiver::signalMessageReceived,
|
||||
this, &FxALoginPage::slotMessageReceived);
|
||||
m_channel->registerObject(QString("communicator"), m_communicator);
|
||||
|
||||
QFile scriptFile(":/data/inject.js");
|
||||
if (!scriptFile.open(QIODevice::ReadOnly)) {
|
||||
qDebug() << "Couldn't load JavaScript file to inject.";
|
||||
qWarning() << "Couldn't load JavaScript file to inject.";
|
||||
}
|
||||
QString injectScript = QString::fromLatin1(scriptFile.readAll());
|
||||
QString injectScript = QString::fromUtf8(scriptFile.readAll());
|
||||
scriptFile.close();
|
||||
m_page->runJavaScript(injectScript);
|
||||
}
|
||||
|
@ -79,21 +78,20 @@ void FxALoginPage::slotMessageReceived()
|
|||
|
||||
void FxALoginPage::parseMessage(QJsonObject *msg)
|
||||
{
|
||||
QJsonValue command = (*msg).value("detail").toObject().value("message").toObject().value("command");
|
||||
if(command.toString() == QString("fxaccounts:can_link_account")) {
|
||||
QJsonValue command = msg->value("detail").toObject().value("message").toObject().value("command");
|
||||
if (command.toString() == QLatin1String("fxaccounts:can_link_account")) {
|
||||
QJsonObject responseData;
|
||||
responseData.insert("ok", true);
|
||||
responseData.insert(QString("ok"), true);
|
||||
QJsonObject message;
|
||||
message.insert("command", command);
|
||||
message.insert("data", responseData);
|
||||
message.insert("messageId", (*msg).value("detail").toObject().value("message").toObject().value("messageId"));
|
||||
message.insert("messageId", msg->value("detail").toObject().value("message").toObject().value("messageId"));
|
||||
QJsonObject response;
|
||||
response.insert("id", (*msg).value("detail").toObject().value("id"));
|
||||
response.insert("id", msg->value("detail").toObject().value("id"));
|
||||
response.insert("message", message);
|
||||
sendMessage(response);
|
||||
}
|
||||
else if(command.toString() == QString("fxaccounts:login")) {
|
||||
QJsonObject data = (*msg).value("detail").toObject().value("message").toObject().value("data").toObject();
|
||||
} else if (command.toString() == QLatin1String("fxaccounts:login")) {
|
||||
QJsonObject data = msg->value("detail").toObject().value("message").toObject().value("data").toObject();
|
||||
QString email = data.value("email").toString();
|
||||
QString uid = data.value("uid").toString();
|
||||
QString session_token = data.value("sessionToken").toString();
|
||||
|
|
|
@ -15,57 +15,91 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* ============================================================ */
|
||||
|
||||
#include "synccrypto.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include <nettle/sha2.h>
|
||||
#include <nettle/hkdf.h>
|
||||
#include <nettle/hmac.h>
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
HKDF::HKDF(const QByteArray key, const QByteArray salt, const QByteArray info)
|
||||
u_char *syncCryptoHkdf(QByteArray *in, QByteArray *info, size_t out_len)
|
||||
{
|
||||
pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF,NULL);
|
||||
hmac_sha256_ctx *ctx = new hmac_sha256_ctx;
|
||||
|
||||
init(key, salt,info);
|
||||
size_t in_len = in->size();
|
||||
size_t info_len = info->size();
|
||||
u_char *salt = new u_char[SHA256_DIGEST_SIZE] {0};
|
||||
u_char *prk = new u_char[SHA256_DIGEST_SIZE];
|
||||
u_char *output = new u_char[out_len];
|
||||
|
||||
nettle_hmac_sha256_set_key(ctx, SHA256_DIGEST_SIZE, salt);
|
||||
nettle_hkdf_extract(ctx,
|
||||
(nettle_hash_update_func *)hmac_sha256_update,
|
||||
(nettle_hash_digest_func *)hmac_sha256_digest,
|
||||
SHA256_DIGEST_SIZE,
|
||||
in_len, (u_char *)in->data(), prk);
|
||||
nettle_hmac_sha256_set_key(ctx, SHA256_DIGEST_SIZE, prk);
|
||||
nettle_hkdf_expand(ctx,
|
||||
(nettle_hash_update_func *)hmac_sha256_update,
|
||||
(nettle_hash_digest_func *)hmac_sha256_digest,
|
||||
SHA256_DIGEST_SIZE,
|
||||
info_len, (u_char *)info->data(), out_len, output);
|
||||
|
||||
delete[] prk;
|
||||
return output;
|
||||
}
|
||||
|
||||
HKDF::~HKDF() {
|
||||
}
|
||||
|
||||
void HKDF::init(const QByteArray key, const QByteArray salt, const QByteArray info)
|
||||
void syncCryptoKW(QByteArray *kw, QString name)
|
||||
{
|
||||
size_t keylen = key.size();
|
||||
size_t saltlen = salt.size();
|
||||
size_t infolen = info.size();
|
||||
|
||||
if (EVP_PKEY_derive_init(pctx) <= 0) {
|
||||
qWarning("Unable to initialize public key algorithm context for HKDF.");
|
||||
return;
|
||||
}
|
||||
if (EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()) <= 0) {
|
||||
qWarning("Unable to set HKDF message digest.");
|
||||
return;
|
||||
}
|
||||
if (EVP_PKEY_CTX_set1_hkdf_salt(pctx, (uchar *)salt.data(), saltlen) <= 0) {
|
||||
qWarning("Unable to set salt.");
|
||||
return;
|
||||
}
|
||||
if (EVP_PKEY_CTX_set1_hkdf_key(pctx, (uchar *)key.data(), keylen) <= 0) {
|
||||
qWarning("Unable to set key.");
|
||||
return;
|
||||
}
|
||||
if (EVP_PKEY_CTX_add1_hkdf_info(pctx, (uchar *)info.data(), infolen) <= 0) {
|
||||
qWarning("Uable to set info for HKDF.");
|
||||
return;
|
||||
}
|
||||
// Concatenate "name" to Mozilla prefix to get the required KW.
|
||||
// See https://raw.githubusercontent.com/wiki/mozilla/fxa-auth-server/images/onepw-create.png for details.
|
||||
QString info = QString("identity.mozilla.com/picl/v1/").append(name);
|
||||
kw->append(info.toUtf8());
|
||||
}
|
||||
|
||||
QByteArray HKDF::getKey(size_t outlen) {
|
||||
QByteArray out;
|
||||
if (EVP_PKEY_derive(pctx, (uchar *)out.data(), &outlen) <= 0) {
|
||||
qWarning("Unable to derive HKDF key.");
|
||||
}
|
||||
return out;
|
||||
void deriveSessionToken(QByteArray *sessionToken, QByteArray *tokenId, QByteArray *reqHMACKey, QByteArray *reqKey)
|
||||
{
|
||||
QByteArray *kw = new QByteArray();
|
||||
syncCryptoKW(kw, QString("sessionToken"));
|
||||
size_t len = 32;
|
||||
|
||||
u_char *out = syncCryptoHkdf(sessionToken, kw, 3 * len);
|
||||
QByteArray *temp = new QByteArray(QByteArray::fromRawData((const char *)out, 3 * len));
|
||||
QByteArray tId(*temp);
|
||||
tId.remove(len, 2 * len);
|
||||
tokenId->append(tId);
|
||||
reqKey->append(temp->right(len));
|
||||
temp->remove(0, len);
|
||||
temp->remove(len, len);
|
||||
reqHMACKey->append(*temp);
|
||||
}
|
||||
|
||||
void deriveKeyFetchToken(QByteArray *keyFetchToken, QByteArray *tokenId, QByteArray *reqHMACKey, QByteArray *respHMACKey, QByteArray *respXORKey)
|
||||
{
|
||||
QByteArray *infoKft = new QByteArray();
|
||||
syncCryptoKW(infoKft, "keyFetchToken");
|
||||
QByteArray *infoKeys = new QByteArray();
|
||||
syncCryptoKW(infoKeys, "account/keys");
|
||||
size_t len = 32;
|
||||
|
||||
u_char *out1 = syncCryptoHkdf(keyFetchToken, infoKft, 3 * len);
|
||||
QByteArray *temp = new QByteArray(QByteArray::fromRawData((const char *)out1, 3 * len));
|
||||
QByteArray tId(*temp);
|
||||
tId.remove(len, 2 * len);
|
||||
tokenId->append(tId);
|
||||
QByteArray *reqKey = new QByteArray();
|
||||
reqKey->append(temp->right(len));
|
||||
temp->remove(0, len);
|
||||
temp->remove(len, len);
|
||||
reqHMACKey->append(*temp);
|
||||
|
||||
u_char *out2 = syncCryptoHkdf(reqKey, infoKeys, 3 * len);
|
||||
QByteArray *temp2 = new QByteArray(QByteArray::fromRawData((const char *)out2, 3 * len));
|
||||
QByteArray respHKey(*temp2);
|
||||
respHKey.remove(len, 2 * len);
|
||||
respHMACKey->append(respHKey);
|
||||
temp2->remove(0, len);
|
||||
respXORKey->append(*temp2);
|
||||
}
|
||||
|
|
|
@ -17,20 +17,12 @@
|
|||
* ============================================================ */
|
||||
#pragma once
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
class HKDF
|
||||
{
|
||||
public:
|
||||
explicit HKDF(const QByteArray key, const QByteArray salt, const QByteArray info);
|
||||
~HKDF();
|
||||
|
||||
QByteArray getKey(size_t outlen);
|
||||
|
||||
private:
|
||||
void init(const QByteArray key, const QByteArray salt, const QByteArray info);
|
||||
|
||||
EVP_PKEY_CTX *pctx;
|
||||
};
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
|
||||
u_char *syncCryptoHkdf(QByteArray *in, QByteArray *info, size_t out_len);
|
||||
void syncCryptoKW(QByteArray *kw, QString name);
|
||||
void deriveSessionToken(QByteArray *sessionToken, QByteArray *tokenId, QByteArray *reqHMACKey, QByteArray *reqKey);
|
||||
void deriveKeyFetchToken(QByteArray *keyFetchToken, QByteArray *tokenId, QByteArray *reqHMACKey, QByteArray *respHMACKey, QByteArray *respXORKey);
|
||||
|
|
Loading…
Reference in New Issue
Block a user