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