Yandex RSA посредством PHP

Многие работали с API Яндекса. Помимо общепринятой OAuth авторизации API Яндекс.Фоток поддерживает еще и авторизацию по логину и паролю пользователя. Сложность состоит в том, что для шифрования пользовательских данных они используют свой собственный алгоритм.
На хабре можно найти примеры на python и javascript, я же хочу предоставить вашему вниманию реализацию этого алгоритма на php.

Поскольку данный метод шифрования использует значения, значительно превосходящие int, для реализации алгоритма я решил использовать GMP.
Справедливости ради должен отметить, что для работы с большими числами в php так же существует BCMath, но он не позволяет переводить числа в разные системы счисления, хотя, в отличии от GMP, расширение BCMath входит в стандартный пакет php.

Еще стоит отметить, что функция hex2bin требует PHP >= 5.4.0

Собственно, сам скрипт
<code class="php">function yandex_rsa($public_key, $text)
{	
	$DATA_ARR = array();

	list($NSTR, $ESTR) = explode('#', $public_key);

	$N = gmp_strval(gmp_init($NSTR, 16));
	$E = gmp_strval(gmp_init($ESTR, 16));

	$STEP_SIZE = strlen($NSTR)/2-1;
	$prev_crypted = array();
	
	for($i=0;$i<$STEP_SIZE;$i++)
		array_push($prev_crypted, false);
	
	$hex_out = "";

	for($i=0; $i<strlen($text); $i++)
		array_push($DATA_ARR, ord(substr($text, $i, 1)));
	
	for($i=0; $i<((count($DATA_ARR)-1)/($STEP_SIZE+1)); $i++)
	{
		$tmp = array_slice($DATA_ARR, $i*$STEP_SIZE, ($i+1)*$STEP_SIZE);
		
		for($j=0;$j<count($tmp);$j++)
			$tmp[$j] = ($tmp[$j] ^ $prev_crypted[$j]);
		
		$tmp = array_reverse($tmp);
		$plain = 0;
		for($x=0;$x<count($tmp);$x++)
		{
			$pow_mult = gmp_mul($tmp[$x], gmp_powm(256, $x, $N));
			$plain = gmp_add($plain, $pow_mult);
		}
		
		$hex_result = gmp_strval(gmp_powm($plain, $E, $N), 16);
		
		$array = array();
		for($j=0;$j<strlen($NSTR)-strlen($hex_result)+1;$j++)
			array_push($array, false);
			
		$hex_result = implode('0', $array).$hex_result;
		
		for($x=0;$x<min(strlen($hex_result), count($prev_crypted)*2);$x+=2)
			$prev_crypted[$x/2] = gmp_intval(substr($hex_result, $x, 2));
		
		if(count($tmp) < 16)
			$hex_out .= '00';	
		
		$hex_out .= strtoupper(dechex(count($tmp))).'00';
		
		$ks = strlen($NSTR)/2;
		
		if($ks < 16)
			$hex_out .= '0';
		
		$hex_out .= strtoupper(dechex($ks)).'00';
		$hex_out .= $hex_result;
	}
	
	return preg_replace('#\n\t\s#', '', base64_encode(hex2bin($hex_out)));
}
</code>

Ссылки по теме:
My Yandex.Fotki Uploader (Myf) — начало открытого тестирования — реализация на python и javascript
Один из комментариев к этой статье побудил меня к написанию данного поста.
Реализация на perl
Реализация RSA класса на PHP — стандартный алгоритм.


0 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.