Completed
Pull Request — master (#3)
by Guillermo
37:57
created

UrlCrypt::getInstance()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
/**
4
 * URLCrypt
5
 *
6
 * PHP library to securely encode and decode short pieces of arbitrary binary data in URLs.
7
 *
8
 * (c) Guillermo Gonzalez
9
 *
10
 * For the full copyright and license information, please view the COPYING
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Atrapalo\UrlCrypt;
15
16
/**
17
 * Class UrlCrypt
18
 * @package Atrapalo\UrlCrypt
19
 */
20
class UrlCrypt
21
{
22
    public $table = "1bcd2fgh3jklmn4pqrstAvwxyz567890";
23
    private $ivSize = 16;
24
    private $opensslMode = 'AES-256-OFB';
25
26
    public function __construct(string $table = null)
27
    {
28
        if (!is_null($table) && $table != '') {
29
            $this->table = $table;
30
        }
31
    }
32
33 13
    public static function getInstance(string $table = null): UrlCrypt
34
    {
35 13
        return new self($table);
36 1
    }
37 1
38 13
    public function encode(string $string): string
39
    {
40
        $table = str_split($this->table, 1);
41
        $size = strlen($string) * 8 / 5;
42
        $stringArray = str_split($string, 1);
43
44 10
        $message = "";
45
        foreach ($stringArray as $char) {
46 10
            $message .= str_pad(decbin(ord($char)), 8, "0", STR_PAD_LEFT);
47 10
        }
48 10
49
        $message = str_pad($message, ceil(strlen($message) / 5) * 5, "0", STR_PAD_RIGHT);
50 10
51 10
        $encodeString = "";
52 10
        for ($i = 0; $i < $size; $i++) {
53 10
            $encodeString .= $table[bindec(substr($message, $i * 5, 5))];
54
        }
55 10
56
        return $encodeString;
57 10
    }
58 10
59 9
    public function decode(string $string): string
60 9
    {
61
        $table = str_split($this->table, 1);
62 10
        $size = strlen($string) * 5 / 8;
63
        $stringArray = str_split($string, 1);
64
65
        $message = "";
66
        foreach ($stringArray as $char) {
67
            $message .= str_pad(decbin(array_search($char, $table)), 5, "0", STR_PAD_LEFT);
68
        }
69 10
70
        $originalString = '';
71 10
        for ($i = 0; $i < floor($size); $i++) {
72 10
            $originalString .= chr(bindec(substr($message, $i * 8, 8)));
73 10
        }
74
75 10
        return $originalString;
76 10
    }
77 10
78 10
    public function encrypt(string $string, string $key): string
79
    {
80 10
        $key = $this->prepareKey($key);
81 10
        $iv = openssl_random_pseudo_bytes($this->ivSize);
82 9
        $cipherText = openssl_encrypt($string, $this->opensslMode, $key, 0, $iv);
83 9
        $cipherText = $iv . $cipherText;
84
85 10
        return $this->encode($cipherText);
86
    }
87
88
    public function decrypt(string $string, string $key): string
89
    {
90
        $key = $this->prepareKey($key);
91
        $string = $this->decode($string);
92
93
        $ivDec = substr($string, 0, $this->ivSize);
94 9
        $string = substr($string, $this->ivSize);
95
        $string = openssl_decrypt($string, $this->opensslMode, $key, 0, $ivDec);
96 9
97 7
        return $string;
98 7
    }
99 7
100
    private function prepareKey(string $key): string
101 7
    {
102
        if (is_null($key) || $key == "") {
103
            throw new \Exception('No key provided.');
104
        }
105
106
        if (in_array(strlen($key), [32, 48, 64]) && $this->isHexString($key)) {
107
            return pack('H*', $key);
108
        } elseif (in_array(strlen($key), [16, 24, 32])) {
109
            return $key;
110 7
        } else {
111
            return md5($key);
112 7
        }
113 7
    }
114
115 7
    private function isHexString(string $string): string
116 7
    {
117 7
        return (preg_match('/^[0-9a-f]+$/i', $string) === 1);
118
    }
119
}
120