Completed
Push — master ( 8ed914...095f85 )
by Roberto
25:48 queued 11:05
created

Crypto::decriptMsg()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 12
rs 9.4285
cc 1
eloc 9
nc 1
nop 4
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 integer
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 int $cipher encoded cipher
66
     */
67
    public function __construct($derdata, $cipher = self::AES_128_CBC)
68
    {
69
        $this->cipher = $cipher;
0 ignored issues
show
Documentation Bug introduced by
It seems like $cipher can also be of type string. However, the property $cipher is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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
     */
80
    public function keyGenerate()
81
    {
82
        $length = openssl_cipher_iv_length($this->cipher);
83
        $this->key = openssl_random_pseudo_bytes($length);
84
        $this->iv = openssl_random_pseudo_bytes($length);
85
        $this->keyencrypted = $this->encryptkey($this->key, $this->iv);
86
    }
87
    
88
    /**
89
     * Recover encryped key+iv in base64
90
     * @return string
91
     */
92
    public function getEncrypedKey()
93
    {
94
        return $this->keyencrypted;
95
    }
96
    
97
    /**
98
     * Recover Thumbprint (or fingerprint) from certificate
99
     * @return string
100
     */
101
    public function getThumbprint()
102
    {
103
        return $this->fingerprint;
104
    }
105
    
106
    /**
107
     * Return an array with KEY and IV used to encripy and decript
108
     * @return array
109
     */
110
    public function getKeyAndIV()
111
    {
112
        return ['key' => $this->key, 'iv' => $this->iv];
113
    }
114
    
115
    /**
116
     * Encrypt message whith generate randon key and iv
117
     * @param string $datamsg
118
     * @return string
119
     */
120
    public function encryptMsg($datamsg)
121
    {
122
        return openssl_encrypt($datamsg, $this->cipher, $this->key, 0, $this->iv);
123
    }
124
    
125
    /**
126
     * Decript message with private key and randon key and iv
127
     * @param string $cryptedmsg encrytped message
128
     * @param string $privateKey in PEM format
129
     * @param string $keyencrypted key+iv im base64 format
130
     * @param string $cipher for encrypt and decrypt
131
     * @return string
132
     */
133
    public function decriptMsg($cryptedmsg, $privateKey, $keyencrypted, $cipher = self::AES_128_CBC)
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...
134
    {
135
        openssl_private_decrypt(
136
            base64_decode($keyencrypted),
137
            $decryptedkey,
138
            $privateKey,
139
            OPENSSL_PKCS1_PADDING
140
        );
141
        $key = substr($decryptedkey, 0, strlen($decryptedkey)-16);
142
        $iv = substr($decryptedkey, -16);
143
        return openssl_decrypt($cryptedmsg, $this->cipher, $key, 0, $iv);
144
    }
145
    
146
    /**
147
     * Recover certificate info
148
     * @return array
149
     */
150
    public function certificateInfo()
151
    {
152
        $resource = openssl_x509_read($this->certificate);
153
        $detail = openssl_x509_parse($resource, false);
154
        $validFrom = \DateTime::createFromFormat('ymdHis\Z', $detail['validFrom']);
155
        $validTo = \DateTime::createFromFormat('ymdHis\Z', $detail['validTo']);
156
        return [
157
          'validFrom' => $validFrom,
158
          'validTo' => $validTo,
159
          'details' => $detail
160
        ];
161
    }
162
    
163
    /**
164
     * Extract fingerprint from certificate
165
     * @param string $certificate
166
     * @return string
167
     */
168
    protected function thumbprint($certificate)
169
    {
170
        return openssl_x509_fingerprint($certificate, "sha1", false);
171
    }
172
    
173
    /**
174
     * Encrypt key with certificate, add iv and converts to base64
175
     * @param string $key
176
     * @param string $iv
177
     * @return string
178
     */
179
    protected function encryptkey($key, $iv)
180
    {
181
        openssl_public_encrypt($key.$iv, $cryptedkey, $this->certificate, OPENSSL_PKCS1_PADDING);
182
        return base64_encode($cryptedkey);
183
    }
184
    
185
    /**
186
     * Converts certificate in DER format to PEM format
187
     * @param string $derdata
188
     * @return string
189
     */
190
    protected function convertDERtoPEM($derdata)
191
    {
192
        $certificate = chunk_split(base64_encode($derdata), 64, "\n");
193
        return "-----BEGIN CERTIFICATE-----\n"
194
            . $certificate
195
            ."-----END CERTIFICATE-----\n";
196
    }
197
}
198