QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
qgsauthcrypto.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsauthcrypto.cpp
3 ---------------------
4 begin : October 5, 2014
5 copyright : (C) 2014 by Boundless Spatial, Inc. USA
6 author : Larry Shaffer
7 email : lshaffer at boundlessgeo dot com
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17#include "qgsauthcrypto.h"
18
19#include <QObject>
20#include <QtCrypto>
21
22// defines culled from MeePasswords (GPL2)
23// https://github.com/ruedigergad/meepasswords/blob/master/entrystorage.h
24#define CIPHER_SIGNATURE "aes256-cbc-pkcs7"
25#define CIPHER_TYPE "aes256"
26#define CIPHER_MODE QCA::Cipher::CBC
27#define CIPHER_PADDING QCA::Cipher::PKCS7
28#define CIPHER_IV_LENGTH 32
29#define CIPHER_PROVIDER "qca-ossl"
30#define PASSWORD_HASH_ALGORITHM "sha256"
31#define KEY_GEN_ITERATIONS 10000
32#define KEY_GEN_LENGTH 16
33#define KEY_GEN_IV_LENGTH 16
34
36{
37 if ( !QCA::isSupported( CIPHER_SIGNATURE, CIPHER_PROVIDER ) )
38 {
39 qDebug( "Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" );
40 return true;
41 }
42 return false;
43}
44
45const QString QgsAuthCrypto::encrypt( const QString &pass, const QString &cipheriv, const QString &text )
46{
48 return QString();
49
50 return encryptdecrypt( pass, cipheriv, text, true );
51}
52
53const QString QgsAuthCrypto::decrypt( const QString &pass, const QString &cipheriv, const QString &text )
54{
56 return QString();
57
58 return encryptdecrypt( pass, cipheriv, text, false );
59}
60
61static QCA::SymmetricKey passwordKey_( const QString &pass, const QCA::InitializationVector &salt )
62{
63 const QCA::SecureArray passarray( QByteArray( pass.toUtf8().constData() ) );
64 const QCA::SecureArray passhash( QCA::Hash( PASSWORD_HASH_ALGORITHM ).hash( passarray ) );
65 return QCA::PBKDF2().makeKey( passhash, salt, KEY_GEN_LENGTH, KEY_GEN_ITERATIONS );
66}
67
68void QgsAuthCrypto::passwordKeyHash( const QString &pass, QString *salt, QString *hash, QString *cipheriv )
69{
71 return;
72
73 const QCA::InitializationVector saltiv = QCA::InitializationVector( KEY_GEN_IV_LENGTH );
74 const QCA::SymmetricKey key = passwordKey_( pass, saltiv );
75
76 if ( !key.isEmpty() )
77 {
78 *salt = QCA::arrayToHex( saltiv.toByteArray() );
79 //qDebug( "salt hex: %s", qPrintable( *salt ) );
80
81 *hash = QCA::arrayToHex( key.toByteArray() );
82 //qDebug( "hash hex: %s", qPrintable( *hash ) );
83
84 if ( cipheriv )
85 {
86 *cipheriv = QCA::arrayToHex( QCA::InitializationVector( CIPHER_IV_LENGTH ).toByteArray() );
87 //qDebug( "cipheriv hex: %s", qPrintable( *cipheriv ) );
88 }
89 }
90}
91
92bool QgsAuthCrypto::verifyPasswordKeyHash( const QString &pass, const QString &salt, const QString &hash, QString *hashderived )
93{
95 return false;
96
97 const QCA::InitializationVector saltiv( QCA::hexToArray( salt ) );
98 const QString derived( QCA::arrayToHex( passwordKey_( pass, saltiv ).toByteArray() ) );
99
100 if ( hashderived )
101 {
102 *hashderived = derived;
103 }
104
105 return hash == derived;
106}
107
108QString QgsAuthCrypto::encryptdecrypt( const QString &passstr, const QString &cipheriv, const QString &textstr, bool encrypt )
109{
110 QString outtxt = QString();
112 return outtxt;
113
114 const QCA::InitializationVector iv( QCA::hexToArray( cipheriv ) );
115
116 const QCA::SymmetricKey key( QCA::SecureArray( QByteArray( passstr.toUtf8().constData() ) ) );
117
118 if ( encrypt )
119 {
120 QCA::Cipher cipher = QCA::Cipher( CIPHER_TYPE, CIPHER_MODE, CIPHER_PADDING, QCA::Encode, key, iv, CIPHER_PROVIDER );
121
122 const QCA::SecureArray securedata( textstr.toUtf8() );
123 const QCA::SecureArray encrypteddata( cipher.process( securedata ) );
124 if ( !cipher.ok() )
125 {
126 qDebug( "Encryption failed!" );
127 return outtxt;
128 }
129 outtxt = QCA::arrayToHex( encrypteddata.toByteArray() );
130 // qDebug( "Encrypted hex: %s", qPrintable( outtxt ) );
131 }
132 else
133 {
134 QCA::Cipher cipher = QCA::Cipher( CIPHER_TYPE, CIPHER_MODE, CIPHER_PADDING, QCA::Decode, key, iv, CIPHER_PROVIDER );
135
136 const QCA::SecureArray ciphertext( QCA::hexToArray( textstr ) );
137 const QCA::SecureArray decrypteddata( cipher.process( ciphertext ) );
138 if ( !cipher.ok() )
139 {
140 qDebug( "Decryption failed!" );
141 return outtxt;
142 }
143
144 outtxt = QString( decrypteddata.toByteArray() );
145 // qDebug( "Decrypted text %s", qPrintable( outtxt ) ); // DO NOT LEAVE THIS LINE UNCOMMENTED
146 }
147
148 return outtxt;
149}
static void passwordKeyHash(const QString &pass, QString *salt, QString *hash, QString *cipheriv=nullptr)
Generate SHA256 hash for master password, with iterations and salt.
static const QString encrypt(const QString &pass, const QString &cipheriv, const QString &text)
Encrypt data using master password.
static bool verifyPasswordKeyHash(const QString &pass, const QString &salt, const QString &hash, QString *hashderived=nullptr)
Verify existing master password hash to a re-generated one.
static const QString decrypt(const QString &pass, const QString &cipheriv, const QString &text)
Decrypt data using master password.
static bool isDisabled()
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
#define KEY_GEN_IV_LENGTH
#define PASSWORD_HASH_ALGORITHM
#define CIPHER_IV_LENGTH
#define KEY_GEN_ITERATIONS
#define CIPHER_PADDING
#define CIPHER_MODE
#define CIPHER_PROVIDER
#define CIPHER_TYPE
#define KEY_GEN_LENGTH
#define CIPHER_SIGNATURE