英文:
generate MAC ISO/IEC 9797-1 in php
问题
我正在尝试在PHP中使用32字符的十六进制密钥从XML生成ISO/IEC 9797-1 MAC,但我无法获得预期的结果。
我尝试过使用open_ssl和phpseclib的各种方法,但都没有得到预期的输出。
为了验证我的MAC,我使用网站https://paymentcardtools.com/emv-misc/mac-calculator,在数据字段中将我的XML转换为十六进制,使用填充方法1,并输入我的32位数字密钥。
我需要知道如何在PHP中实现相同的结果。有人以前做过类似的事情吗?
英文:
I am trying to generate an ISO/IEC 9797-1 MAC from an XML with a 32-character Hex key in PHP, but I am not able to get the expected result.
I have tried various approaches using open_ssl and phpseclib, but none of them result in the expected output.
To validate my MAC, I am using the website https://paymentcardtools.com/emv-misc/mac-calculator, where I convert my XML to hex in the Data field, use padding method 1, and input my 32-digit key.
I need to know how I can achieve the same result in PHP. Has anyone done something like this before?
$length = strlen($message);
$padding = 8 - ($length % 8);
$message .= str_repeat(chr(0), $padding);
// Separate the first DES key and 3DES key
$des_key = substr($key, 0, 8);
$tripledes_key = substr($key, 8, 16);
// Use the first DES key for CBC-MAC
$cbc_mac = openssl_encrypt($message, 'DES-ECB', $des_key, OPENSSL_RAW_DATA);
// Use 3DES for the final block
$last_block = substr($message, -8);
$tripledes_cipher = openssl_encrypt($last_block, 'DES-EDE3-ECB', $tripledes_key, OPENSSL_RAW_DATA);
// The result is the last 8 bytes of the triple DES cipher
return substr(strtoupper(bin2hex(substr($tripledes_cipher, -8))), 0, 8);
答案1
得分: 2
要确定MAC(根据算法3),需要执行以下步骤:
可能的PHP实现(包括测试数据)如下:
<?php
function xored($data1, $data2) {
$result = '';
for($n = 0; $n < strlen($data1); $n++){
$result .= substr($data1, $n, 1) ^ substr($data2, $n, 1);
}
return $result;
}
function encrypt($data, $key){
return openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
}
function decrypt($data, $key){
return openssl_decrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
}
$messageHex = '54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67';
$message = hex2bin($messageHex);
// 获取第1个和第2个DES密钥
$keyHex = '04984575FE4A526123D6F876B3E3371A';
$key = hex2bin($keyHex);
$desKey1 = substr($key, 0, 8);
$desKey2 = substr($key, 8, 16);
// 填充方法1:仅在长度标准未满足时进行零填充
$length = strlen($message);
$padding = (8 - ($length % 8)) % 8;
$message .= str_repeat(chr(0), $padding);
// 输入/初始转换1和迭代
$messageLen = strlen($message);
for ($i = 0; $i < $messageLen; $i = $i + 8) {
$d = substr($message, $i, 8);
$i == 0 ? $in = $d : $in = xored($d, $h);
$h = encrypt($in, $desKey1);
}
// 输出转换3
$innerDecryption = decrypt($h, $desKey2);
$outerEncryption = encrypt($innerDecryption, $desKey1);
// 截断
$mac = substr($outerEncryption, 0, 8);
print(bin2hex($mac) . PHP_EOL); // 37b44913c7a43700
?>
使用的测试数据,MAC与链接的网站一致,为0x37b44913c7a43700:
英文:
The steps required to determine the MAC (according to algorithm 3) are (here):
- padding (OP applied method 1), s. here
- input/initial transformation 1, s. here and iteration, s. here
- output transformation 3, s. here
- truncation, s. here
A possible PHP implementation is (including test data):
<?php
function xored($data1, $data2) {
$result = '';
for($n = 0; $n < strlen($data1); $n++){
$result .= substr($data1, $n, 1) ^ substr($data2, $n, 1);
}
return $result;
}
function encrypt($data, $key){
return openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
}
function decrypt($data, $key){
return openssl_decrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
}
$messageHex = '54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67';
$message = hex2bin($messageHex);
// get 1st and 2nd DES key
$keyHex = '04984575FE4A526123D6F876B3E3371A';
$key = hex2bin($keyHex);
$desKey1 = substr($key, 0, 8);
$desKey2 = substr($key, 8, 16);
// padding method 1: zero pad only if length criterion is not met
$length = strlen($message);
$padding = (8 - ($length % 8)) % 8;
$message .= str_repeat(chr(0), $padding);
// input/initial transformation 1 and iteration
$messageLen = strlen($message);
for ($i = 0; $i < $messageLen; $i = $i + 8) {
$d = substr($message, $i, 8);
$i == 0 ? $in = $d : $in = xored($d, $h);
$h = encrypt($in, $desKey1);
}
// output transformation 3
$innerDecryption = decrypt($h, $desKey2);
$outerEncryption = encrypt($innerDecryption, $desKey1);
// truncation
$mac = substr($outerEncryption, 0, 8);
print(bin2hex($mac) . PHP_EOL); // 37b44913c7a43700
?>
For the test data used, the MAC is 0x37b44913c7a43700 in accordance with the linked web site:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论