Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

10 integer keys fix #14

Merged
merged 2 commits into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ It is an array of key names, for example:
```php
$sensitive_keys = ['api_key'];
```
Will hash the value of the `api_key`.
Will hash the value of the `api_key`. Because of PHP's tendency to automatically add integer indexes to such an array,
integers in sensitive keys will be ignored and might lead to unexpected results. To be on the safe side, only use
sensitive string keys, or a nested tree of strings.

#### 2. Create a Processor using the keys

Expand Down
31 changes: 29 additions & 2 deletions src/Hasher.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ protected function traverseInputArray(array $inputArray, array $sensitiveKeys):

// If the value is not an array or an object, hash it if it is a sensitive key
if (is_scalar($value)) {
if (in_array($key, $sensitiveKeys) || array_key_exists($key, $sensitiveKeys)) {
if ($this->isSensitiveKey($key, $sensitiveKeys)) {
$inputArray[$key] = $this->hash(print_r($value, true));
}

Expand All @@ -105,7 +105,7 @@ protected function traverseInputArray(array $inputArray, array $sensitiveKeys):

// The value is either an array or an object, let traverse handle the specifics
// If the current key is a sensitive key, traverse the subtree.
if ((in_array($key, $sensitiveKeys) || array_key_exists($key, $sensitiveKeys))) {
if ($this->isSensitiveKey($key, $sensitiveKeys)) {
// If the current key doesn't have a subtree of sensitive keys (indicating the entire subtree,
// and not a value somewhere in the subtree should be hashed)
if (!array_key_exists($key, $sensitiveKeys)) {
Expand Down Expand Up @@ -191,4 +191,31 @@ protected function traverseObject(object $object, array $sensitiveKeys): object

return $object;
}

/**
* @param int|string $key
*
* @param array<array-key, mixed> $sensitiveKeys Keys to redact
*
* @return bool Whether the key provided is a sensitiveKey
*/
protected function isSensitiveKey(int|string $key, array $sensitiveKeys): bool
{
// Checks the values, if the key is in the value list of sensitive keys (the 'end' of the sensitive key lists)
if (in_array($key, $sensitiveKeys)) {
return true;
}

// When there is a sub array, check whether the key is in the sensitive key key list
if (array_key_exists($key, $sensitiveKeys)) {
if (is_int($key)) {
// If the key is an integer, this is php generated key, when sensitiveKeys should be a value list
return false;
}

return true;
}

return false;
}
}
18 changes: 18 additions & 0 deletions tests/HashSensitiveArrayTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,22 @@

$record = $this->getRecord(context: $this->insideNested->getInput());
expect($processor($record)->context)->toBe(['test' => ['nested' => 'c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2']]);
});

# Prevent bugs from re-appearing
# Issue: https://github.com/Globy-App/hash-sensitive/issues/10
it('10 - does not hash values of integer keys', function (): void {
$integerKeys = new TestDataEntity([0 => 'foo', 1 => 'bar'], ['other', 'first', 'second']);
$processor = new HashSensitiveProcessor($integerKeys->getSensitiveKeys());

$record = $this->getRecord(context: $integerKeys->getInput());
expect($processor($record)->context)->toBe([0 => 'foo', 1 => 'bar']);
});

it('10 - does not throw an exception', function (): void {
$integerKeys = new TestDataEntity([0 => ['id' => 1, 'value' => 'foo'], 1 => ['id' => 2, 'value' => 'bar']], ['other', 'first', 'second']);
$processor = new HashSensitiveProcessor($integerKeys->getSensitiveKeys());

$record = $this->getRecord(context: $integerKeys->getInput());
expect($processor($record)->context)->toBe([0 => ['id' => 1, 'value' => 'foo'], 1 => ['id' => 2, 'value' => 'bar']]);
});
19 changes: 19 additions & 0 deletions tests/HashSensitiveObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,23 @@
expect($processor($record)->context)->toBe(['nested' => $nested])
->and($nested->test)->toBe('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2')
->and($nested->optionalKey)->toBeNull();
});

# Prevent bugs from re-appearing
# Issue: https://github.com/Globy-App/hash-sensitive/issues/
it('10 - does not throw an exception', function (): void {
$nested1 = new \stdClass();
$nested1->id = 1;
$nested1->value = 'foo';

$nested2 = new \stdClass();
$nested2->id = 2;
$nested2->value = 'bar';

$input = [0 => $nested1, 1 => $nested2];
$sensitive_keys = ['other', 'first', 'second'];
$processor = new HashSensitiveProcessor($sensitive_keys);

$record = $this->getRecord(context: $input);
expect($processor($record)->context)->toBe([0 => $nested1, 1 => $nested2]);
});