生成 MAC(消息认证码)ISO/IEC 9797-1 在 PHP 中。

huangapple go评论82阅读模式
英文:

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),需要执行以下步骤:

  • 填充(使用操作方法1),请参见此处
  • 输入/初始转换1,请参见此处和迭代,请参见此处
  • 输出转换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:

生成 MAC(消息认证码)ISO/IEC 9797-1 在 PHP 中。

英文:

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:

生成 MAC(消息认证码)ISO/IEC 9797-1 在 PHP 中。

huangapple
  • 本文由 发表于 2023年8月4日 05:54:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831808.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定