co-stack / reversible
提供可移植的可逆函数和队列。例如,可用于传输编码或复杂值处理。
v1.7.0
2023-12-22 13:38 UTC
Requires
- php: ^7.2 || ^8.0 <8.4
- ext-json: *
- ext-openssl: *
- ext-zlib: *
README
什么是可逆函数
可逆函数是可以正向执行和反向回退(撤销)的函数。它们无副作用(幂等)且无状态。
这些函数对于传输编码、持久化映射、加密等许多其他用例特别有用。
注意
某些编码并非完全幂等,例如 Base64Encoding
。base64_encode
函数不保留数据类型(int、float、bool)。可能不是完全幂等的 Reversible
实现实现了 Lossy
接口。
摘要
此包的真正优势在于 ReversiblePipe
。下面更简单的示例只是为了说明。
$mySecret = 'correcthorsebatterystaple';
$myValue = [
'foo-bar-baz',
'boo-beng-fump'
];
$pipe = new \CoStack\Reversible\Applicable\ReversiblePipe();
$pipe->enqueue(new \CoStack\Reversible\Operation\Encoding\JsonEncoding())
->enqueue(new \CoStack\Reversible\Operation\Security\HmacAssertion($mySecret))
->enqueue(new \CoStack\Reversible\Operation\Encoding\Base64Encoding());
// The pipe will json encode the array, add the HMAC to the encoded array and base64 encode it
$transportSafeAndHmacProtected = $pipe->execute($myValue);
// Transport over wire
// ------->------->------->
// The pipe will base64 decode it and validate the HMAC. If the HMAC is valid the string will be json decoded and the array returned
$myValue = $pipe->reverse($transportSafeAndHmacProtected);
示例
我为您准备了一些有用的示例,展示了此包的通用性。
通过空中发送的标量值
在系统 A 上
// System A
$input = random_bytes(256);
$encoding = new \CoStack\Reversible\Operation\Encoding\Base64Encoding();
$output = $encoding->execute($input);
// System B
$encoding = new \CoStack\Reversible\Operation\Encoding\Base64Encoding();
$restoredInput = $encoding->reverse($output);
// $restoredInput is exactly $input what was generated on System A
通过字符串传输关联数组,无需序列化
// Shared Library
function getPipe(): \CoStack\Reversible\Applicable\ReversiblePipe {
$pipe = new \CoStack\Reversible\Applicable\ReversiblePipe();
$pipe->enqueue(new \CoStack\Reversible\Operation\Mapping\ArrayKeyMapping(['key1', 'key2', 'payload']));
$pipe->enqueue(new \CoStack\Reversible\Applicable\ApplyOnArrayValueRecursively(new \CoStack\Reversible\Operation\Encoding\Base64Encoding()));
$pipe->enqueue(new \CoStack\Reversible\Operation\Transform\ImplodeTransform());
return $pipe;
}
// System A
$array = [
'key1' => 1,
'key2' => 'value',
'payload' => uniqid(),
];
$pipe = getPipe();
$safeEncodedObject = $pipe->execute($array);
// The string will contain base64 encoded values, imploded with "|". There are no associative keys in the string because they have been replaced by the ArrayKeyMapping
// System B
$pipe = getPipe();
$array = $pipe->reverse($safeEncodedObject);
请注意,ImplodeTransform
是有损的,因为 explode(',', implode(',', [2])) === ['2']
(整数将变成字符串)。
通过问题媒介(例如,查询参数)传输对象
// Shared Library
function getPipe(): \CoStack\Reversible\Applicable\ReversiblePipe {
$pipe = new \CoStack\Reversible\Applicable\ReversiblePipe();
$pipe->enqueue(new \CoStack\Reversible\Operation\Encoding\SerializationEncoding());
$pipe->enqueue(new \CoStack\Reversible\Operation\Encoding\UrlEncode());
return $pipe;
}
// System A
$object = new SplFileInfo('file.txt');
$pipe = getPipe();
$safeEncodedObject = $pipe->execute($object);
// System B
$pipe = getPipe();
$object = $pipe->reverse($safeEncodedObject);
UUIDv4 到二进制和回(例如,在数据库中持久化二进制格式的 uuid)
$uuid = gen_uuid();
$uuidToBinary = new \CoStack\Reversible\Applicable\ReversiblePipe();
$uuidToBinary->enqueue(new \CoStack\Reversible\Operation\Fixed\FixedStringStripping('-', [8, 4, 4, 4]));
$uuidToBinary->enqueue(new \CoStack\Reversible\Operation\Encoding\HexToBinEncoding());
$binary = $uuidToBinary->execute($uuid);
// Persist binary uuid in DB
// Select binary uuid from DB and convert to readable string again
$uuidAgain = $uuidToBinary->reverse($binary);
安全性
在数据转换和编码的最后添加 \CoStack\Reversible\Operation\Security\HmacAssertion
,以生成 HMAC,反转时将自动验证。
$mySecretKey = 'Tr0ub4dor&3';
$protectMeFromChanges = uniqid();
$pipe = new \CoStack\Reversible\Applicable\ReversiblePipe();
$pipe->enqueue(new \CoStack\Reversible\Operation\Encoding\Base64Encoding());
$pipe->enqueue(new \CoStack\Reversible\Operation\Security\HmacAssertion($mySecretKey));
$stringWithHmac = $pipe->execute($protectMeFromChanges);
$stringWithHmac .= 'EvilChanges';
try {
$pipe->reverse($stringWithHmac);
} catch (\CoStack\Reversible\Exception\HmacAssertionFailedException $exception) {
echo 'Someone fiddled with the string!';
exit(1);
}