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

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

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?

  1. $length = strlen($message);
  2. $padding = 8 - ($length % 8);
  3. $message .= str_repeat(chr(0), $padding);
  4. // Separate the first DES key and 3DES key
  5. $des_key = substr($key, 0, 8);
  6. $tripledes_key = substr($key, 8, 16);
  7. // Use the first DES key for CBC-MAC
  8. $cbc_mac = openssl_encrypt($message, 'DES-ECB', $des_key, OPENSSL_RAW_DATA);
  9. // Use 3DES for the final block
  10. $last_block = substr($message, -8);
  11. $tripledes_cipher = openssl_encrypt($last_block, 'DES-EDE3-ECB', $tripledes_key, OPENSSL_RAW_DATA);
  12. // The result is the last 8 bytes of the triple DES cipher
  13. return substr(strtoupper(bin2hex(substr($tripledes_cipher, -8))), 0, 8);

答案1

得分: 2

要确定MAC(根据算法3),需要执行以下步骤:

  • 填充(使用操作方法1),请参见此处
  • 输入/初始转换1,请参见此处和迭代,请参见此处
  • 输出转换3,请参见此处
  • 截断,请参见此处

可能的PHP实现(包括测试数据)如下:

  1. <?php
  2. function xored($data1, $data2) {
  3. $result = '';
  4. for($n = 0; $n < strlen($data1); $n++){
  5. $result .= substr($data1, $n, 1) ^ substr($data2, $n, 1);
  6. }
  7. return $result;
  8. }
  9. function encrypt($data, $key){
  10. return openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
  11. }
  12. function decrypt($data, $key){
  13. return openssl_decrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
  14. }
  15. $messageHex = '54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67';
  16. $message = hex2bin($messageHex);
  17. // 获取第1个和第2个DES密钥
  18. $keyHex = '04984575FE4A526123D6F876B3E3371A';
  19. $key = hex2bin($keyHex);
  20. $desKey1 = substr($key, 0, 8);
  21. $desKey2 = substr($key, 8, 16);
  22. // 填充方法1:仅在长度标准未满足时进行零填充
  23. $length = strlen($message);
  24. $padding = (8 - ($length % 8)) % 8;
  25. $message .= str_repeat(chr(0), $padding);
  26. // 输入/初始转换1和迭代
  27. $messageLen = strlen($message);
  28. for ($i = 0; $i < $messageLen; $i = $i + 8) {
  29. $d = substr($message, $i, 8);
  30. $i == 0 ? $in = $d : $in = xored($d, $h);
  31. $h = encrypt($in, $desKey1);
  32. }
  33. // 输出转换3
  34. $innerDecryption = decrypt($h, $desKey2);
  35. $outerEncryption = encrypt($innerDecryption, $desKey1);
  36. // 截断
  37. $mac = substr($outerEncryption, 0, 8);
  38. print(bin2hex($mac) . PHP_EOL); // 37b44913c7a43700
  39. ?>

使用的测试数据,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):

  1. <?php
  2. function xored($data1, $data2) {
  3. $result = '';
  4. for($n = 0; $n < strlen($data1); $n++){
  5. $result .= substr($data1, $n, 1) ^ substr($data2, $n, 1);
  6. }
  7. return $result;
  8. }
  9. function encrypt($data, $key){
  10. return openssl_encrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
  11. }
  12. function decrypt($data, $key){
  13. return openssl_decrypt($data, 'DES-ECB', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
  14. }
  15. $messageHex = '54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67';
  16. $message = hex2bin($messageHex);
  17. // get 1st and 2nd DES key
  18. $keyHex = '04984575FE4A526123D6F876B3E3371A';
  19. $key = hex2bin($keyHex);
  20. $desKey1 = substr($key, 0, 8);
  21. $desKey2 = substr($key, 8, 16);
  22. // padding method 1: zero pad only if length criterion is not met
  23. $length = strlen($message);
  24. $padding = (8 - ($length % 8)) % 8;
  25. $message .= str_repeat(chr(0), $padding);
  26. // input/initial transformation 1 and iteration
  27. $messageLen = strlen($message);
  28. for ($i = 0; $i < $messageLen; $i = $i + 8) {
  29. $d = substr($message, $i, 8);
  30. $i == 0 ? $in = $d : $in = xored($d, $h);
  31. $h = encrypt($in, $desKey1);
  32. }
  33. // output transformation 3
  34. $innerDecryption = decrypt($h, $desKey2);
  35. $outerEncryption = encrypt($innerDecryption, $desKey1);
  36. // truncation
  37. $mac = substr($outerEncryption, 0, 8);
  38. print(bin2hex($mac) . PHP_EOL); // 37b44913c7a43700
  39. ?>

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:

确定