Completed
Push — master ( 3e460a...170823 )
by Michael
06:32 queued 05:08
created

AesCbc::decrypt()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 23
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 23
rs 9.0856
cc 1
eloc 8
nc 1
nop 3
1
<?php
2
3
/**
4
 * AesCbc.php
5
 * 
6
 * PHP version 7
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 AES-256-CBC encryption functions powered by OpenSSL.
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 AesCbc extends Aes
28
{
29
    /**
30
     * AES-256 cipher identifier that will be passed to openssl
31
     * 
32
     * @var string
33
     */
34
    const CIPHER = 'aes-256-cbc';
35
36
    /**
37
     * Decrypt cyphertext
38
     *
39
     * @param string $cyphertext Cyphertext to decrypt
40
     * @param string $password   Password that should be used to decrypt input data
41
     * @param int    $cost       Number of extra HMAC iterations to perform on key
42
     *
43
     * @return string
44
     */
45
    public static function decrypt(string $cyphertext, string $password, int $cost = 0): string
46
    {
47
        // Find the IV at the beginning of the cypher text
48
        $ivr = Str::substr($cyphertext, 0, self::IVSIZE);
49
50
        // Derive key from password
51
        $key = self::key($password, $ivr, $cost, self::mode());
52
53
        // Gather the checksum portion of the cypher text
54
        $sum = Str::substr($cyphertext, self::IVSIZE, self::CKSIZE);
55
56
        // Gather message portion of cyphertext after iv and checksum
57
        $msg = Str::substr($cyphertext, self::IVSIZE + self::CKSIZE);
58
59
        // Calculate verification checksum
60
        $chk = self::checksum($msg, $ivr, $key, self::mode());
61
62
        // Verify HMAC before decrypting
63
        self::checksumVerify($chk, $sum);
64
65
        // Decrypt message and return
66
        return \openssl_decrypt($msg, static::CIPHER, $key, 1, $ivr);
67
    }
68
69
    /**
70
     * Encrypt plaintext
71
     *
72
     * @param string $plaintext Plaintext string to encrypt.
73
     * @param string $password  Password used to encrypt data.
74
     * @param int    $cost      Number of extra HMAC iterations to perform on key
75
     *
76
     * @return string
77
     */
78
    public static function encrypt(string $plaintext, string $password, int $cost = 0): string
79
    {
80
        // Generate IV of appropriate size.
81
        $ivr = \random_bytes(self::IVSIZE);
82
83
        // Derive key from password
84
        $key = self::key($password, $ivr, $cost, self::mode());
85
86
        // Encrypt the plaintext
87
        $msg = \openssl_encrypt($plaintext, static::CIPHER, $key, 1, $ivr);
88
89
        // If message could not be encrypted then throw an exception
90
        if ($msg === false) {
91
            throw new \exception('Could not encrypt the data.'); // @codeCoverageIgnore
92
        }
93
94
        // Create the cypher text prefix (iv + checksum)
95
        $prefix = $ivr . self::checksum($msg, $ivr, $key, self::mode());
96
97
        // Return prefix + cyphertext
98
        return $prefix . $msg;
99
    }
100
}
101