PEMファイルを分割する方法


38

注:すでに答えを見つけたので、これは実際には質問ではありませんが、ここでは簡単に見つけられなかったので、他の人に役立つように投稿します。

質問:連結されたPEMファイルをapache / mod_sslディレクティブSSLCACertificateFileによって使用されるものとして読み取る方法は?

回答(オリジナル)ソース):

cat $file|awk 'split_after==1{n++;split_after=0} /-----END CERTIFICATE-----/ {split_after=1} {print > "cert" n ".pem"}'

のように末尾に空白行がある場合、空のファイルが残ることがありますopenssl pkcs7 -outform PEM -in my-chain-file -print_certs。これを防ぐには、印刷する前に行の長さを確認します。

cat $file|awk 'split_after==1{n++;split_after=0}
   /-----END CERTIFICATE-----/ {split_after=1}
   {if(length($0) > 0) print > "cert" n ".pem"}' 

回答29/03/2016

@slugchewerの回答に続いてcsplit、より明確なオプションがあります:

csplit -f cert- $file '/-----BEGIN CERTIFICATE-----/' '{*}'

これは愚かな質問かもしれませんが、なぜpemファイルを分割する必要があるのですか?
アシュワニアガルワル

6
@AshwaniAgarwal PEMファイルに複数の証明書が含まれる場合、PEMファイルを分割し、openssl1つの証明書を分析に使用するツールなどで個別に証明書を調べたい場合。
法律

さらに、一部のツールまたはサーバーは証明書とキーを組み合わせたファイルを必要としますが、別のツールまたはサーバーはそれらを別々に必要とします。
captncraig

空のファイルを防ぐために、csplitコマンドラインに「%----- BEGIN CERTIFICATE -----%」を追加する必要がありました。manページで指定されている内容と一致しているようです:csplit -f ./tmp/cert- $ file '%----- BEGIN CERTIFICATE -----%' '/ ----- BEGIN CERTIFICATE ----- / '' {*} '
クレイグヒックス

2
空のファイルを残さないようにするには、「csplit -z」を使用します。
ポールM

回答:


23

awkスニペットはさまざまな部分を抽出するために機能しますが、キー/証明書/チェーンであるセクションを知る必要があります。特定のセクションを抽出する必要があり、OpenSSLメーリングリストでこれを見つけました:http : //openssl.6102.n7.nabble.com/Convert-pem-to-crt-and-key-files-tp47681p47697.html

# Extract key
openssl pkey -in foo.pem -out foo-key.pem

# Extract all the certs
openssl crl2pkcs7 -nocrl -certfile foo.pem |
  openssl pkcs7 -print_certs -out foo-certs.pem

# Extract the textually first cert as DER
openssl x509 -in foo.pem -outform DER -out first-cert.der

素敵なコマンドセットは:)私は、将来の使用のためにそれをしておこう、しかし、上記の私のユースケースでは、私は50+ CA証明書==>無PKEYもチェーン含む証明書のみのファイルで働いている
Cerber

2
これはawkソリューションよりも優れていると思います。opensslで解析を行い、変換を取得します。
さび

申し訳ありませんが、pkeyコマンドのみが正しいです。2番目と3番目はあなたが宣伝することをしません-彼らは何か他のことをします。場合によっては、結果が良いこともありますが、場合によっては、消費者に不思議な行動を引き起こすことがあります。少し編集しました。
クバンチク

このようにしてテキストで3番目の証明書を取得する方法はありますか?
フリッカーフライ


15

このsplitコマンドはほとんどのシステムで使用でき、その呼び出しは覚えやすいでしょう。

ファイルcollection.pemに分割するindividual-*ファイルがある場合は、次を使用します。

split -p "-----BEGIN CERTIFICATE-----" collection.pem individual-

持っていない場合はsplit、試すことができますcsplit

csplit -f individual- collection.pem '/-----BEGIN CERTIFICATE-----/' '{*}'

2
申し訳ありませんが、私のシステム(busybox、fedora、centos)のいずれ-p分割時にオプション(および私が読んだマンページ)を表示しません。たぶん、あなたは特別なバイナリ/パッケージを使用しています
-Cerber

1
@Cerber csplit代わりに試すことができます...(上記の編集を参照)
squidpickles

1
でうまく動作しcsplitます!
ケルバー

FreeBSDでは、csplitから取得しますcsplit: *}: bad repetition count(ただし、分割は機能しているようです)
グウィネスLlewelyn

4

複数証明書のPEMバンドルから単一の証明書を取得する場合は、次を試してください。

