Completed
Push — master ( 539cfe...32b8af )
by Michael
03:42 queued 02:23
created

OpensslStatic::tagRequired()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
c 0
b 0
f 0
rs 9.7
cc 3
nc 3
nop 1
1
<?php
2
3
/**
4
 * OpensslStatic.php
5
 *
6
 * PHP version 7
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
class OpensslStatic extends OpensslWrapper
18
{
19
    public static function decrypt(string $data, string $pass, string $cipher, string $algo): string
20
    {
21
        // Calculate the hash checksum size in bytes for the specified algo
22
        $hsz = Str::hashSize($algo);
23
24
        // Find the tag size for this cipher mode
25
        // Unless using GCM/CCM this will be zero
26
        $tsz = self::tagRequired($cipher) ? 4 : 0;
27
28
        // Ask openssl for the IV size needed for specified cipher
29
        $isz = parent::ivsize($cipher);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (ivsize() instead of decrypt()). Are you sure this is correct? If so, you might want to change this to $this->ivsize().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
30
31
        // Find the IV at the beginning of the cypher text
32
        $ivr = Str::substr($data, 0, $isz);
33
34
        // Gather the checksum portion of the ciphertext
35
        $sum = Str::substr($data, $isz, $hsz);
36
37
        // Gather the GCM/CCM authentication tag
38
        $tag = Str::substr($data, $isz + $hsz, $tsz);
39
40
        // Gather the iterations portion of the cipher text as packed/encrytped unsigned long
41
        $itr = Str::substr($data, $isz + $hsz + $tsz, 4);
42
43
        // Gather message portion of ciphertext after iv and checksum
44
        $msg = Str::substr($data, $isz + $hsz + $tsz + 4);
45
46
        // Calculate verification checksum
47
        $chk = \hash_hmac($algo, ($msg . $itr . $ivr), $pass, true);
48
49
        // Verify HMAC before decrypting
50
        if (!Str::equal($chk, $sum)) {
51
            throw new \InvalidArgumentException('Decryption can not proceed due to invalid cyphertext checksum.');
52
        }
53
54
        // Decrypt and unpack the cost parameter to match what was used during encryption
55
        $cost = \unpack('N', $itr ^ \hash_hmac($algo, $ivr, $pass, true))[1];
56
57
        // Derive key from password
58
        $key = \hash_pbkdf2($algo, ($pass . $cipher), $ivr, $cost, 0, true);
59
60
        // Decrypt message and return
61
        return parent::openssl_decrypt($msg, $cipher, $key, $ivr, $tag);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (openssl_decrypt() instead of decrypt()). Are you sure this is correct? If so, you might want to change this to $this->openssl_decrypt().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
62
    }
63
64
    public static function encrypt(string $data, string $pass, string $cipher, string $algo, int $cost = 1): string
65
    {
66
        // Generate IV of appropriate size.
67
        $ivr = \random_bytes(parent::ivsize($cipher));
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (ivsize() instead of encrypt()). Are you sure this is correct? If so, you might want to change this to $this->ivsize().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
68
69
        // Derive key from password with hash_pbkdf2 function.
70
        // Append CIPHER to password beforehand so that cross-method decryptions will fail at checksum step
71
        $key = \hash_pbkdf2($algo, ($pass . $cipher), $ivr, $cost, 0, true);
72
73
        // Create a placeholder for the authentication tag to be passed by reference
74
        $tag = '';
75
76
        // Encrypt the plaintext data
77
        $msg = parent::openssl_encrypt($data, $cipher, $key, $ivr, $tag);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (openssl_encrypt() instead of encrypt()). Are you sure this is correct? If so, you might want to change this to $this->openssl_encrypt().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
78
79
        // Convert cost integer into 4 byte string and XOR it with a newly derived key
80
        $itr = \pack('N', $cost) ^ \hash_hmac($algo, $ivr, $pass, true);
81
82
        // Generate the ciphertext checksum to prevent bit tampering
83
        $chk = \hash_hmac($algo, ($msg . $itr . $ivr), $pass, true);
84
85
        // Return iv + checksum + iterations + cyphertext + tag
86
        return $ivr . $chk . $tag . $itr . $msg;
87
    }
88
}
89