Completed
Push — master ( 9caefd...b7aa3a )
by Michael
02:53
created

Aes::encrypt()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2.0078

Importance

Changes 4
Bugs 0 Features 0
Metric Value
c 4
b 0
f 0
dl 0
loc 22
ccs 7
cts 8
cp 0.875
rs 9.2
cc 2
eloc 8
nc 2
nop 3
crap 2.0078
1
<?php
2
3
/**
4
 * Aes.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 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 Aes extends Cryptobase
28
{
29
30
    /**
31
     * AES-256 cipher identifier that will be passed to openssl
32
     * 
33
     * @var string
34
     */
35
    const CIPHER = 'aes-256-cbc';
36
37
    /**
38
     * Size of initialization vector in bytes
39
     * 
40
     * @var int
41
     */
42
    const IVSIZE = 16;
43
44
    /**
45
     * Size of checksum in bytes
46
     * 
47
     * @var int
48
     */
49
    const CKSIZE = 32;
50
    
51
    /**
52
     * This string is used when hashing to ensure cross compatibility between
53
     * dcrypt\mcrypt and dcrypt\aes.
54
     */
55
    const RIJNDA = 'rijndael-128';
56
57
    /**
58
     * Decrypt cyphertext
59
     * 
60
     * @param string $cyphertext Cyphertext to decrypt
61
     * @param string $password   Password that should be used to decrypt input data
62
     * @param int    $cost       Number of extra HMAC iterations to perform on key
63
     * 
64
     * @return string
65
     */
66 8
    public static function decrypt($cyphertext, $password, $cost = 0)
67
    {
68
        // Find the IV at the beginning of the cypher text
69 8
        $iv = Str::substr($cyphertext, 0, self::IVSIZE);
70
71
        // Gather the checksum portion of the cypher text
72 8
        $chksum = Str::substr($cyphertext, self::IVSIZE, self::CKSIZE);
73
74
        // Gather message portion of cyphertext after iv and checksum
75 8
        $message = Str::substr($cyphertext, self::IVSIZE + self::CKSIZE);
76
77
        // Derive key from password
78 8
        $key = self::key($password, $iv, $cost, self::RIJNDA, self::mode());
79
80
        // Calculate verification checksum
81 8
        $verify = self::checksum($message, $iv, $key, self::RIJNDA, self::mode());
82
83
        // Verify HMAC before decrypting
84 8
        self::checksumVerify($verify, $chksum);
85
86
        // Decrypt message and return
87 6
        return \openssl_decrypt($message, static::CIPHER, $key, 1, $iv);
88
    }
89
90
    /**
91
     * Encrypt plaintext
92
     * 
93
     * @param string $plaintext Plaintext string to encrypt.
94
     * @param string $password  Password used to encrypt data.
95
     * @param int    $cost      Number of extra HMAC iterations to perform on key
96
     * 
97
     * @return string 
98
     */
99 7
    public static function encrypt($plaintext, $password, $cost = 0)
100
    {
101
        // Generate IV of appropriate size.
102 7
        $iv = Random::bytes(self::IVSIZE);
103
104
        // Derive key from password
105 7
        $key = self::key($password, $iv, $cost, self::RIJNDA, self::mode());
106
107
        // Encrypt the plaintext
108 7
        $message = \openssl_encrypt($plaintext, static::CIPHER, $key, 1, $iv);
109
        
110
        // If message could not be encrypted then throw an exception
111 7
        if ($message === false) {
112
            throw new \exception('Could not encrypt the data.');
113
        }
114
115
        // Create the cypher text prefix (iv + checksum)
116 7
        $prefix = $iv . self::checksum($message, $iv, $key, self::RIJNDA, self::mode());
117
118
        // Return prefix + cyphertext
119 7
        return $prefix . $message;
120
    }
121
122
    /**
123
     * Return the encryption mode string. "cbc" or "ctr"
124
     * 
125
     * @return string
126
     */
127 9
    protected static function mode()
128
    {
129 9
        return substr(static::CIPHER, -3);
130
    }
131
132
}
133