Completed
Push — master ( ee148f...3aab2e )
by Michael
02:37
created

Cryptobase::checksum()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 9
ccs 3
cts 3
cp 1
rs 9.6666
cc 1
eloc 3
nc 1
nop 6
crap 1
1
<?php
2
3
/**
4
 * Cryptobase.php
5
 * 
6
 * PHP version 5
7
 * 
8
 * @category Dcrypt
9
 * @package  Dcrypt
10
 * @author   Michael Meyer (mmeyer2k) <[email protected]>
11
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
12
 * @link     https://github.com/mmeyer2k/dcrypt
13
 */
14
15
namespace Dcrypt;
16
17
/**
18
 * Provides functionality common to Dcrypt's block ciphers.
19
 * 
20
 * @category Dcrypt
21
 * @package  Dcrypt
22
 * @author   Michael Meyer (mmeyer2k) <[email protected]>
23
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
24
 * @link     https://github.com/mmeyer2k/dcrypt
25
 * @link     https://apigen.ci/github/mmeyer2k/dcrypt/namespace-Dcrypt.html
26
 */
27
class Cryptobase
28
{
29
30
    /**
31
     * Create a message authentication checksum.
32
     * 
33
     * @param string $cyphertext Cyphertext that needs a check sum.
34
     * @param string $iv         Initialization vector.
35
     * @param string $key        HMAC key
36
     * @param string $cipher     Mcrypt cipher
37
     * @param string $mode       Mcrypt mode
38
     * @param string $algo       Hashing algorithm to use for internal operations
39
     * 
40
     * @return string
41
     */
42 6
    protected static function checksum($cyphertext, $iv, $key, $cipher = 'rijndael-128', $mode = 'cbc', $algo = 'sha256')
43
    {
44
        // Prevent potentially large string concat by hmac-ing the cyphertext
45
        // by itself...
46 6
        $sum = \hash_hmac($algo, $cyphertext, $key, true);
47
48
        // ... then hash other elements with previous hmac and return
49 6
        return \hash_hmac($algo, $sum . $iv . $mode . $cipher, $key, true);
50
    }
51
52
    /**
53
     * This will normalize a hash to a certain length by extending it if
54
     * too short and truncating it if too long. This ensures that any
55
     * hash algo will work with any combination of other settings. However,
56
     * it is probably best to make sure that the keysize and algo size
57
     * are identical so that the input hash passes through unchanged.
58
     * 
59
     * @param string $hash Hash to be normalized
60
     * @param int    $size Size of the desired output hash, in bytes
61
     * @param string $algo Hashing algorithm to use for internal operations
62
     * 
63
     * @return string
64
     */
65 6
    protected static function hashNormalize($hash, $size, $algo)
66
    {
67
        // Extend hash if too short
68 6
        while (Str::strlen($hash) < $size) {
69 1
            $hash .= \hash($algo, $hash, true);
70 1
        }
71
72
        // Truncate to specified number of bytes (if needed) and return
73 6
        return Str::substr($hash, 0, $size);
74
    }
75
76
    /**
77
     * Determine the length of the output of a given hash algorithm in bytes.
78
     * 
79
     * @param string $algo Name of algorithm to look up
80
     * 
81
     * @return int
82
     */
83 10
    protected static function hashSize($algo)
84
    {
85 10
        return Str::strlen(\hash($algo, 'hash me', true));
86
    }
87
88
    /**
89
     * Transform password into key and perform iterative HMAC
90
     * 
91
     * @param string $password Encryption key
92
     * @param string $iv       Initialization vector
93
     * @param int    $cost     Number of HMAC iterations to perform on key
94
     * @param string $cipher   Mcrypt cipher
95
     * @param string $mode     Mcrypt block mode
96
     * @param string $algo     Hashing algorithm to use for internal operations
97
     * 
98
     * @return string
99
     */
100 6
    protected static function key($password, $iv, $cost, $cipher = 'rijndael-128', $mode = 'cbc', $algo = 'sha256')
101
    {
102
        // This if statement allows the usage of the Openssl library without
103
        // the need to have the mcrypt plugin installed at all.
104 6
        if ($mode === 'cbc' && $cipher === 'rijndael-128') {
105 6
            $keysize = 32;
106 6
        } else {
107 1
            $keysize = \mcrypt_get_key_size($cipher, $mode);
108
        }
109
110
        // Perform key derivation
111 6
        $key = Hash::ihmac($password . $iv, $password, $cost, $algo);
112
113
        // Return hash normalized to key length
114 6
        return self::hashNormalize($key, $keysize, $algo);
115
    }
116
117
    protected static function checksumVerify($calculated, $supplied)
118
    {
119
        if (!Str::equal($calculated, $supplied)) {
120
            $e = 'Decryption can not proceed due to invalid cyphertext checksum.';
121
            throw new \InvalidArgumentException($e);
122
        }
123
    }
124
125
}
126