В настоящее время я поддерживаю библиотеку Alipay URL-генерации, и в этом фрагменте кода происходит несколько интересных вещей (кроме очень запутанных схем именования и размещения функций).
У меня есть функция, которая создает URL (используя create_linkstring()
) + его RSA-подписано (sign()
) аналог:
function build_mysign($sort_array,$key,$sign_type) {
$prestr = create_linkstring($sort_array);
$prestr = $prestr.$key;
$mysgin = sign($prestr,$sign_type);
return $mysgin;
}
Это мое create_linkstring()
метод:
function create_linkstring($array) {
$arg = "";
while (list ($key, $val) = each ($array)) {
$arg.=$key."=".$val."&";
}
$arg = substr($arg,0,count($arg)-2);
return $arg;
}
Это мое sign()
функция:
function sign($prestr){
$fprivate = fopen(dirname(__FILE__) . '/rsa_private_key.pem', 'r');
$priv_key = fread($fprivate, 123456);
fclose($fprivate);
$privatekeyid = openssl_get_privatekey($priv_key);
// Compute signature
openssl_sign($prestr, $signMsg, $privatekeyid, OPENSSL_ALGO_SHA1);
// Free the key from memory
openssl_free_key($privatekeyid);
$signMsg = base64_encode($signMsg);
return $signMsg;
}
Он в основном принимает массив ключей и значений и генерирует URL, который затем подписывается с использованием sign()
метод.
Эта библиотека на самом деле имеет два механизма подписи — MD5 и RSA. Я написал функцию подписи RSA, так как она не была поддержана по умолчанию. Глядя на выходной URL-адрес использования подписи MD5, sign=
это строка из 32 символов, так что это выглядит так sign=779d70d2b4d9b50cad3a4ce144726e9f
,
Однако, используя мою функцию подписи RSA, на выходе получается строка из 172 символов! Вход выглядит так:
&знак = WiYQIl0x + Vkey3SciP03HDv / 7IZKoq2 + OcvsSlQJb3NMElG6JawRc5b98ddJOOYjt9YK2YypwlFWgizj0b5wk + HNJB5lSYq7rDCcDGG0m0cKbW / m9P23J8gQaR1x6RovEDaWhs5zv4YTFe83hmPaf4Q / eVa2CpiixjpHd3kjybg =
Если я не ошибаюсь, RSA-подписанные строки должны иметь длину 128 символов. Я не совсем уверен, почему это происходит. Я не на 100%, если я добавляю это с посторонними строками, и я замечаю, что все ключи, подписанные RSA, заканчиваются =
что определенно не правильно.
Я предполагаю, что вы путаете длину байта подписи RSA с длиной строки кодировки base64 подписи.
Если вы используете 1024-битный ключ RSA (немного короткий, кстати), длина подписи в байтах должна составлять 128 байтов. Байты могут иметь любое значение, включая 0
и другие символы, которые нельзя распечатать с помощью UTF-8 или ASCII (и многие другие, которые не подходят для использования в URL-адресах и т. д.). Таким образом, ваш код кодирует байты в base64. Размер 172 символа (включая отступы) =
) как раз прав: 128 байтов / 1024 бит
$ echo WiYQIl0x+Vkey3SciP03HDv/7IZKoq2+OcvsSlQJb3NMElG6JawRc5b98ddJOOYjt9YK2YypwlFWgizj0b5wk+HNJB5lSYq7rDCcDGG0m0cKbW/m9P23J8gQaR1x6RovEDaWhs5zv4YTFe83hmPaf4Q/eVa2CpiixjpHd3kjybg= \
| base64 --decode | hexdump -C
00000000 5a 26 10 22 5d 31 f9 59 1e cb 74 9c 88 fd 37 1c |Z&."]1.Y..t...7.|
00000010 3b ff ec 86 4a a2 ad be 39 cb ec 4a 54 09 6f 73 |;...J...9..JT.os|
00000020 4c 12 51 ba 25 ac 11 73 96 fd f1 d7 49 38 e6 23 |L.Q.%..s....I8.#|
00000030 b7 d6 0a d9 8c a9 c2 51 56 82 2c e3 d1 be 70 93 |.......QV.,...p.|
00000040 e1 cd 24 1e 65 49 8a bb ac 30 9c 0c 61 b4 9b 47 |..$.eI...0..a..G|
00000050 0a 6d 6f e6 f4 fd b7 27 c8 10 69 1d 71 e9 1a 2f |.mo....'..i.q../|
00000060 10 36 96 86 ce 73 bf 86 13 15 ef 37 86 63 da 7f |.6...s.....7.c..|
00000070 84 3f 79 56 b6 0a 98 a2 c6 3a 47 77 79 23 c9 b8 |.?yV.....:Gwy#..|
00000080
Других решений пока нет …