$ openssl crl2pkcs7 -nocrl -certfile INPUT.PEM | \
    openssl pkcs7 -print_certs | \
    awk '/subject.*CN=host.domain.com/,/END CERTIFICATE/'
  • 最初の二つopensslのコマンドは、PEMファイルを処理し、それは事前に保留してバックアウト吐くだろう"subject:""issuer:"、各証明書の前の行。PEMがすでにこの方法でフォーマットされている場合、必要なのは最後のawkコマンドだけです。
  • awkコマンドは、CN(共通名)文字列に一致する個々のPEMを吐き出します。

ソース1ソース2


あなたの情報源にはこれは見当たりません。さらに、PEMはBase64でエンコードされているため、「subject」、「CN」などのテキストは見つかりません
。awkを使用して-Cerber

1
はい、これはすべての種類のPEMで機能するわけではありません。opensslを使用してP7BをPEMに抽出すると、各証明書の前に件名行がリストされます。または、PEMファイルをセグメント化する任意の文字列に変更できます。
cmcginty

PEMに「サブジェクト」が含まれていない場合に処理するための回答を更新しました
-cmcginty

3

また、PEMファイルBEGIN/ ENDブロック内のキー/証明書の単なるコレクションであるため、1つまたは2つの興味深いエンティティを持つ単一のファイルであれば、カット/ペーストするのは非常に簡単です...


2

証明書と認証局チェーンの連結である完全チェーン証明書(つまり、letsencrypt / certbotなどによって生成されたもの)を処理している場合、bash文字列操作を使用できます。

例えば:

# content of /path/to/fullchain.pem
-----BEGIN CERTIFICATE-----
some long base64 string containing
the certificate
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
another base64 string
containing the first certificate
in the authority chain
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
another base64 string
containing the second certificate
in the authority chain
(there might be more...)
-----END CERTIFICATE-----

証明書と認証局チェーンを変数に抽出するには:

# load the certificate into a variable
FULLCHAIN=$(</path/to/fullchain.pem)
CERTIFICATE="${FULLCHAIN%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----"
CHAIN=$(echo -e "${FULLCHAIN#*-----END CERTIFICATE-----}" | sed '/./,$!d')

説明:

awkまたはopenssl(強力なツールですが、常に利用できるとは限らない、つまりDocker Alpineイメージ)を使用する代わりに、bash文字列操作を使用できます。

"${FULLCHAIN%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----":FULLCHAINのコンテンツの終わりから、最も長い部分文字列一致を返し、-----END CERTIFICATE-----それが削除されると連結します。*後のすべての文字にマッチします-----END CERTIFICATE-----

$(echo -e "${FULLCHAIN#*-----END CERTIFICATE-----}" | sed '/./,$!d'):FULLCHAINのコンテンツの先頭から、部分文字列の最短一致を返し、次に先頭の新しい行を削除します。同様に、*前のすべての文字にマッチします-----END CERTIFICATE-----

クイックリファレンス(bash での文字列操作の詳細についてはこちらをご覧ください):

${VAR#substring}= VARのコンテンツの先頭からの最短部分文字列

${VAR%substring}= VARのコンテンツの末尾から最も短い部分文字列

${VAR##substring}= VARのコンテンツの先頭から最も長い部分文字列

${VAR%%substring}= VARのコンテンツの末尾から最も長い部分文字列


それほどbashに精通していない場合、これらの変数をエコーで囲むと、変数を引用符で囲み、それらを表示するのに使用される方法で改行を保持できます。それが私にとってそれほど明白ではなかった時期を覚えています。ファビオ、bash文字列操作の甘い使用!
フリッカーフライ

0

うーん...この状況が多くの人が持っているように思えることを知らずに、私が解決策を準備したのとほぼ同じ方法で(y @Cerber提案)。私のソリューションはほぼ同じロジックに従いますが、いくつかのより基本的なコマンドを使用します。

私のすべての証明書はファイルにあります: certin.pem

c=0
while read line
  do
    if echo $line | grep END; then
    echo $line >> certout$c.pem
    c=`expr $c + 1`
    else
     echo $line
     echo $line >> certout$c.pem
    fi
done < /tmp/certin.pem

これは基本的に、「END」に遭遇するまでファイルへの書き込みを続け、その後、増分方式で別のファイルへの書き込みを開始します。この方法では、入力PEMファイル(certin.pem)に含まれる証明書の数に応じて、「N」個の出力ファイル(certout0.pem、certout1.pemなど)ファイルが作成されます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.