encryptByPublicKey()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 2 Features 1
Metric Value
eloc 10
c 3
b 2
f 1
dl 0
loc 15
rs 9.9332
cc 2
nc 2
nop 3
1
<?php
2
3
namespace Smoren\EncryptionTools\Helpers;
4
5
use Smoren\EncryptionTools\Exceptions\AsymmetricEncryptionException;
6
use Smoren\EncryptionTools\Exceptions\JsonException;
7
use Smoren\EncryptionTools\Exceptions\SymmetricEncryptionException;
8
9
/**
10
 * Class AsymmetricLargeDataEncryptionHelper
11
 * @author Smoren <[email protected]>
12
 */
13
class AsymmetricLargeDataEncryptionHelper
14
{
15
    /**
16
     * Generates RSA key pair
17
     * @return string[] [$privateKey, $publicKey]
18
     * @throws AsymmetricEncryptionException
19
     */
20
    public static function generateKeyPair(): array
21
    {
22
        return AsymmetricEncryptionHelper::generateKeyPair();
23
    }
24
25
    /**
26
     * Returns data encrypted by public key
27
     * @param mixed $data data to encrypt
28
     * @param string $publicKey public key
29
     * @return string encrypted data
30
     * @throws AsymmetricEncryptionException
31
     * @throws JsonException
32
     */
33
    public static function encryptByPublicKey($data, string $publicKey, int $internalKeyLength = 128): string
34
    {
35
        $internalKey = static::generateRandomString($internalKeyLength);
36
        $internalKeyEncrypted = AsymmetricEncryptionHelper::encryptByPublicKey($internalKey, $publicKey);
37
        try {
38
            $dataEncrypted = SymmetricEncryptionHelper::encrypt($data, $internalKey);
39
        } catch(SymmetricEncryptionException $e) {
40
            throw new AsymmetricEncryptionException(
41
                'cannot encrypt',
42
                AsymmetricEncryptionException::CANNOT_ENCRYPT,
43
                $e
44
            );
45
        }
46
47
        return strlen($internalKeyEncrypted).'_'.$internalKeyEncrypted.$dataEncrypted;
48
    }
49
50
    /**
51
     * Returns data encrypted by private key
52
     * @param mixed $data data to encrypt
53
     * @param string $privateKey public key
54
     * @return string encrypted data
55
     * @throws AsymmetricEncryptionException
56
     * @throws JsonException
57
     */
58
    public static function encryptByPrivateKey($data, string $privateKey, int $internalKeyLength = 128): string
59
    {
60
        $internalKey = static::generateRandomString($internalKeyLength);
61
        $internalKeyEncrypted = AsymmetricEncryptionHelper::encryptByPrivateKey($internalKey, $privateKey);
62
        try {
63
            $dataEncrypted = SymmetricEncryptionHelper::encrypt($data, $internalKey);
64
        } catch(SymmetricEncryptionException $e) {
65
            throw new AsymmetricEncryptionException(
66
                'cannot encrypt',
67
                AsymmetricEncryptionException::CANNOT_ENCRYPT,
68
                $e
69
            );
70
        }
71
72
        return strlen($internalKeyEncrypted).'_'.$internalKeyEncrypted.$dataEncrypted;
73
    }
74
75
    /**
76
     * Returns data decrypted by public key
77
     * @param string $dataEncrypted data to decrypt
78
     * @param string $publicKey public key
79
     * @return mixed decrypted data
80
     * @throws AsymmetricEncryptionException
81
     */
82
    public static function decryptByPublicKey(string $dataEncrypted, string $publicKey)
83
    {
84
        $matches = static::getPrefixMatches($dataEncrypted);
85
86
        $internalKeyEncrypted = substr($dataEncrypted, $matches[0], $matches[1]);
87
        /** @var string $internalKeyDecrypted */
88
        $internalKeyDecrypted = AsymmetricEncryptionHelper::decryptByPublicKey($internalKeyEncrypted, $publicKey);
89
        $dataPartEncrypted = substr($dataEncrypted, $matches[0]+$matches[1]);
90
91
        try {
92
            return SymmetricEncryptionHelper::decrypt($dataPartEncrypted, $internalKeyDecrypted);
93
        } catch(SymmetricEncryptionException $e) {
94
            throw new AsymmetricEncryptionException(
95
                'cannot decrypt',
96
                AsymmetricEncryptionException::CANNOT_DECRYPT,
97
                $e
98
            );
99
        }
100
    }
101
102
    /**
103
     * Returns data decrypted by private key
104
     * @param string $dataEncrypted data to decrypt
105
     * @param string $privateKey private key
106
     * @return mixed decrypted data
107
     * @throws AsymmetricEncryptionException
108
     */
109
    public static function decryptByPrivateKey(string $dataEncrypted, string $privateKey)
110
    {
111
        $matches = static::getPrefixMatches($dataEncrypted);
112
113
        $internalKeyEncrypted = substr($dataEncrypted, $matches[0], $matches[1]);
114
        /** @var string $internalKeyDecrypted */
115
        $internalKeyDecrypted = AsymmetricEncryptionHelper::decryptByPrivateKey($internalKeyEncrypted, $privateKey);
116
        $dataPartEncrypted = substr($dataEncrypted, $matches[0]+$matches[1]);
117
118
        try {
119
            return SymmetricEncryptionHelper::decrypt($dataPartEncrypted, $internalKeyDecrypted);
120
        } catch(SymmetricEncryptionException $e) {
121
            throw new AsymmetricEncryptionException(
122
                'cannot decrypt',
123
                AsymmetricEncryptionException::CANNOT_DECRYPT,
124
                $e
125
            );
126
        }
127
    }
128
129
    /**
130
     * Internal function-helper for decrypting
131
     * @param string $dataEncrypted encrypted data
132
     * @return array<int> [int, int]
133
     * @throws AsymmetricEncryptionException
134
     */
135
    protected static function getPrefixMatches(string $dataEncrypted): array
136
    {
137
        preg_match('/^([0-9]+)_/', $dataEncrypted, $matches);
138
        if(!isset($matches[1])) {
139
            throw new AsymmetricEncryptionException('cannot decrypt', AsymmetricEncryptionException::CANNOT_DECRYPT);
140
        }
141
        $matches[0] = strlen($matches[0]);
142
143
        return [$matches[0], (int)$matches[1]];
144
    }
145
146
    /**
147
     * Generates random string
148
     * @param int $length string length
149
     * @return string random string
150
     */
151
    protected static function generateRandomString(int $length): string
152
    {
153
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
154
        $charactersLength = strlen($characters);
155
        $randomString = '';
156
157
        for($i = 0; $i < $length; $i++) {
158
            $randomString .= $characters[rand(0, $charactersLength - 1)];
159
        }
160
161
        return $randomString;
162
    }
163
}
164