Issues (2)

src/Helpers/SymmetricEncryptionHelper.php (1 issue)

Severity
1
<?php
2
3
namespace Smoren\EncryptionTools\Helpers;
4
5
use Smoren\EncryptionTools\Exceptions\JsonException;
6
use Smoren\EncryptionTools\Exceptions\SymmetricEncryptionException;
7
8
/**
9
 * Class SymmetricEncryptionHelper
10
 * @author Smoren <[email protected]>
11
 */
12
class SymmetricEncryptionHelper
13
{
14
    /**
15
     * Returns data encrypted by secret key
16
     * @param mixed $data data to encrypt
17
     * @param string $secretKey secret key
18
     * @param string $cipherMethod encryption method
19
     * @return string encrypted data
20
     * @throws SymmetricEncryptionException
21
     * @throws JsonException
22
     */
23
    public static function encrypt($data, string $secretKey, string $cipherMethod = 'aes-256-cbc'): string
24
    {
25
        static::checkCipherMethodAvailable($cipherMethod);
26
        $data = JsonHelper::encode($data);
27
28
        $ivLen = openssl_cipher_iv_length($cipherMethod);
29
        if($ivLen === false) {
30
            throw new SymmetricEncryptionException(
31
                'openssl_cipher_iv_length() returned false',
32
                SymmetricEncryptionException::OPENSSL_ERROR
33
            );
34
        }
35
        $iv = openssl_random_pseudo_bytes($ivLen);
36
        if(!$iv) {
37
            throw new SymmetricEncryptionException(
38
                'openssl_random_pseudo_bytes() returned false',
39
                SymmetricEncryptionException::OPENSSL_ERROR
40
            );
41
        }
42
        $cipherText = openssl_encrypt($data, $cipherMethod, $secretKey, OPENSSL_RAW_DATA, $iv);
43
        if($cipherText === false) {
44
            throw new SymmetricEncryptionException(
45
                'openssl_encrypt() returned false',
46
                SymmetricEncryptionException::OPENSSL_ERROR
47
            );
48
        }
49
        $hmac = hash_hmac('sha256', $cipherText, $secretKey, true);
50
51
        return base64_encode($iv.$hmac.$cipherText);
52
    }
53
54
    /**
55
     * Returns data decrypted by secret key
56
     * @param string $encryptedData data to decrypt
57
     * @param string $secretKey secret key
58
     * @param string $cipherMethod encryption method
59
     * @return mixed decrypted data
60
     * @throws SymmetricEncryptionException
61
     */
62
    public static function decrypt(string $encryptedData, string $secretKey, string $cipherMethod = 'aes-256-cbc')
63
    {
64
        static::checkCipherMethodAvailable($cipherMethod);
65
66
        $c = base64_decode($encryptedData);
67
        $ivLen = openssl_cipher_iv_length($cipherMethod);
68
        if($ivLen === false) {
69
            throw new SymmetricEncryptionException(
70
                'openssl_cipher_iv_length() returned false',
71
                SymmetricEncryptionException::OPENSSL_ERROR
72
            );
73
        }
74
        $iv = substr($c, 0, $ivLen);
75
        $hmac = substr($c, $ivLen, $sha2len=32);
0 ignored issues
show
The assignment to $hmac is dead and can be removed.
Loading history...
76
        $cipherText = substr($c, $ivLen+$sha2len);
77
78
        $data = openssl_decrypt($cipherText, $cipherMethod, $secretKey, OPENSSL_RAW_DATA, $iv);
79
80
        if($data === false) {
81
            throw new SymmetricEncryptionException(
82
                'incorrect secret key',
83
                SymmetricEncryptionException::CANNOT_DECRYPT
84
            );
85
        }
86
        return json_decode($data, true);
87
    }
88
89
    /**
90
     * Returns list of available encryption methods
91
     * @return array<string>
92
     */
93
    public static function getCipherMethodList(): array
94
    {
95
        return openssl_get_cipher_methods();
96
    }
97
98
    /**
99
     * Checks if encryption method available
100
     * @param string $cipherMethod encryption method
101
     * @throws SymmetricEncryptionException if method is unavailable
102
     */
103
    public static function checkCipherMethodAvailable(string $cipherMethod): void
104
    {
105
        if(!in_array($cipherMethod, static::getCipherMethodList(), true)) {
106
            throw new SymmetricEncryptionException(
107
                "unknown cipher method '{$cipherMethod}'",
108
                SymmetricEncryptionException::UNKNOWN_METHOD
109
            );
110
        }
111
    }
112
}
113