(Erlang) извлечение открытого ключа из сертификата в формате pem

У меня есть сертификат в формате pem, и я хочу извлечь открытый ключ (RSA). Я уже так далеко:

{ok, PemBin} = file:read_file("/path/to/certificate.pem").
[Certificate] = public_key:pem_decode(PemBin).

Теперь я могу сделать следующее:

public_key:pem_entry_decode(Certificate).

Это дает мне кортеж со всевозможными подробностями о сертификате, но я нигде не вижу записи для открытого ключа. Как получить открытый ключ из этого сертификата? Должно быть прямолинейно, но я не могу найти для этого никакой функции в модуле public_key.


person Jeyhey    schedule 21.02.2016    source источник


Ответы (2)


Хорошо, вот полная функция в модуле:

-module(crypto_helper).
-include_lib("public_key/include/public_key.hrl").
-export([get_public_key_from_cert/1]).

get_public_key_from_cert(PathToCert) ->
   {ok, PemBin} = file:read_file(PathToCert),
   PemEntries = public_key:pem_decode(PemBin),
   {value, CertEntry} = lists:keysearch(‘Certificate’, 1, PemEntries)
   {_, DerCert, _} = CertEntry,
   Decoded = public_key:pkix_decode_cert(DerCert, otp),
   PublicKey = Decoded#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.subjectPublicKeyInfo#'OTPSubjectPublicKeyInfo'.subjectPublicKey,
   PublicKey.

Теперь вы можете использовать его следующим образом:

PublicKey = crypto_helper:get_public_key_from_cert("/usr/admin/myServer/priv/certificate.pem"),
EncryptedMsg = public_key:encrypt_public(<<"Hallo">>, PublicKey),
person Jeyhey    schedule 22.02.2016

public_key:pem_entry_decode(Certificate) возвращает запись Certificate. Чтобы извлечь из него открытый ключ, вам нужно загрузить определения записей. В оболочке Erlang введите следующее:

rr(public_key).

После загрузки определений записей в оболочку возвращаемые значения будут содержать имена полей, а также значения полей, что должно немного прояснить ситуацию.

В модуле Erlang загрузите файл заголовка следующим образом:

-include_lib("public_key/include/public_key.hrl").

Затем вы можете извлечь информацию об открытом ключе следующим образом:

DecodedCertificate = public_key:pem_entry_decode(Certificate).
DecodedCertificate#'Certificate'.tbsCertificate#'TBSCertificate'.subjectPublicKeyInfo.

который возвращает:

#'SubjectPublicKeyInfo'{
    algorithm = 
        #'AlgorithmIdentifier'{
            algorithm = {1,2,840,113549,1,1,1},
            parameters = <<5,0>>},
    subjectPublicKey = 
        <<48,130,2,10,2,130,2,1,0,195,76,200,181,90,146,51,183,
          39,91,176,28,95,117,241,28,140,...>>}

Или копайте на один уровень ниже, чтобы получить сам ключ:

DecodedCertificate#'Certificate'.tbsCertificate
    #'TBSCertificate'.subjectPublicKeyInfo
    #'SubjectPublicKeyInfo'.subjectPublicKey.
<<48,130,2,10,2,130,2,1,0,195,76,200,181,90,146,51,183,39,
  91,176,28,95,117,241,28,140,212,223,132,...>>
person legoscia    schedule 22.02.2016
comment
Спасибо, это мне очень помогло. Отсутствует только последний шаг, когда вы декодируете открытый ключ и получаете тип rsa_public_key(), который вы должны использовать в public_key:decrypt_public/2. - person Jeyhey; 23.02.2016
comment
Существует вероятность того, что subjectPublicKey может быть {0, KeyDer} = DecodedCertificate#'Certificate'.tbsCertificate #'TBSCertificate'.subjectPublicKeyInfo #'SubjectPublicKeyInfo'.subjectPublicKey. Где KeyDer — это Der Encoded, если ключ имеет тип RSA RsaPublicKey = public_key:der_decode('RSAPublicKey', KeyDer). Теперь RsaPublicKey имеет тип rsa_public_key() - person Srikanth Kyatham; 06.04.2016