PHP openssl库中的DES3方法问题

问题描述 投票:0回答:1

我有一个Web服务,其中我以“ TripleDES,ECB模式,密钥大小192和填充零”的格式发送加密的数据。提供商向我展示了原始值和预期结果的示例:

原始字符串=IA000001加密的字符串(发送到Web服务)= aVR5J/0Lph0=;

在PHP中,openssl_encrypt()函数对此字符串正常工作,但是会引发data not multiple of block length SSL错误。

我做了一个脚本来显示所有问题(带有注释):

<?php

$key = '1234567890123456ABCDEFGH';
$expected_result = 'aVR5J/0Lph0=';

function test_results($expected_value, $return_value) {
    echo openssl_error_string() . "\n";
    $compare = var_export($return_value == $expected_value, 1);
    echo "'$return_value' == '$expected_value' => {$compare}\n" ;
}

echo "Function value == Expected Value => same strings?\n";

// This works with $data == 'IA000001'
$data = 'IA000001';
$resultado_function = @openssl_encrypt($data, 'DES3', $key, OPENSSL_ZERO_PADDING);
test_results($expected_result, $resultado_function); // true

// but if I change string value (i.e. $data == 'IA000001T')
// openssl function fail:
//  error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length
$data = 'IA000001T';
$resultado_function = @openssl_encrypt($data, 'DES3', $key, OPENSSL_ZERO_PADDING);

// if change options to OPENSSL_RAW_DATA, errors gone, but strings aren't equals
$data = 'IA000001';
$resultado_function = @openssl_encrypt($data, 'DES3', $key, OPENSSL_RAW_DATA);
test_results($expected_result, $resultado_function); // false

// results are encoded in base64? not equal, but almost equal
$resultado_function = @openssl_encrypt($data, 'DES3', $key, OPENSSL_RAW_DATA);
$decoded_result = base64_encode($resultado_function);
test_results($expected_result, $decoded_result); // false but...

// Compare the firsts 11 chars:
// aVR5J/0Lph0=
// aVR5J/0Lph05HiLWyHnDqg==
//          ^-- Until this char, the strings are equal.

我做错了什么?块大小?没有编码的密钥或数据?

注意:我无法控制Web服务的实现。

php openssl php-openssl tripledes
1个回答
0
投票

我不是加密专家,但是最近从mcrypt切换到openssl时必须解决类似的问题。我认为您的数据长度必须能被8整除(即8个字符的块)。该字符串的长度为9个字符,而不是8或16个字符,因此会出现此错误。

您可以通过使用空字符填充它以达到所需的长度(即8的倍数)来克服此问题。

我将加密代码包装到一个函数中以更好地封装逻辑:

$key = '1234567890123456ABCDEFGH';
$expected_result = 'aVR5J/0Lph0=';

function test_results($expected_value, $return_value) {
    echo openssl_error_string() . "\n";
    $compare = var_export($return_value == $expected_value, 1);
    echo "'$return_value' == '$expected_value' => {$compare}\n" ;
}

function encrypt($text, $key) {
    if (strlen($text) % 8) {
        $text = str_pad($text, strlen($text) + 8 - strlen($text) % 8, "\0");
    }
    return base64_encode(openssl_encrypt($text, 'DES3', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING));
}

$data = 'IA000001T';
$resultado_function = encrypt($data, $key);
test_results($expected_result, $resultado_function); // false

输出:

'aVR5J/0Lph21RT9SWL7RSg==' == 'aVR5J/0Lph0=' => false
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.