Crypsic::round()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Crypsic - A Speed Metal Encryption Library For PHP
4
 *
5
 * @category   Encryption
6
 * @package    Rammy Labs
7
 *
8
 * @author     Moviet
9
 * @license    MIT Public License
10
 *
11
 * @version    Build @@version@@
12
 */
13
namespace Moviet\Heavy;
14
15
use \RuntimeException;
16
use Moviet\Heavy\Speed\Verbal;
17
use Moviet\Heavy\Exceptions\EqualsException;
18
use Moviet\Heavy\Exceptions\DecryptException;
19
20
/**
21
 * Let's Simplify
22
 */
23
class Crypsic
24
{
25
    /**
26
     * @param string key
27
     */
28
    protected static $key;
29
30
    /**
31
     * @param string key
32
     */
33
    protected static $has;
34
35
    /**
36
     * @param string password
37
     */
38
    protected static $auth;
39
40
    /**
41
    * @param string hash
42
    */
43
    protected static $hash;
44
45
    /**
46
     * @param string cipher
47
     */
48
    protected static $mode;
49
50
    /**
51
     * Check requirements
52
     * 
53
     * @throws RunTimeException; 
54
     */
55
    public function __construct()
56
    {
57
        if (!extension_loaded('openssl')) {
58
            throw new RuntimeException('Unable to load openssl extension');
59
        }
60
61
        if (!extension_loaded('mbstring')) {
62
            throw new RuntimeException('Unable to load mbstring extension');
63
        }
64
65
        if (!function_exists('hash_equals')) {
66
            throw new RuntimeException('Unable to load comparation hash function');
67
        }
68
    }
69
70
    /**
71
     * Generate key from any storage
72
     * and use a key to validate
73
     * 
74
     * @param string $key
75
     */
76
    public static function key($key)
77
    {
78
        self::$has = self::h2bin($key);
79
    }
80
81
    /**
82
     * Generate mac and build a nice salt
83
     * this is use to authenticated crypto
84
     * 
85
     * @return string
86
     */
87
    protected static function suitSalt()
88
    {
89
        return hash_hmac(
90
            Verbal::RAWKEY_ALGOS, self::$has . self::getMode(), self::$has
91
        );
92
    }
93
94
    /**
95
     * Load password from any request
96
     * 
97
     * @param string $password
98
     */
99
    public static function authKey($password)
100
    {
101
        self::$auth = (string) $password;
102
103
        return new self;
104
    }
105
106
    /**
107
     * Load data password from any storage
108
     * 
109
     * @param string $datahash
110
     */
111
    public function hash($datahash)
112
    {
113
        self::$hash = (string) $datahash;
114
115
        return $this;
116
    }
117
118
    /**
119
     * You encoded, you responsible to decoded
120
     * just make it readable yayy
121
     *  
122
     * @param string $string
123
     */
124
    public static function listen($string)
125
    {
126
        return base64_encode(self::cipherBlock($string));
127
    }
128
129
    /**
130
     * Just simply decoded the ciphertext
131
     * 
132
     * @param string $string
133
     */
134
    public static function look($string)
135
    {
136
        return self::record(base64_decode($string));
137
    }
138
139
    /**
140
     * Check what the operation modes
141
     * 
142
     * @return string
143
     */
144
    protected static function combatKey()
145
    {
146
        return self::suitSalt();
147
    }
148
149
    /**
150
     * Check parameter key if they use password
151
     * then verify the absolete if not then
152
     * we can authentify next
153
     * 
154
     * @throws Moviet\Heavy\Exceptions\EqualsException
155
     * @return bool
156
     */
157
    protected static function verify()
158
    {
159
        if (!is_null(self::$hash)) {
160
            if (!password_verify(self::$auth, self::$hash)) {
161
                throw new EqualsException('Password does not match');
162
            } 
163
        }
164
    }
165
166
    /**
167
     * Compact the string, cipher modes, a key and ivector
168
     * and just make a zig-zag onto natively
169
     * 
170
     * @param string
171
     * @param mixed
172
     * @return mixed
173
     */
174
    protected static function crypto($string, $nonce)
175
    {
176
        return openssl_encrypt(
177
            $string, self::getMode(), self::getKey(), OPENSSL_RAW_DATA, $nonce
178
        );
179
    }
180
181
    /**
182
     * Generate and compact all the chunks here
183
     * and deliver the raw crypto
184
     * 
185
     * @return mixed
186
     */
187
    protected static function cipherBlock($string)
188
    {
189
        $nonce = self::nonceCash();
190
        
191
        return $nonce . self::hmac($string, $nonce) . self::crypto($string, $nonce);
192
    }
193
194
    /**
195
     * Generate mac, salt and bandage the raw crypto
196
     * so we can get assosiated data
197
     *  
198
     * @param string
199
     * @param mixed
200
     * @return string
201
     */
202
    protected static function hmac($string, $nonce)
203
    {
204
        return hash_hmac(
205
            Verbal::HMAC_GIVER, self::crypto($string, $nonce), self::combatKey(), true
206
        );
207
    }
208
209
    /**
210
     * Generate initial vector for spesific cipher
211
     * 
212
     * @return mixed
213
     */
214
    protected static function nonceCash()
215
    {
216
        if (!function_exists('random_bytes')) {
217
            return openssl_random_pseudo_bytes(openssl_cipher_iv_length(self::getMode()));
218
219
        } else {
220
            return random_bytes(openssl_cipher_iv_length(self::getMode()));
221
        }
222
    }
223
224
    /**
225
     * Now we check the mac for something called 'noin bullet'  
226
     * then check what the key that was generated
227
     * if they use a password so we must proof it
228
     * and compare the spesific length
229
     * 
230
     * @param string $string
231
     * @throws Moviet\Heavy\Exceptions\EqualsException
232
     * @throws Moviet\Heavy\Exceptions\DecryptException
233
     * @return mixed
234
     */
235
    protected static function record($string)
236
    {		
237
        if (!hash_equals(self::compare($string), self::screw($string))) {
238
            throw new EqualsException('You have invalid data');
239
        }
240
241
        if (self::verify() !== false) {
242
            return openssl_decrypt(
243
                self::round($string), self::getMode(), self::$has, OPENSSL_RAW_DATA, self::rotate($string)
244
            );
245
246
        } else {
247
            throw new DecryptException("You can not decrypt invalid data");
248
        }
249
    }
250
251
    /**
252
     * Here the bytes crypto must not be invalid
253
     * 
254
     * @return mixed
255
     */
256
    protected static function rotate($string)
257
    {
258
        return mb_substr(
259
            $string, Verbal::ZERO_BITS_FIXED, Verbal::MIN_BYTES_SIZE, Verbal::CHBYTES
260
        );
261
    }
262
263
    /**
264
     * Screw up the bytes size to compare
265
     * 
266
     * @return mixed
267
     */
268
    protected static function screw($string)
269
    {
270
        return mb_substr(
271
            $string, Verbal::MIN_BYTES_SIZE, Verbal::MAX_BYTES_SIZE, Verbal::CHBYTES
272
        );
273
    }
274
275
    /**
276
     * Round up the crypto in spesific length
277
     * 
278
     * @return mixed
279
     */
280
    protected static function round($string)
281
    {
282
        return mb_substr(
283
            $string, Verbal::BYTES_CONVERSION, Verbal::KEEP_BYTES_CLEAN, Verbal::CHBYTES
284
        );
285
    }
286
287
    /**
288
     * Now we host an assosiated salt
289
     * to authenticate the data
290
     * 
291
     * @return mixed
292
     */
293
    protected static function compare($string)
294
    {
295
        return hash_hmac(
296
            Verbal::HMAC_GIVER, self::round($string), self::combatKey(), true
297
        );
298
    }
299
300
    /**
301
     * Calculate key for acceptable cipher mode
302
     * 
303
     * @param string $key
304
     * @return int
305
     */
306
    protected static function guideKey($key)
307
    {
308
        $length = mb_strlen($key, Verbal::CHBYTES);
309
310
        if ($length <=> self::calcKey() && self::calcKey() == Verbal::MIN_CIPHER_SIZE) {
311
            $total = Verbal::MIN_BYTES_SIZE;
312
313
        } elseif ($length <=> self::calcKey() && self::calcKey() == Verbal::MEDIUM_CIPHER_SIZE) {
314
            $total = Verbal::MEDIUM_BYTES_SIZE;
315
316
        } else {
317
            $total = Verbal::MAX_BYTES_SIZE;
318
        }
319
320
        return $total;
321
    }
322
323
    /**
324
     * Set cooperative cipher mode
325
     * 
326
     * @param string $cipher
327
     */
328
    public static function mode($cipher)
329
    {
330
        self::$mode = Verbal::BLOCK_MODE[$cipher];
331
    }
332
333
    /**
334
     * Get cipher mode, if nothing, set to default mode
335
     * 
336
     * @return string
337
     */
338
    protected static function getMode()
339
    {
340
        if (isset(self::$mode)) {
341
            $setmode = self::$mode;
342
343
        } else {
344
            $setmode = Verbal::BLOCK_MODE[Verbal::DEFAULT_MODE];
345
        }			
346
347
        return $setmode;
348
    }
349
350
    /**
351
     * Checking cipher operation mode
352
     * 
353
     * @return int
354
     */
355
    protected static function calcKey()
356
    {
357
        return preg_replace('/[^0-9]/','', self::getMode());
0 ignored issues
show
Bug Best Practice introduced by
The expression return preg_replace('/[^...', '', self::getMode()) returns the type string which is incompatible with the documented return type integer.
Loading history...
358
    }
359
360
    /**
361
     * We must generate a readable key
362
     * 
363
     * @param string $length
364
     * @return string
365
     */
366
    protected static function b2hex($length)
367
    {
368
        return bin2hex($length);
369
    }
370
371
    /**
372
     * We must reverse the key to generate cipher
373
     * and get the requirement length
374
     * 
375
     * @param string $length
376
     * @return string
377
     */
378
    protected static function h2bin($length)
379
    {
380
        return hex2bin($length);
381
    }
382
383
    /**
384
     * Generate random key with minimum requirement
385
     * if a length does look badass, says 4 bytes
386
     * we prevent with calculation and make it readable
387
     * 
388
     * @param string $key
389
     * @return string
390
     */
391
    public static function saveKey($key)
392
    {
393
        if (!function_exists('random_bytes')) {
394
            self::$key = self::b2hex(openssl_random_pseudo_bytes(self::guideKey($key)));
395
396
        } else {
397
            self::$key = self::b2hex(random_bytes(self::guideKey($key)));
398
        }
399
400
        return self::$key;
401
    }
402
403
    /**
404
     * Get key to generate crypto
405
     * 
406
     * @return mixed
407
     */
408
    protected static function getKey()
409
    {
410
        return self::h2bin(self::$key);
411
    }
412
}
413