(Erlang) 从 pem 格式的证书中提取 public 密钥

(Erlang) extracting public key from certificate in pem format

我有一个 pem 格式的证书,我想提取 public 密钥 (RSA)。我已经走了这么远:

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

现在,我可以执行以下操作:

public_key:pem_entry_decode(Certificate).

这给了我一个包含证书各种详细信息的元组,但我在任何地方都看不到 public 密钥的条目。如何从此证书中获取 public 密钥?应该是直截了当的,但我在 public_key-module 中找不到任何函数。

public_key:pem_entry_decode(Certificate) return 一条 Certificate 记录。要从中提取 public 键,您需要加载记录定义。在 Erlang shell 中,键入以下内容:

rr(public_key).

将记录定义加载到 shell 后,return 值将包含字段名称和字段值,这应该会使事情更清楚一些。

在 Erlang 模块中,像这样加载头文件:

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

然后你可以像这样提取public关键信息:

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

其中 return 个:

#'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,...>>

好的,这是模块中的完整功能:

-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),