Passed
Push — master ( 7f2cdc...86c1a0 )
by Tony Karavasilev (Тони
06:16
created

AbstractUnkeyedHashFunction::hashObject()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
c 1
b 0
f 0
dl 0
loc 9
ccs 5
cts 5
cp 1
rs 10
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
/**
4
 * Abstraction for unkeyed hash objects like checksums and plain cryptographic hash functions.
5
 */
6
7
namespace CryptoManana\Core\Abstractions\MessageDigestion;
8
9
use \CryptoManana\Core\Abstractions\MessageDigestion\AbstractHashAlgorithm as HashAlgorithm;
10
use \CryptoManana\Core\Interfaces\MessageDigestion\ObjectHashingInterface as ObjectHashing;
11
use \CryptoManana\Core\Interfaces\MessageDigestion\FileHashingInterface as FileHashing;
12
13
/**
14
 * Class AbstractUnkeyedHashFunction - Abstraction for unkeyed hash classes.
15
 *
16
 * @package CryptoManana\Core\Abstractions\MessageDigestion
17
 */
18
abstract class AbstractUnkeyedHashFunction extends HashAlgorithm implements ObjectHashing, FileHashing
19
{
20
    /**
21
     * The internal name of the algorithm.
22
     */
23
    const ALGORITHM_NAME = 'none';
24
25
    /**
26
     * Flag to force native code polyfill realizations, if available.
27
     *
28
     * @var bool Flag to force native realizations.
29
     */
30
    protected $useNative = false;
31
32
    /**
33
     * Unkeyed hash algorithm constructor.
34
     */
35 352
    public function __construct()
36
    {
37 352
    }
38
39
    /**
40
     * Calculates a hash value for the given data.
41
     *
42
     * @param string $data The input string.
43
     *
44
     * @return string The digest.
45
     * @throws \Exception Validation errors.
46
     */
47 126
    public function hashData($data)
48
    {
49 126
        if (!is_string($data)) {
1 ignored issue
show
introduced by
The condition is_string($data) is always true.
Loading history...
50 14
            throw new \InvalidArgumentException('The data for hashing must be a string or a binary string.');
51
        }
52
53 112
        $data = $this->addSaltString($data);
54
55 112
        $digest = hash(static::ALGORITHM_NAME, $data, ($this->digestFormat === self::DIGEST_OUTPUT_RAW));
56
57 112
        $digest = $this->changeOutputFormat($digest);
58
59 112
        return $digest;
60
    }
61
62
    /**
63
     * Calculates a hash value for the content of the given filename and location.
64
     *
65
     * @param string $filename The full path and name of the file for hashing.
66
     *
67
     * @return string The digest.
68
     * @throws \Exception Validation errors.
69
     */
70 66
    public function hashFile($filename)
71
    {
72
        // Validate input type
73 66
        if (!is_string($filename)) {
1 ignored issue
show
introduced by
The condition is_string($filename) is always true.
Loading history...
74 22
            throw new \InvalidArgumentException('The file path must be of type string.');
75
        }
76
77 44
        $filename = str_replace("\0", '', $filename); // (ASCII 0 (0x00))
78 44
        $filename = realpath($filename); // Path traversal escape and absolute path fetching
79
80
        // Clear path cache
81 44
        if (!empty($filename)) {
82 22
            clearstatcache(true, $filename);
83
        }
84
85
        // Check if path is valid and the file is readable
86 44
        if ($filename === false || !file_exists($filename) || !is_readable($filename) || !is_file($filename)) {
87 22
            throw new \RuntimeException('File is not found or can not be accessed.');
88
        }
89
90 22
        if ($this->useNative) {
91 22
            $data = file_get_contents($filename);
92
93 22
            $oldSalt = $this->getSalt();
94 22
            $oldMode = $this->getSaltingMode();
95
96 22
            $this->setSalt('');
97 22
            $this->setSaltingMode(self::SALTING_MODE_NONE);
98
99 22
            $digest = $this->hashData($data);
100
101 22
            $this->setSalt($oldSalt);
102 22
            $this->setSaltingMode($oldMode);
103
        } else {
104 22
            $digest = hash_file(static::ALGORITHM_NAME, $filename, ($this->digestFormat === self::DIGEST_OUTPUT_RAW));
105
106 22
            $digest = $this->changeOutputFormat($digest);
107
        }
108
109 22
        return $digest;
110
    }
111
112
    /**
113
     * Calculates a hash value for the serialized value of the given object.
114
     *
115
     * @param object|\stdClass $object The full path and name of the file for hashing.
116
     *
117
     * @return string The digest.
118
     * @throws \Exception Validation errors.
119
     */
120 44
    public function hashObject($object)
121
    {
122 44
        if (is_object($object)) {
123 22
            $object = serialize($object);
124
        } else {
125 22
            throw new \InvalidArgumentException('The data for hashing must be an object instance.');
126
        }
127
128 22
        return $this->hashData($object);
129
    }
130
131
    /**
132
     * Get debug information for the class instance.
133
     *
134
     * @return array Debug information.
135
     */
136 22
    public function __debugInfo()
137
    {
138
        return [
139 22
            'standard' => static::ALGORITHM_NAME,
140 22
            'type' => 'unkeyed digestion or checksum',
141 22
            'salt' => $this->salt,
142 22
            'mode' => $this->saltingMode,
143
        ];
144
    }
145
}
146