У меня есть открытый ключ RSA в формате OpenSSH:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9xmJumsHeLEDcJwf3LYONZholP3+pDHJYen4w+gm8o1r7t6oq825Gmjr7pjsQ+ZDxWivkI4vMW9RyFevPg09ljW+V7lZInBpRtB6v1s8PdmV9YVk4R3S0e7sPMPXuM7ocPLh5yKZ9f7JZwQlpp4ww/RE7blbXywjwCxngT7+G+J6HJB0UcR8xR8t6z8qDrDTAJA7pFFFNliw9M+I8tbrFl8HmoyudOFsGsYOd5hjemy4ivW88XcXzfHJdKnmD9FHVZv/GUXgErVMHS25xLcJfPalm5R8BFQrgl8SiqXj9i2vEVct9ZGydG0/Zyh2eX98D82pJhgIBmpJC4JUGv+Mt user@host
Как преобразовать в PHP этот ключ в формат, подходящий для openssl_pkey_get_public () ?
Легко извлекать номера открытых ключей RSA (n и e), потому что вторая часть строки OpenSSH – это только формат ключа с кодировкой base64, описанный в RFC4253 . Итак, на самом деле вопрос заключается в том, как кодировать эти числа в формате открытого ключа PEM RSA?
Решение:
function len($s) { $len = strlen($s); if ($len < 0x80) { return chr($len); } $data = dechex($len); $data = pack('H*', (strlen($data) & 1 ? '0' : '') . $data); return chr(strlen($data) | 0x80) . $data; } function openssh2pem($file) { list(,$data) = explode(' ', trim(file_get_contents($file)), 3); $data = base64_decode($data); list(,$alg_len) = unpack('N', substr($data, 0, 4)); $alg = substr($data, 4, $alg_len); if ($alg !== 'ssh-rsa') { return FALSE; } list(,$e_len) = unpack('N', substr($data, 4 + strlen($alg), 4)); $e = substr($data, 4 + strlen($alg) + 4, $e_len); list(,$n_len) = unpack('N', substr($data, 4 + strlen($alg) + 4 + strlen($e), 4)); $n = substr($data, 4 + strlen($alg) + 4 + strlen($e) + 4, $n_len); $algid = pack('H*', '06092a864886f70d0101010500'); // algorithm identifier (id, null) $algid = pack('Ca*a*', 0x30, len($algid), $algid); // wrap it into sequence $data = pack('Ca*a*Ca*a*', 0x02, len($n), $n, 0x02, len($e), $e); // numbers $data = pack('Ca*a*', 0x30, len($data), $data); // wrap it into sequence $data = "\x00" . $data; // don't know why, but needed $data = pack('Ca*a*', 0x03, len($data), $data); // wrap it into bitstring $data = $algid . $data; // prepend algid $data = pack('Ca*a*', 0x30, len($data), $data); // wrap it into sequence return "-----BEGIN PUBLIC KEY-----\n" . chunk_split(base64_encode($data), 64, "\n") . "-----END PUBLIC KEY-----\n"; }
Ресурсы: http://tools.ietf.org/html/rfc3447#appendix-A.1 , http://luca.ntop.org/Teaching/Appunti/asn1.html
Это старый вопрос … но я просто прошел это упражнение самостоятельно, и я зарегистрировал свое решение здесь:
Там есть образец кода для создания открытого ключа PKCS # 1 RSA из открытого ключа OpenSSH, который немного отличается от решения Jakub (которое создает открытый ключ x.509). Я попытался включить объяснения и ссылки на дополнительную документацию в записи.
Я добавляю это здесь в первую очередь потому, что этот вопрос продолжает появляться в моих поисках дополнительной информации, поэтому я надеюсь, что кто-то там найдет полезной мою попытку обобщить вещи.