QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
45 const 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 
53 const 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 
61 static QCA::SymmetricKey passwordKey_( const QString &pass, const QCA::InitializationVector &salt )
62 {
63  QCA::SecureArray passarray( QByteArray( pass.toUtf8().constData() ) );
64  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 
68 void QgsAuthCrypto::passwordKeyHash( const QString &pass, QString *salt, QString *hash, QString *cipheriv )
69 {
71  return;
72 
73  QCA::InitializationVector saltiv = QCA::InitializationVector( KEY_GEN_IV_LENGTH );
74  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 
92 bool QgsAuthCrypto::verifyPasswordKeyHash( const QString &pass,
93  const QString &salt,
94  const QString &hash,
95  QString *hashderived )
96 {
98  return false;
99 
100  QCA::InitializationVector saltiv( QCA::hexToArray( salt ) );
101  QString derived( QCA::arrayToHex( passwordKey_( pass, saltiv ).toByteArray() ) );
102 
103  if ( hashderived )
104  {
105  *hashderived = derived;
106  }
107 
108  return hash == derived;
109 }
110 
111 QString QgsAuthCrypto::encryptdecrypt( const QString &passstr,
112  const QString &cipheriv,
113  const QString &textstr,
114  bool encrypt )
115 {
116  QString outtxt = QString();
118  return outtxt;
119 
120  QCA::InitializationVector iv( QCA::hexToArray( cipheriv ) );
121 
122  QCA::SymmetricKey key( QCA::SecureArray( QByteArray( passstr.toUtf8().constData() ) ) );
123 
124  if ( encrypt )
125  {
126  QCA::Cipher cipher = QCA::Cipher( CIPHER_TYPE, CIPHER_MODE, CIPHER_PADDING,
127  QCA::Encode, key, iv,
128  CIPHER_PROVIDER );
129 
130  QCA::SecureArray securedata( textstr.toUtf8() );
131  QCA::SecureArray encrypteddata( cipher.process( securedata ) );
132  if ( !cipher.ok() )
133  {
134  qDebug( "Encryption failed!" );
135  return outtxt;
136  }
137  outtxt = QCA::arrayToHex( encrypteddata.toByteArray() );
138  // qDebug( "Encrypted hex: %s", qPrintable( outtxt ) );
139  }
140  else
141  {
142  QCA::Cipher cipher = QCA::Cipher( CIPHER_TYPE, CIPHER_MODE, CIPHER_PADDING,
143  QCA::Decode, key, iv,
144  CIPHER_PROVIDER );
145 
146  QCA::SecureArray ciphertext( QCA::hexToArray( textstr ) );
147  QCA::SecureArray decrypteddata( cipher.process( ciphertext ) );
148  if ( !cipher.ok() )
149  {
150  qDebug( "Decryption failed!" );
151  return outtxt;
152  }
153 
154  outtxt = QString( decrypteddata.toByteArray() );
155  // qDebug( "Decrypted text %s", qPrintable( outtxt ) ); // DO NOT LEAVE THIS LINE UNCOMMENTED
156  }
157 
158  return outtxt;
159 }
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.
#define CIPHER_TYPE
static void passwordKeyHash(const QString &pass, QString *salt, QString *hash, QString *cipheriv=nullptr)
Generate SHA256 hash for master password, with iterations and salt.
#define CIPHER_PROVIDER
#define KEY_GEN_ITERATIONS
#define CIPHER_SIGNATURE
#define KEY_GEN_IV_LENGTH
#define KEY_GEN_LENGTH
#define PASSWORD_HASH_ALGORITHM
static const QString encrypt(const QString &pass, const QString &cipheriv, const QString &text)
Encrypt data using master password.
static const QString decrypt(const QString &pass, const QString &cipheriv, const QString &text)
Decrypt data using master password.
#define CIPHER_IV_LENGTH
#define CIPHER_PADDING
static bool isDisabled()
Whether QCA has the qca-ossl plugin, which a base run-time requirement.
#define CIPHER_MODE