Completed
Push — master ( b7aa3a...e48183 )
by Michael
02:09
created

Mcrypt::encrypt()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 25
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 25
ccs 7
cts 7
cp 1
rs 8.8571
cc 2
eloc 9
nc 2
nop 6
crap 2
1
<?php
2
3
/**
4
 * Mcrypt.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
 * Symmetric Mcrypt wrapper functions.
19
 * 
20
 * Features:
21
 *     - PKCS #7 padding of messages
22
 *     - random IV selection
23
 *     - checksum validation with HMAC
24
 *     - tested to be compatible with many ciphers, modes and hashing algorithms.
25
 *     - highly customizable, but default options are most secure
26
 *
27
 * @category Dcrypt
28
 * @package  Dcrypt
29
 * @author   Michael Meyer (mmeyer2k) <[email protected]>
30
 * @license  http://opensource.org/licenses/MIT The MIT License (MIT)
31
 * @link     https://github.com/mmeyer2k/dcrypt
32
 * @link     https://apigen.ci/github/mmeyer2k/dcrypt/namespace-Dcrypt.html
33
 */
34
final class Mcrypt extends Cryptobase
35
{
36
37
    /**
38
     * Decrypt cyphertext
39
     * 
40
     * @param string $cyphertext Cypher text to decrypt
41
     * @param string $password   Password that should be used to decrypt input data
42
     * @param int    $cost       Number of HMAC iterations to perform on key
43
     * @param string $cipher     Mcrypt cipher
44
     * @param string $mode       Mcrypt mode
45
     * @param string $algo       Hashing algorithm to use for internal operations
46
     * 
47
     * @return string|boolean Returns false on checksum validation failure
48
     */
49 4
    public static function decrypt($cyphertext, $password, $cost = 0, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC, $algo = 'sha256')
50
    {
51
        // Determine that size of the IV in bytes
52 4
        $ivsize = \mcrypt_get_iv_size($cipher, $mode);
53
54
        // Find the IV at the beginning of the cypher text
55 4
        $iv = Str::substr($cyphertext, 0, $ivsize);
56
57
        // Gather the checksum portion of the cypher text
58 4
        $chksum = Str::substr($cyphertext, $ivsize, Str::hashSize($algo));
59
60
        // Gather message portion of cyphertext after iv and checksum
61 4
        $message = Str::substr($cyphertext, $ivsize + Str::hashSize($algo));
62
63
        // Derive key from password
64 4
        $key = self::key($password, $iv, $cost, $cipher, $mode, $algo);
65
66
        // Calculate verification checksum
67 4
        $verify = self::checksum($message, $iv, $key, $cipher, $mode, $algo);
68
69
        // If checksum could not be verified return false
70 4
        self::checksumVerify($verify, $chksum);
71
72
        // Decrypt unpad return
73 4
        return Pkcs7::unpad(\mcrypt_decrypt($cipher, $key, $message, $mode, $iv));
74
    }
75
76
    /**
77
     * Encrypt plaintext
78
     * 
79
     * @param string $plaintext Plaintext string to encrypt
80
     * @param string $password  Key used to encrypt data
81
     * @param int    $cost      Number of HMAC iterations to perform on key
82
     * @param string $cipher    Mcrypt cipher
83
     * @param string $mode      Mcrypt mode
84
     * @param string $algo      Hashing algorithm to use for internal operations
85
     * 
86
     * @return string 
87
     */
88 1
    public static function encrypt($plaintext, $password, $cost = 0, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC, $algo = 'sha256')
89
    {
90
        // Pad the input string to a multiple of block size
91 1
        $padded = Pkcs7::pad($plaintext, \mcrypt_get_block_size($cipher, $mode));
92
93
        // Generate IV of appropriate size
94 1
        $iv = Random::bytes(\mcrypt_get_iv_size($cipher, $mode));
95
96
        // Derive key from password
97 1
        $key = self::key($password, $iv, $cost, $cipher, $mode, $algo);
98
99
        // Encrypt the plaintext
100 1
        $message = \mcrypt_encrypt($cipher, $key, $padded, $mode, $iv);
101
        
102
        // If message could not be encrypted then throw an exception
103 1
        if ($message === false) {
104
            throw new \exception('Could not encrypt the data.');
105
        }
106 1
107
        // Create the cypher text prefix (iv + checksum)
108
        $prefix = $iv . self::checksum($message, $iv, $key, $cipher, $mode, $algo);
109
110
        // Return prefix + cyphertext
111
        return $prefix . $message;
112
    }
113
114
}
115