]> git.mxchange.org Git - core.git/blob - framework/main/classes/crypto/class_CryptoHelper.php
Continued:
[core.git] / framework / main / classes / crypto / class_CryptoHelper.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Helper\Crypto;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Bootstrap\FrameworkBootstrap;
7 use Org\Mxchange\CoreFramework\Crypto\Cryptable;
8 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
9 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
10
11 /**
12  * A helper class for cryptographical things like hashing passwords and so on
13  *
14  * @author              Roland Haeder <webmaster@shipsimu.org>
15  * @version             0.0.0
16  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2020 Core Developer Team
17  * @license             GNU GPL 3.0 or any newer version
18  * @link                http://www.shipsimu.org
19  *
20  * This program is free software: you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation, either version 3 of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program. If not, see <http://www.gnu.org/licenses/>.
32  */
33 class CryptoHelper extends BaseFrameworkSystem implements Cryptable {
34         // Exception constants
35         const EXCEPTION_ENCRYPT_MISSING = 0x1f0;
36         const EXCEPTION_ENCRYPT_INVALID = 0x1f1;
37
38         /**
39          * An instance of this own clas
40          */
41         private static $selfInstance = NULL;
42
43         /**
44          * Instance of the crypto stream
45          */
46         private $cryptoStreamInstance = NULL;
47
48         /**
49          * Salt for hashing operations
50          */
51         private $salt = '';
52
53         /**
54          * Protected constructor
55          *
56          * @return      void
57          */
58         protected function __construct () {
59                 // Call parent constructor
60                 parent::__construct(__CLASS__);
61         }
62
63         /**
64          * Creates an instance of this class
65          *
66          * @return      $cryptoInstance         An instance of this crypto helper class
67          */
68         public static final function createCryptoHelper () {
69                 // Get a new instance
70                 $cryptoInstance = new CryptoHelper();
71
72                 // Initialize the hasher
73                 $cryptoInstance->initHasher();
74
75                 // Attach a crypto stream
76                 $cryptoInstance->attachCryptoStream();
77
78                 // Return the instance
79                 return $cryptoInstance;
80         }
81
82         /**
83          * Get a singleton instance of this class
84          *
85          * @return      $selfInstance   An instance of this crypto helper class
86          */
87         public static final function getSelfInstance () {
88                 // Is no instance there?
89                 if (is_null(self::$selfInstance)) {
90                         // Then get a new one
91                         self::$selfInstance = self::createCryptoHelper();
92                 } // END - if
93
94                 // Return the instance
95                 return self::$selfInstance;
96         }
97
98         /**
99          * Attaches a crypto stream to this crypto helper by detecting loaded
100          * modules.
101          *
102          * @return      void
103          */
104         protected function attachCryptoStream () {
105                 // @TODO Maybe rewrite this with DirectoryIterator, similar to Compressor thing?
106                 // Do we have openssl/mcrypt loaded?
107                 if ($this->isPhpExtensionLoaded('mcrypt')) {
108                         // Then use it
109                         $this->cryptoStreamInstance = ObjectFactory::createObjectByName('Org\Mxchange\CoreFramework\Stream\Crypto\McryptStream', array($this->getRngInstance()));
110                 } elseif ($this->isPhpExtensionLoaded('openssl')) {
111                         // Then use it
112                         $this->cryptoStreamInstance = ObjectFactory::createObjectByName('Org\Mxchange\CoreFramework\Stream\Crypto\OpenSslStream', array($this->getRngInstance()));
113                 } else {
114                         // If nothing works ...
115                         $this->cryptoStreamInstance = ObjectFactory::createObjectByName('Org\Mxchange\CoreFramework\Stream\Crypto\NullCryptoStream');
116                 }
117         }
118
119         /**
120          * Initializes the hasher for different purposes.
121          *
122          * @return      void
123          */
124         protected function initHasher () {
125                 // Initialize the random number generator which is required by some crypto methods
126                 $this->setRngInstance(ObjectFactory::createObjectByConfiguredName('rng_class'));
127
128                 // Generate a salt for the hasher
129                 $this->generateSalt();
130         }
131
132         /**
133          * Generates the salt based on configured length
134          *
135          * @return      void
136          */
137         private function generateSalt () {
138                 // Get a random string from the RNG
139                 $randomString = $this->getRngInstance()->randomString() . $this->createUuid();
140
141                 // Get config entry for salt length
142                 $length = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('salt_length');
143
144                 // Keep only defined number of characters
145                 $this->salt = substr(sha1($randomString), -$length, $length);
146         }
147
148         /**
149          * Returns a UUID (Universal Unique IDentifier) if PECL extension uuid was
150          * found or an empty string it not.
151          *
152          * @return      $uuid   UUID with leading dash or empty string
153          */
154         public function createUuid () {
155                 // Init empty UUID
156                 $uuid = '';
157
158                 // Is the UUID extension loaded and enabled? (see pecl)
159                 if (FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('extension_uuid_loaded') === true) {
160                         // Then add it as well
161                         $uuid = uuid_create();
162                 } // END - if
163
164                 // Return it
165                 return $uuid;
166         }
167
168         /**
169          * Hashes a string with salt and returns the hash. If an old previous hash
170          * is supplied the method will use the first X chars of that hash for hashing
171          * the password. This is useful if you want to check if password is identical
172          * for authorization purposes.
173          *
174          * @param       $str            Unhashed string
175          * @param       $oldHash        A hash from previous hashed string
176          * @param       $withFixed      Whether to include a fixed salt (not recommended in p2p applications)
177          * @return      $hashed         The hashed and salted string
178          */
179         public function hashString ($str, $oldHash = '', $withFixed = true) {
180                 // Cast the string
181                 $str = (string) $str;
182
183                 // Default is the default salt ;-)
184                 $salt = $this->salt;
185
186                 // Is the old password set?
187                 if (!empty($oldHash)) {
188                         // Use the salt from hash, first get length
189                         $length = FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('salt_length');
190
191                         // Then extract the X first characters from the hash as our salt
192                         $salt = substr($oldHash, 0, $length);
193                 } // END - if
194
195                 // Hash the password with salt
196                 //* DEBUG: */ echo "salt=".$salt."/plain=".$str."<br />\n";
197                 if ($withFixed === true) {
198                         // Use additional fixed salt
199                         $hashed = $salt . md5(sprintf(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('hash_extra_mask'),
200                                 $salt,
201                                 $this->getRngInstance()->getFixedSalt(),
202                                 $str
203                         ));
204                 } else {
205                         // Use salt+string to hash
206                         $hashed = $salt . md5(sprintf(FrameworkBootstrap::getConfigurationInstance()->getConfigEntry('hash_normal_mask'),
207                                 $salt,
208                                 $str
209                         ));
210                 }
211
212                 // And return it
213                 return $hashed;
214         }
215
216         /**
217          * Encrypt the string with fixed salt
218          *
219          * @param       $str            The unencrypted string
220          * @param       $key            Optional key, if none provided, a random key will be generated
221          * @return      $encrypted      Encrypted string
222          */
223         public function encryptString ($str, $key = NULL) {
224                 // Encrypt the string through the stream
225                 $encrypted = $this->cryptoStreamInstance->encryptStream($str, $key);
226
227                 // Return the string
228                 return $encrypted;
229         }
230
231         /**
232          * Decrypt the string with fixed salt
233          *
234          * @param       $encrypted      Encrypted string
235          * @return      $str            The unencrypted string
236          */
237         public function decryptString ($encrypted) {
238                 // Encrypt the string through the stream
239                 $str = $this->cryptoStreamInstance->decryptStream($encrypted);
240
241                 // Return the string
242                 return $str;
243         }
244
245 }