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