Crypto::encryptkey()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 5
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
namespace NFePHP\eFinanc\Common;
4
5
/**
6
 * Crypto class Performs message encryption processes
7
 *
8
 * @category  API
9
 * @package   NFePHP\eFinanc
10
 * @copyright Copyright (c) 2018
11
 * @license   http://www.gnu.org/licenses/lesser.html LGPL v3
12
 * @author    Roberto L. Machado <linux.rlm at gmail dot com>
13
 * @link      http://github.com/nfephp-org/sped-efinanceira for the canonical source repository
14
 */
15
class Crypto
16
{
17
    /**
18
     * @var string
19
     */
20
    protected $cipher;
21
    /**
22
     * @var string
23
     */
24
    protected $key;
25
    /**
26
     * @var string
27
     */
28
    protected $iv;
29
    /**
30
     * @var string
31
     */
32
    protected $certificate;
33
    /**
34
     * @var string
35
     */
36
    protected $fingerprint;
37
    /**
38
     * @var string
39
     */
40
    protected $keyencrypted;
41
    /**
42
     * constants
43
     */
44
    const AES_128_CBC = 'aes-128-cbc';
45
    const AES_128_CBF = 'aes-128-cfb';
46
    const AES_128_CBF1 = 'aes-128-cfb1';
47
    const AES_128_CBF8 = 'aes-128-cfb8';
48
    const AES_128_OFB = 'aes-128-ofb';
49
    const AES_192_CBC = 'aes-192-cbc';
50
    const AES_192_CBF = 'aes-192-cbf';
51
    const AES_192_CBF1 = 'aes-192-cbf1';
52
    const AES_192_CBF8 = 'aes-192-cbf8';
53
    const AES_192_OFB = 'aes-192-ofb';
54
    const AES_256_CBC = 'aes-256-cbc';
55
    const AES_256_CBF = 'aes-256-cbf';
56
    const AES_256_CBF1 = 'aes-256-cbf1';
57
    const AES_256_CBF8 = 'aes-256-cbf8';
58
    const AES_256_OFB = 'aes-256-ofb';
59
    
60
    /**
61
     * Constructor
62
     * Recive cer content and convert to pem, get certificate fingerprint and
63
     * creates a encryption key and initialization vector
64
     * @param string $derdata certificate content in DER format (usual)
65
     * @param string $cipher encoded cipher
66
     */
67
    public function __construct($derdata, $cipher = self::AES_128_CBC)
68
    {
69
        $this->cipher = $cipher;
70
        $this->certificate = $this->convertDERtoPEM($derdata);
71
        $this->fingerprint = $this->thumbprint($this->certificate);
72
        $this->keyGenerate();
73
    }
74
    
75
    /**
76
     * Generate a key and initialization vector
77
     * and encrypt this key with a certificate
78
     * and combine with initialization vector in base64 format
79
     * @return void
80
     */
81
    public function keyGenerate()
82
    {
83
        $length = openssl_cipher_iv_length($this->cipher);
84
        $this->key = openssl_random_pseudo_bytes($length);
85
        $this->iv = openssl_random_pseudo_bytes($length);
86
        $this->keyencrypted = $this->encryptkey($this->key, $this->iv);
87
    }
88
    
89
    /**
90
     * Recover encryped key+iv in base64
91
     * @return string
92
     */
93
    public function getEncrypedKey():string
94
    {
95
        return $this->keyencrypted;
96
    }
97
    
98
    /**
99
     * Recover Thumbprint (or fingerprint) from certificate
100
     * @return string
101
     */
102
    public function getThumbprint():string
103
    {
104
        return $this->fingerprint;
105
    }
106
    
107
    /**
108
     * Recover used cipher
109
     * @return string
110
     */
111
    public function getCipher():string
112
    {
113
        return $this->cipher;
114
    }
115
    
116
    /**
117
     * Return an array with KEY and IV used to encripy and decript
118
     * @return array
119
     */
120
    public function getKeyAndIV():array
121
    {
122
        return ['key' => $this->key, 'iv' => $this->iv];
123
    }
124
    
125
    /**
126
     * Encrypt message whith generate randon key and iv
127
     * @param string $datamsg
128
     * @return string
129
     */
130
    public function encryptMsg($datamsg):string
131
    {
132
        return openssl_encrypt($datamsg, $this->cipher, $this->key, 0, $this->iv);
133
    }
134
    
135
    /**
136
     * Decrypt message with private key and randon key and iv
137
     * @param string $cryptedmsg encrytped message
138
     * @param string $privateKey in PEM format
139
     * @param string $keyencrypted key+iv im base64 format
140
     * @param string $cipher for encrypt and decrypt
141
     * @return string
142
     */
143
    public function decryptMsg($cryptedmsg, $privateKey, $keyencrypted, $cipher = self::AES_128_CBC):string
0 ignored issues
show
Unused Code introduced by
The parameter $cipher is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
144
    {
145
        openssl_private_decrypt(
146
            base64_decode($keyencrypted),
147
            $decryptedkey,
148
            $privateKey,
149
            OPENSSL_PKCS1_PADDING
150
        );
151
        $key = substr($decryptedkey, 0, strlen($decryptedkey)-16);
152
        $iv = substr($decryptedkey, -16);
153
        return openssl_decrypt($cryptedmsg, $this->cipher, $key, 0, $iv);
154
    }
155
    
156
    /**
157
     * Decrypt message encripted with AES
158
     * @param string $message
159
     * @param string $cipher
160
     * @param string $key
161
     * @param string $iv
162
     * @return string
163
     */
164
    public function decryptAes($message, $cipher, $key, $iv):string
165
    {
166
        return openssl_decrypt($message, $cipher, $key, 0, $iv);
167
    }
168
    
169
    /**
170
     * Recover certificate info
171
     * @return array
172
     */
173
    public function certificateInfo():array
174
    {
175
        $resource = openssl_x509_read($this->certificate);
176
        $detail = openssl_x509_parse($resource, false);
177
        $validFrom = \DateTime::createFromFormat('ymdHis\Z', $detail['validFrom']);
178
        $validTo = \DateTime::createFromFormat('ymdHis\Z', $detail['validTo']);
179
        return [
180
          'validFrom' => $validFrom,
181
          'validTo' => $validTo,
182
          'details' => $detail
183
        ];
184
    }
185
    
186
    /**
187
     * Extract fingerprint from certificate
188
     * @param string $certificate
189
     * @return string
190
     */
191
    protected function thumbprint($certificate):string
192
    {
193
        return openssl_x509_fingerprint($certificate, "sha1", false);
194
    }
195
    
196
    /**
197
     * Encrypt key with certificate, add iv and converts to base64
198
     * @param string $key
199
     * @param string $iv
200
     * @return string
201
     */
202
    protected function encryptkey($key, $iv):string
203
    {
204
        openssl_public_encrypt($key.$iv, $cryptedkey, $this->certificate, OPENSSL_PKCS1_PADDING);
205
        return base64_encode($cryptedkey);
206
    }
207
    
208
    /**
209
     * Converts certificate in DER format to PEM format
210
     * @param string $derdata
211
     * @return string
212
     */
213
    protected function convertDERtoPEM($derdata):string
214
    {
215
        $certificate = chunk_split(base64_encode($derdata), 64, "\n");
216
        return "-----BEGIN CERTIFICATE-----\n"
217
            . $certificate
218
            ."-----END CERTIFICATE-----\n";
219
    }
220
}
221