web-dev-qa-db-ja.com

OpenSSLを使用したSMIME電子メール復号化キー

Opensslコマンドを使用して、電子メールのコンテンツを暗号化/復号化するためのキーを取得および復号化できるかどうかを知りたいです。私はこのようなもので暗号化されたメール全体を復号化できることを知っています

openssl smime -decrypt -in enc_mail.eml -inkey recip_priv.pem > dec_mail.eml

ただし、その間の手順を教えてください。手順を正しく理解していれば、メールの実際の内容は受信者の公開鍵ではなく、送信者側でランダムに生成された鍵で暗号化されています。この鍵は、受信者の公開鍵で暗号化され、暗号化されたメッセージに添付されます。私は正しいですか? opensslを使用して、添付された暗号化キーを表示し、個別に復号化することはできますか?

ありがとう。

10
Jakub Žitný

はい、できます。この例では、openssl smimeをデフォルトのRC2 CBCと40ビットのキーで使用しています。新しい cmsサブコマンドの動作は少し異なります で、デフォルトで3-DESを使用します。 重要なデータを暗号化するためにこれらのアルゴリズムのどちらも使用するべきではありません;-)

2つのマイナーな警告があります。1つ目は、他のいくつかのツールも使用します(ただし、OpenSSLはすべての重い作業に使用されます)、2つ目は電子メールがどのように暗号化されたかについていくつかの仮定を行うため。

En/decryptionは、ほとんどのRSAを使用する方法のラインに沿っています:(低速で高価な)RSAを使用して対称鍵をen/decryptし、高速対称鍵を使用して実際のデータをen/decryptします。 (詳細については this question または this を参照してください)。

メールを受け取り、P7M部分を抽出してデコードします。 base64でエンコードされた単一の.p7mパーツがある場合、metamailを使用してこれを簡単に行うことができます。

$ metamail -wy enc_mail.eml

