Failed Conditions
Push — master ( 637149...2dd17c )
by Moesjarraf
03:01
created

Transform::generate_public_key()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2.0625

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 6
cts 8
cp 0.75
rs 9.4285
cc 2
eloc 8
nc 2
nop 2
crap 2.0625
1
<?php
2
3
namespace LegalThings\DataEnricher\Processor;
4
5
use LegalThings\DataEnricher\Node;
6
use LegalThings\DataEnricher\Processor;
7
8
/**
9
 * Transform processor, apply transformation functions on data
10
 */
11
class Transform implements Processor
12
{
13
    use Processor\Implementation;
14
    
15
    /**
16
     * Allowed transformation functions
17
     * @var array 
18
     */
19
    public $functions;
20
    
21
    
22
    /**
23
     * Class constructor
24
     * 
25
     * @param string $property  Property key with the processing instruction
26
     */
27 19
    public function __construct($property)
28
    {
29 19
        $this->property = $property;
30 19
        $this->functions = $this->getDefaultFunctions();
31 19
    }
32
    
33
    /**
34
     * Default transformation functions
35
     * @var array
36
     */
37 19
    public function getDefaultFunctions()
38
    {
39 19
        $class = 'LegalThings\DataEnricher\Processor\Transform';
40
41
        return [
42 19
            'hash' => 'hash',
43 19
            'hash_hmac' => 'hash_hmac',
44 19
            'base64_encode' => 'base64_encode',
45 19
            'base64_decode' => 'base64_decode',
46 19
            'json_encode' => 'json_encode',
47 19
            'json_decode' => 'json_decode',
48 19
            'serialize' => 'serialize',
49 19
            'unserialize' => 'unserialize',
50 19
            'strtotime' => 'strtotime',
51 19
            'date' => 'date',
52 19
            'public_encrypt' => "$class::public_encrypt",
53 19
            'private_encrypt' => "$class::private_encrypt",
54 19
            'private_decrypt' => "$class::private_decrypt",
55 19
            'generate_private_key' => "$class::generate_private_key",
56 19
            'generate_public_key' => "$class::generate_public_key",
57 19
            'generate_signature' => "$class::generate_signature",
58 19
            'verify_signature' => "$class::verify_signature"
59 19
        ];
60
    }
61
    
62
    
63
    /**
64
     * Apply processing to a single node
65
     * 
66
     * @param Node $node
67
     */
68 15
    public function applyToNode(Node $node)
69
    {
70 15
        $instruction = $node->getInstruction($this);
71 15
        $transformations = !is_array($instruction) ? [$instruction] : $instruction;
72
        
73 15
        if (isset($node->input)) {
74 5
            $input = $this->resolveNodes($node->input);
75 5
        }
76
        
77 15
        foreach ($transformations as $transformation) {
78 15
            if (is_string($transformation) && !isset($input)) {
79 1
                continue;
80
            }
81
            
82 14
            if (is_string($transformation)) {
83 5
                list($key, $args) = explode(':', $transformation) + [null, null];
84 14
            } elseif (is_object($transformation) || is_array($transformation)) {
85 9
                $transformation = (object)$transformation;
86 9
                $key = isset($transformation->function) ? $transformation->function : null;
87 9
                $args = isset($transformation->args) ? $transformation->args : [];
88 9
            }
89
            
90 14
            if (!isset($this->functions[$key])) {
91 1
                throw new \Exception("Unknown transformation '$key'");
92
            }
93
            
94 13
            if (isset($args)) {
95 12
                $args = $this->resolveNodes($args);
96 12
            }
97
            
98 13
            $fn = $this->functions[$key];
0 ignored issues
show
Bug introduced by
The variable $key does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
99
            
100 13
            if (is_string($transformation)) {
101 4
                $result = isset($args) ? call_user_func($fn, $args, $input) : call_user_func($fn, $input);
0 ignored issues
show
Bug introduced by
The variable $input does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
102 13
            } elseif (is_object($transformation)) {
103 9
                $result = call_user_func_array($fn, $args);
0 ignored issues
show
Bug introduced by
The variable $args does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
104 9
            }
105 14
        }
106
        
107 14
        if (isset($result)) {
108 13
            $node->setResult($result);
109 13
        }
110 14
    }
111
    
112
    /**
113
     * Resolve instructions of nodes by getting their results
114
     * 
115
     * @param Node $node
116
     * 
117
     * @return mixed $result
118
     */
119 14
    protected function resolveNodes($node) {
120 14
        if (!$node instanceof Node) {
121 14
            return $node;
122
        }
123
124 1
        return $node->getResult();
125
    }
126
    
127
    
128
    /**
129
     * Generate a private key
130
     * 
131
     * @param array $options
132
     * @throws RuntimeException
133
     * @return string
134
     */
135 1
    public function generate_private_key($options = [])
0 ignored issues
show
Coding Style introduced by
Method name "Transform::generate_private_key" is not in camel caps format
Loading history...
136
    {
137
        $config = array(
138 1
            "digest_alg" => "sha512",
139 1
            "private_key_bits" => 2048,
140 1
            "private_key_type" => OPENSSL_KEYTYPE_RSA,
141 1
        );
142
        
143 1
        $input = $options + $config;
144 1
        $res = openssl_pkey_new($input);
145
        
146 1
        openssl_pkey_export($res, $key); 
147 1
        return $key;
148
    }
149
    
150
    /**
151
     * Generate a public based on existing private key
152
     * 
153
     * @param string $privateKey
154
     * @param string $passphrase
155
     * @throws \RuntimeException
156
     * @return string
157
     */
158 1
    public function generate_public_key($privateKey, $passphrase = null)
0 ignored issues
show
Coding Style introduced by
Method name "Transform::generate_public_key" is not in camel caps format
Loading history...
159
    {
160 1
        $privKey = openssl_get_privatekey($privateKey, $passphrase);
161
        
162 1
        if (!is_resource($privKey)) {
163
            $type = gettype($privKey);
164
            throw new \Exception("Expected private key to be resource, got: '$type'. Check if the given private key is in correct syntax.");
165
        }
166
        
167 1
        $pubKey = openssl_pkey_get_details($privKey);
168 1
        $key = $pubKey["key"];
169
        
170 1
        return $key;
171
    }
172
    
173
    /**
174
     * Encrypts data with private key
175
     * 
176
     * @link http://php.net/manual/en/function.openssl-private-encrypt.php
177
     * 
178
     * @param string $data
179
     * @param string $key          The private key
180
     * @param string $passphrase
181
     * @param int $padding
182
     * 
183
     * @return string
184
     */
185 1 View Code Duplication
    function private_encrypt($data, $key, $passphrase = null, $padding = OPENSSL_PKCS1_PADDING)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for private_encrypt.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Coding Style introduced by
Method name "Transform::private_encrypt" is not in camel caps format
Loading history...
186
    {
187 1
        $privKey = openssl_get_privatekey($key, $passphrase);
188
        
189 1
        if (!is_resource($privKey)) {
190
            $type = gettype($privKey);
191
            throw new \Exception("Expected private key to be resource, got: '$type'. Check if the given private key is in correct syntax.");
192
        }
193
        
194 1
        openssl_private_encrypt($data, $result, $privKey, $padding);
195
        
196 1
        if (!is_string($result)) {
197
            throw new \Exception("Failed to encrypt data. Result: '$result'");
198
        }
199
        
200 1
        $base64 = base64_encode($result);
201
        
202 1
        return $base64;
203
    }
204
    
205
    /**
206
     * Decrypts data with public key, that was encrypted with private key
207
     * 
208
     * @link http://php.net/manual/en/function.openssl-private-decrypt.php
209
     * 
210
     * @param string $data
211
     * @param string $key          The public key
212
     * @param string $passphrase
0 ignored issues
show
Bug introduced by
There is no parameter named $passphrase. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
213
     * @param int $padding
214
     * 
215
     * @return string
216
     */
217 1
    function private_decrypt($data, $key, $padding = OPENSSL_PKCS1_PADDING)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for private_decrypt.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Coding Style introduced by
Method name "Transform::private_decrypt" is not in camel caps format
Loading history...
218
    {
219 1
        if ($this->is_base64($data)) {
220 1
            $data = base64_decode($data);
221 1
        }
222
        
223 1
        openssl_public_decrypt($data, $result, $key, $padding);
224
        
225 1
        if (!is_string($result)) {
226
            throw new \Exception("Failed to decrypt data. Result: '$result'");
227
        }
228
        
229 1
        return $result;
230
    }
231
    
232
    /**
233
     * Encrypts data with public key
234
     * 
235
     * @link http://php.net/manual/en/function.openssl-public-encrypt.php
236
     * 
237
     * @param string $data
238
     * @param string $key    The public key
239
     * @param int $padding
240
     * 
241
     * @return string
242
     */
243 1
    function public_encrypt($data, $key, $padding = OPENSSL_PKCS1_PADDING)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for public_encrypt.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Coding Style introduced by
Method name "Transform::public_encrypt" is not in camel caps format
Loading history...
244
    {
245 1
        openssl_public_encrypt($data, $result, $key, $padding);
246
        
247 1
        if (!is_string($result)) {
248
            throw new \Exception("Failed to encrypt data. Result: '$result'");
249
        }
250
        
251 1
        $base64 = base64_encode($result);
252
        
253 1
        return $base64;
254
    }
255
    
256
    /**
257
     * Generate signature based on private key
258
     * 
259
     * @link http://php.net/manual/en/function.openssl-sign.php
260
     * 
261
     * @param string $data
262
     * @param string $key         The private key
263
     * @param string $passphrase
264
     * @param int $signature_alg
265
     * 
266
     * @return string
267
     */
268 1 View Code Duplication
    function generate_signature($data, $key, $passphrase = null, $signature_alg = OPENSSL_ALGO_SHA1)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for generate_signature.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Coding Style introduced by
Method name "Transform::generate_signature" is not in camel caps format
Loading history...
269
    {
270 1
        $privKey = openssl_get_privatekey($key, $passphrase);
271
        
272 1
        if (!is_resource($privKey)) {
273
            $type = gettype($privKey);
274
            throw new \Exception("Expected private key to be resource, got: '$type'. Check if the given private key is in correct syntax.");
275
        }
276
        
277 1
        openssl_sign($data, $result, $privKey, $signature_alg);
278
        
279 1
        if (!is_string($result)) {
280
            throw new \Exception("Failed to encrypt data. Result: '$result'");
281
        }
282
        
283 1
        $base64 = base64_encode($result);
284
        
285 1
        return $base64;
286
    }
287
    
288
    /**
289
     * Verify signature that was encrypted with private key through public key
290
     * 
291
     * @link http://php.net/manual/en/function.openssl-verify.php
292
     * 
293
     * @param string $data
294
     * @param string $signature
295
     * @param string $key         The public key
296
     * @param string $passphrase
0 ignored issues
show
Bug introduced by
There is no parameter named $passphrase. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
297
     * @param int $signature_alg
298
     * 
299
     * @return string
300
     */
301 1
    function verify_signature($data, $signature, $key, $signature_alg = OPENSSL_ALGO_SHA1)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for verify_signature.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Coding Style introduced by
Method name "Transform::verify_signature" is not in camel caps format
Loading history...
302
    {
303 1
        if ($this->is_base64($signature)) {
304 1
            $signature = base64_decode($signature);
305 1
        }
306
        
307 1
        return openssl_verify($data, $signature, $key, $signature_alg);
308
    }
309
    
310
    /**
311
     * Check if input is valid base64
312
     * 
313
     * @param string $data
314
     * 
315
     * @return boolean
316
     */
317 2
    function is_base64($data)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
Comprehensibility Best Practice introduced by
It is recommend to declare an explicit visibility for is_base64.

Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed.

If you are not sure which visibility to choose, it is a good idea to start with the most restrictive visibility, and then raise visibility as needed, i.e. start with private, and only raise it to protected if a sub-class needs to have access, or public if an external class needs access.

Loading history...
Coding Style introduced by
Method name "Transform::is_base64" is not in camel caps format
Loading history...
318
    {
319 2
        return base64_encode(base64_decode($data)) === $data;
320
    }
321
}
322