Мне нужно создать в ColdFusion пригодный для использования 20-значный ключ из 40-символьного ключа. Это для расчета подписи HMAC.
Сервер, который я вызываю, проверяет подпись с помощью функции пакета php (H *).
Когда я пытаюсь создать ключ для вычисления печати HMAC, я не могу вычислить тот же ключ, который был возвращен PHP. Pack (H *) возвращает 20 символов, но CF (binaryDecode ()) возвращает 18, некоторые из них игнорируются или результат другой. Подпись недействительна.
Пример: если я попытаюсь вычислить ключ из 20 символов с этим
«325A16A325127FD42B700D4810E83F6312877B92»:
Возврат PHP: 2Z % + p H ? C { и с CF:
2Z% + рН? С {
$key = "325A16A325127FD42B700D4810E83F6312877B92";
$test = pack('H*',$key);
var_dump($test);
С CF:
local.key = toString(binaryDecode("325A16A325127FD42B700D4810E83F6312877B92", "hex"));
writeDump(local.key);
Больше код:
PHP.
function hmac_sha1 ($key, $data) {
$length = 64; // block length for SHA1
if (strlen($key) > $length) { $key = pack("H*",sha1($key)); }
$key = str_pad($key, $length, chr(0x00));
$ipad = str_pad('', $length, chr(0x36));
$opad = str_pad('', $length, chr(0x5c));
$k_ipad = $key ^ $ipad ;
$k_opad = $key ^ $opad;
return sha1($k_opad . pack("H*",sha1($k_ipad . $data)));
}
$key = "325A16A325127FD42B700D4810E83F6312877B92";
$validKey = pack('H*',$key);
$str = "7464052*08/10/2018:14:22:30*65.25EUR*AA123**3.0*FR*carmen*[email protected]**********";
$sign = hmac_sha1($validKey, $str);
$test = pack('H*',$key);
Вернуть: 23e7db20da9b58a47e27c151a65c2393a08ee4f5
local.key = toString(binaryDecode("325A16A325127FD42B700D4810E83F6312877B92","hex"));
local.crypto = createObject("miscellaneous.crypto").init();
local.str = "7464052*08/10/2018:14:22:30*65.25EUR*AA123**3.0*FR*carmen*[email protected]**********";
local.sign = local.crypto.hmacSha1(local.key, local.str, "hex");
Вернуть: ff8d510f348d1a9b3652b33b8e7780c9f8d4536e
Проблема в том, как вы передаете шестнадцатеричный ключ и как пользовательский компонент использует его при создании подписи. Код внутри _getMacInstance()
, который создает secretKeySpec, манипулирует предоставленным значением — и в этом случае — создает совершенно другой ключ. Вот почему подписи не совпадают:
var secretkeySpec = createObject( "java", "javax.crypto.spec.SecretKeySpec" ).init(
toBinary( toBase64( key ) ), // Changes the key value
javaCast( "string", algorithm )
);
технически Вы можете заставить его работать, избавившись от всех преобразований и просто расшифровав ключ из шестнадцатеричного кода:
// Create the specification for our secret key.
var secretkeySpec = createObject( "java", "javax.crypto.spec.SecretKeySpec" ).init(
binaryDecode(arguments.key, "hex"), // Decodes raw HEX key
javaCast( "string", algorithm )
);
Затем, передав необработанный шестнадцатеричный ключ
crypto.hmacSha1("325A16A325127FD42B700D4810E83F6312877B92",value, "hex");
Выдает тот же результат, что и PHP 23e7db20da9b58a47e27c151a65c2393a08ee4f5
Однако вы можете захотеть изменить способ обработки ключей компонентом. Так что это немного менее хрупко. Например, вы можете изменить функции hmac * так, чтобы они принимали двоичные файлы или, возможно, даже поддерживали различные кодировки, используя arguments.encoding
, Все зависит от того, как вы собираетесь использовать ХФУ.
Других решений пока нет …