P7Mファイルを保存します。これは ASN.1 DERエンコードされた [〜#〜] cms [〜#〜] (PKCS#7)ファイルなので、中を覗くことができます。

  $ dumpasn1 -tilda  smime.p7m
   0 1946: SEQUENCE {
   4    9: . OBJECT IDENTIFIER envelopedData (1 2 840 113549 1 7 3)
         : . . (PKCS #7)
  15 1931: . [0] {
                  [ .. certificate details and whatnot omitted ...]
 188   13: . . . . . SEQUENCE {
 190    9: . . . . . . OBJECT IDENTIFIER rsaEncryption (1 2 840 113549 1 1 1)
         : . . . . . . . (PKCS #1)
 201    0: . . . . . . NULL
         : . . . . . . }
 203  256: . . . . . OCTET STRING    
         : . . . . . . A0 DA EA FB EA 1A 0F 81    ........
         : . . . . . . F4 30 9F 78 5C 9B A7 27    .0.x\..'
                       [ ... blob snipped ...]
 463 1483: . . . SEQUENCE {
 467    9: . . . . OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
         : . . . . . (PKCS #7)
 478   26: . . . . SEQUENCE {
 480    8: . . . . . OBJECT IDENTIFIER rc2CBC (1 2 840 113549 3 2)
         : . . . . . . (RSADSI encryptionAlgorithm)
 490   14: . . . . . SEQUENCE {
 492    2: . . . . . . INTEGER 160
 496    8: . . . . . . OCTET STRING 3E EA 0E 12 37 A8 56 70                 
         : . . . . . . }
         : . . . . . }
 506 1440: . . . . [0]    
         : . . . . . A5 FF A1 70 2C AD 82 6A    ...p,..j
         : . . . . . C7 F0 84 E8 9E 93 8F 53    .......S
                     [... blob snipped ...]

私が使用しているのは dumpasn1 です。これは、openssl asn1parseが関心のあるさまざまなblobを表示またはダンプすることを拒否するためです。メールの構造は、上記のものとは異なります。列1と2は、それぞれの(おそらくネストされた)サブ構造のオフセットとサイズです。

興味深い部分はオフセットにあります:

  • 188RSA暗号化の詳細、続いてオフセット203で暗号化されたデータ
  • 463S/MIME暗号化の詳細とパラメーター(RC2 CBC)
  • 506暗号化されたblob

オフセット188では、RSAが使用され、続いて256バイトのデータが使用されていることがわかります。そのため、そのデータBLOB(オフセット203)を抽出し、バイナリに変換します。

$ dumpasn1 -a -203 smime.p7m | tail -qn +2 | xxd -r -p > rsa.bin

(開始オフセット-203と、出力の最初の行をスキップするためのtailの使用に注意してください。これは少し複雑ですが、残念ながらdumpasn1openssl asn1parseはtype-lengthプレフィックスは、オブジェクトをスライスしてダイスするときにそのまま残ります。)

RSAを使用してこのデータを復号化します。

$ openssl rsautl -inkey recip_priv.pem -in rsa.bin -decrypt -out rc2key.bin
$ xxd -u -p  rc2key.bin
92F6EB53B1

この場合、必要な対称鍵である5バイト(40ビット)の出力が得られます。入力は PKCS#1 v1.5 パディングされた(§8.1を参照) さまざまな理由 でしたので、サイズの差異が生じました。

メインのペイロード(電子メール)は、オフセット506のblobにあります。それをファイルに抽出します。

$ dumpasn1 -a -506 smime.p7m | tail -qn +2 | xxd -r -p > email.bin

これが少しトリッキーなビットです。RC2については、 RFC 2268 のセクション6を参照してください。

rc2CBC OBJECT IDENTIFIER
 ::= {iso(1) member-body(2) US(840) rsadsi(113549)
      encryptionAlgorithm(3) 2}

RC2-CBCParameter ::= CHOICE {
  iv IV,
  params SEQUENCE {
    version RC2Version,
    iv IV
  }
}

RC2Version ::= INTEGER -- 1-1024
IV ::= OCTET STRING -- 8 octets

これは、オフセット490のデータ構造を説明しています。

 480    8: . . . . . OBJECT IDENTIFIER rc2CBC (1 2 840 113549 3 2)
         : . . . . . . (RSADSI encryptionAlgorithm)
 490   14: . . . . . SEQUENCE {
 492    2: . . . . . . INTEGER 160
 496    8: . . . . . . OCTET STRING 3E EA 0E 12 37 A8 56 70                 
         : . . . . . . }

(RC2Version 160(0xa0)がEKBテーブルのキーサイズ40ビット(0x28)と一致することを確認できます。)

つまり、S/MIME暗号化アルゴリズム(RC2 40ビットCBC、オフセット480)、RC2キー(オフセット203でblobから復号化)、RC2 IV(暗号化なし、オフセット496)、および暗号化ペイロード(オフセット506):

$ openssl enc -d -rc2-40-cbc -in email.bin -out email.txt -K 92F6EB53B1 -iv 3EEA0E1237A85670

そしてemail.txtはあなたが探しているものでなければなりません。

チップ:

  • xxdの古いバージョンを使用しないようにしてください。入力の16進データが壊れる可能性があります
  • もちろん、構造、サイズ、オフセットはメッセージ、キー、アルゴリズムによって異なります
  • openssl enc -kfile ...が機能しないので、-Kを使用します
  • openssl smimemayが暗号化前にメッセージを変更しました( [〜#〜] crlf [〜#〜] 要件)
  • berdump は、その出力がさらに処理されやすいため、便利なツールです。 DERはBERのサブセットであるため、PKCS#7 DERファイルを直接指すことができます。
10
mr.spuratic

S/MIMEPKCS7 を使用します。おそらく、自分でコードを記述する必要があります。

C++でこれを行う方法の例を次に示します。 https://stackoverflow.com/questions/6369096/how-to-read-the-certificates-file-from-the-pkcs7-p7b-certificate-file -usind-open

そして、これはJavaの例です: https://stackoverflow.com/questions/11026588/pkcs7-encryption

0
ceving