QGIS API Documentation  2.12.0-Lyon
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 RANDOM_KEY_LENGTH 16
32 #define KEY_GEN_ITERATIONS 10000
33 #define KEY_GEN_LENGTH 16
34 #define KEY_GEN_IV_LENGTH 16
35 
37 {
38  if ( !QCA::isSupported( CIPHER_SIGNATURE, CIPHER_PROVIDER ) )
39  {
40  qDebug( "Authentication system DISABLED: QCA's qca-ossl (OpenSSL) plugin is missing" );
41  return true;
42  }
43  return false;
44 }
45 
46 const QString QgsAuthCrypto::encrypt( const QString& pass, const QString& cipheriv, const QString& text )
47 {
49  return QString();
50 
51  return encryptdecrypt( pass, cipheriv, text, true );
52 }
53 
54 const QString QgsAuthCrypto::decrypt( const QString& pass, const QString& cipheriv, const QString& text )
55 {
57  return QString();
58 
59  return encryptdecrypt( pass, cipheriv, text, false );
60 }
61 
62 static QCA::SymmetricKey passwordKey_( const QString& pass, const QCA::InitializationVector& salt )
63 {
64  QCA::SecureArray passarray( QByteArray( pass.toUtf8().constData() ) );
65  QCA::SecureArray passhash( QCA::Hash( PASSWORD_HASH_ALGORITHM ).hash( passarray ) );
66  return QCA::PBKDF2().makeKey( passhash, salt, KEY_GEN_LENGTH, KEY_GEN_ITERATIONS );
67 }
68 
69 void QgsAuthCrypto::passwordKeyHash( const QString& pass, QString *salt, QString *hash, QString *cipheriv )
70 {
72  return;
73 
74  QCA::InitializationVector saltiv = QCA::InitializationVector( KEY_GEN_IV_LENGTH );
75  QCA::SymmetricKey key = passwordKey_( pass, saltiv );
76 
77  if ( !key.isEmpty() )
78  {
79  *salt = QCA::arrayToHex( saltiv.toByteArray() );
80  qDebug( "salt hex: %s", qPrintable( *salt ) );
81 
82  *hash = QCA::arrayToHex( key.toByteArray() );
83  qDebug( "hash hex: %s", qPrintable( *hash ) );
84 
85  if ( cipheriv )
86  {
87  *cipheriv = QCA::arrayToHex( QCA::InitializationVector( CIPHER_IV_LENGTH ).toByteArray() );
88  qDebug( "cipheriv hex: %s", qPrintable( *cipheriv ) );
89  }
90  }
91 }
92 
94  const QString& salt,
95  const QString& hash,
96  QString *hashderived )
97 {
99  return false;
100 
101  QCA::InitializationVector saltiv( QCA::hexToArray( salt ) );
102  QString derived( QCA::arrayToHex( passwordKey_( pass, saltiv ).toByteArray() ) );
103 
104  if ( hashderived )
105  {
106  *hashderived = derived;
107  }
108 
109  return hash == derived;
110 }
111 
112 QString QgsAuthCrypto::encryptdecrypt( const QString& passstr,
113  const QString& cipheriv,
114  const QString& textstr,
115  bool encrypt )
116 {
117  QString outtxt = QString();
119  return outtxt;
120 
121  QCA::InitializationVector iv( QCA::hexToArray( cipheriv ) );
122 
123  QCA::SymmetricKey key( QCA::SecureArray( QByteArray( passstr.toUtf8().constData() ) ) );
124 
125  if ( encrypt )
126  {
127  QCA::Cipher cipher = QCA::Cipher( CIPHER_TYPE, CIPHER_MODE, CIPHER_PADDING,
128  QCA::Encode, key, iv,
129  CIPHER_PROVIDER );
130 
131  QCA::SecureArray securedata( textstr.toUtf8() );
132  QCA::SecureArray encrypteddata( cipher.process( securedata ) );
133  if ( !cipher.ok() )
134  {
135  qDebug( "Encryption failed!" );
136  return outtxt;
137  }
138  outtxt = QCA::arrayToHex( encrypteddata.toByteArray() );
139  // qDebug( "Encrypted hex: %s", qPrintable( outtxt ) );
140  }
141  else
142  {
143  QCA::Cipher cipher = QCA::Cipher( CIPHER_TYPE, CIPHER_MODE, CIPHER_PADDING,
144  QCA::Decode, key, iv,
145  CIPHER_PROVIDER );
146 
147  QCA::SecureArray ciphertext( QCA::hexToArray( textstr ) );
148  QCA::SecureArray decrypteddata( cipher.process( ciphertext ) );
149  if ( !cipher.ok() )
150  {
151  qDebug( "Decryption failed!" );
152  return outtxt;
153  }
154 
155  outtxt = QString( decrypteddata.toByteArray() );
156  // qDebug( "Decrypted text %s", qPrintable( outtxt ) ); // DO NOT LEAVE THIS LINE UNCOMMENTED
157  }
158 
159  return outtxt;
160 }
#define CIPHER_TYPE
static bool verifyPasswordKeyHash(const QString &pass, const QString &salt, const QString &hash, QString *hashderived=0)
Verify existing master password hash to a re-generated one.
const char * constData() const
#define CIPHER_PROVIDER
#define KEY_GEN_ITERATIONS
#define CIPHER_SIGNATURE
#define KEY_GEN_IV_LENGTH
#define KEY_GEN_LENGTH
#define PASSWORD_HASH_ALGORITHM
static void passwordKeyHash(const QString &pass, QString *salt, QString *hash, QString *cipheriv=0)
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 QCA::SymmetricKey passwordKey_(const QString &pass, const QCA::InitializationVector &salt)
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
QByteArray toUtf8() const