web-dev-qa-db-ja.com

公開鍵→証明書?

公開鍵のみを使用して、公開鍵を証明書に変換することは可能ですか?

次の例を確認しました。これは、秘密鍵を使用して証明書リクエストを作成し、それを自己署名することができます。

openssl req -new -key privkey.pem -out cert.csr

しかし、公開鍵のみ(SSH、OpenSSL、PEM、PKCS8形式など)がある場合、公開鍵を含む自己署名証明書(たとえば、PKCS12形式)を作成するにはどうすればよいですか?

ありがとう

基本的に、友達の公開PGPキーを取得して証明書に変換し、ThunderbirdでEnigmaメールを使用せずに、友達のメールプログラムでその証明書を使用してメールを暗号化します。

9
Geremia

まず、あなたがしようとしていることはうまくいきません。 PGPとS/MIMEは基本的に互換性がありません。友人のPGP公開鍵をx.509証明書に入れるとS/MIMEツールを使用して友人と通信できなくなります。両方ともS/MIMEを使用する必要があるか、両方ともPGPを使用する必要があります。混ぜることはできません。

これが可能かどうかに関して:証明書はsomeoneによって署名される必要があります。公開鍵がある場合は、それを他の人が署名する証明書に埋め込むことができますが、秘密鍵なしで自己署名証明書を作成することはできません。

しかし、ここに問題があります。ユーザー指向のツール(opensslコマンドラインなど)は、(a)秘密鍵を使用して自己署名するか、(b)リクエストに署名することによってのみ証明書を作成します。

また、署名リクエスト自体は、それらが埋め込むキーを使用して署名されます。誰かのための証明書を作成するつもりなら、あなたが証明している鍵を彼らが実際に持っていることを確認したいという考え方です。

しかし... openSSL API関数を使用するなど、内部に取り掛かると、ほとんど何でも好きなことができます。未署名のリクエストと証明書を作成できます[1] (どこでも尊重されない場合があります)公開鍵と一部の属性のみを使用して証明書を作成できます。

Openssl C apiを直接使用するか、他の言語用に作成された優れたライブラリの1つを使用することを検討することもできます。

Rubyの例を次に示します。この例は grawity による編集として提供されています。私はこのコードをテストしていません。

#!/usr/bin/env Ruby
require 'openssl'

pkey_data = File.read("id_rsa")
pkey_password = ""
subject = "/O=Honest Achmed's Used Cars and Certificates/OU=Self-made/CN=Geremia's cert"
expiry_years = 1

# Fill basic v1 fields
cert = OpenSSL::X509::Certificate.new
cert.version = 2  # for X.509 v3
cert.serial = 1
cert.subject = OpenSSL::X509::Name.parse(subject)
cert.issuer = cert.subject
cert.not_before = Time.now
cert.not_after = Time.now + (expiry_years * 365 * 86400)

# Add v3 extensions
extf = OpenSSL::X509::ExtensionFactory.new
extf.subject_certificate = cert
extf.issuer_certificate = cert
cert.extensions = [
    # basicConstraints is marked as 'critical' here
    extf.create_extension("basicConstraints", "CA:FALSE", true),
    extf.create_extension("subjectKeyIdentifier", "hash"),
    # 'copy' means needed information will be taken from subjectKeyIdentifier
    extf.create_extension("authorityKeyIdentifier",
        "keyid:copy, issuer:copy"),
    extf.create_extension("keyUsage",
        "digitalSignature, keyEncipherment, nonRepudiation"),
    extf.create_extension("extendedKeyUsage",
        "clientAuth, serverAuth, emailProtection"),
]

# Add public key and self-sign – if you omit the cert.sign()
# call, you WILL have an unsigned certificate made just with the public key.
pkey = OpenSSL::PKey::RSA.new(pkey_data, pkey_password)
cert.public_key = pkey
cert.sign(pkey, OpenSSL::Digest::SHA1.new)

# Output in PEM format (aka base64-encoded DER)
puts cert.to_pem
  • [1] 10年ほど前、私は.NET用のOpenSSL相互運用ライブラリを作成しました。幸いなことに、このプロジェクトを見た人は誰もいませんでした。
11
tylerl

PKCS#12 はほぼすべての一般的なアーカイブ形式ですが、実際には、証明書を格納するために使用されますその秘密鍵とともに。友達の秘密鍵はなく、公開鍵しかないため、PKCS#12アーカイブを作成しても意味がありません。

同じ理由で、署名の生成には所有していない秘密鍵を使用する必要があるため、self-signed証明書を作成することはできません。ただし、証明書の自己署名には魔法のようなものはありません。 X.509証明書 は通常Certification Authority(CAは「証明書を発行する」と呼ばれます)によって署名されるため、証明書の形式には署名用のフィールドが含まれます。証明書がCAによって生成されていない場合、フィールドには何らかの値を入力する必要があります。自己署名を使用するのはtraditionalですが、その署名には有用な情報の点で多くは含まれていません、そしてほとんどのソフトウェアはそれをまったく気にしません。エンコードとデコードのルーチンが機能するように、おおよそのサイズのblobが必要です。

したがって、「証明書として」公開鍵が必要な場合は、CAからの署名の代わりに、ランダムなジャンクと一緒に値を詰め込むことができます。 @tylerlが説明するように、実際のCAソフトウェア(例 OpenSSL )を使用して証明書を作成する方が簡単です。構造はすべて ASN.1 で複雑であるためです。詳細。ほとんどの本格的なCA製品では、公開キーを PKCS#10リクエスト として提供する必要があります。これには、公開キーが含まれますが、対応する秘密キーで署名され、秘密鍵の所有者は本当に証明書を取得したいと考えています。ただし、これは署名システムに固有のものではありません。どのCAでも、任意のソースから取得した公開鍵を含む任意のデータを使用して証明書を作成し、署名することは技術的に可能です。一部の証明書対応ライブラリを直接使用すると、トリックを実行できます。


次に、「PGP」部分について説明します。 OpenPGP形式 はX.509とはまったく異なり、これは電子メールの暗号化方法にも適用されます。 X.509証明書が関係する場合、エンコーディングはOpenPGPではなく S/MIME に依存します。あなたがやろうとしていることに対して、これは2つの結果をもたらします:

  • 友人の公開鍵がX.509形式に適合するとは限りません。 RSAキーは問題ないはずです。ただし、OpenPGPは、X-509ルールのように広範囲に及ぶ標準エンコーディングがない ElGamal keys を使用することがよくあります。 S/MIMEソフトウェア(Thunderbirdなど)は、X.509証明書にあるElGamalキーを理解して使用できません。

  • あなたが暗号化を行ったとしても、あなたの友人は彼の側で同じ問題を抱えています。彼は、OpenPGP形式でのみ格納した秘密鍵を使用してS/MIMEとその復号ルールを適用するためにhisソフトウェアを説得する必要があります。

特に後者の点は、おそらくあなたの友人がalso彼の秘密鍵を抽出し、公開鍵のある種のX.509証明書を取得する必要があることを意味します。その場合、himに任せるほうが簡単です。公開鍵の証明書を作成または取得したら、彼に送信してもらいます。


[〜#〜] pki [〜#〜] の主なポイントは、IDと公開鍵の間のバインディングに関する信頼を伝えることです。 PGPの世界のデータから独自のX.509証明書を作成することで、この信頼をどうにかして無視します。したがって、正しい公開鍵を使用していることを確認するには、いくつかのother方法が必要になります。これは必ずしも間違っているわけではありませんが、「手動」で行うことに注意してください。そのためには、暗号化の詳細まで、nderstand何が起こっているかが必要です。

3
Thomas Pornin