オブジェクトの広場はオージス総研グループのエンジニアによる技術発表サイトです

組み込み/セキュリティ

暗号用語の体系的整理

エンジニアが実際に使う暗号の基礎知識
オージス総研 組み込みソリューション部
大坂 幸治
2021年7月14日

署名はRSASSA-PSS 2048 SHA-1で、salt長は…なんて言われて各単語の意味や位置付けが分からず困ったことはありませんか?ややこしい暗号関連の用語を体系的に整理してすっきり理解しましょう。

はじめに

暗号の用語って似たような単語があってややこしい!と思ったことはありませんか?

本稿は暗号に関する専門用語を体系的に整理したものです。暗号に関する主要なキーワードを紹介していますが、個々の要素技術を深く掘り下げることはしません。

ネットで検索するのに適当なキーワードが思いつかない、似たような単語が複数あってイマイチ使い分けに自信がない、セキュリティに関する業務をやることになったけどどこから手を付けていいか分からない、というような方を想定読者にしています。

目次:暗号用語の体系的整理

  • はじめに
    • 目次:暗号用語の体系的整理
  • 暗号そのものに関する用語
    • アルゴリズムを一意に特定するために:暗号
    • アルゴリズムを一意に特定するために:ハッシュ
    • アルゴリズムを一意に特定するために:組み合わせ
    • 別名と英語名
  • 暗号利用モードと暗号/署名スキーム
    • 共通鍵暗号:暗号利用モード
    • 公開鍵暗号:暗号/署名スキーム
  • データフォーマットに関する用語
    • バイナリデータ
    • 構造のあるデータ
  • おわりに
    • 参考文献と参考ウェブサイト

暗号そのものに関する用語

まず、暗号に関するキーワードの大枠を次の図に示します。

image-20201112153759942

鍵を使用しない「鍵無し」、暗号化と復号に同じ鍵を使う「共通鍵」、暗号化と復号で異なる鍵を使う「公開鍵」の3つに分類しています。

アルゴリズムを一意に特定するために:暗号

ブロック暗号(AESなど)や公開鍵暗号(RSAなど)のような暗号プリミティブ(基本的な暗号部品のこと)を単独で使うことはまずありません。それぞれ暗号利用モード(CBCなど)や暗号スキーム(RSAES-OAEPなど)、署名スキーム(RSASSA-PSSなど)と一緒に使います。

また、多くの暗号は複数の鍵長に対応しています。例えばAESなら128bit, 192bit, 256bitから選択できます。

そのため、使うアルゴリズムを一意に特定するためには暗号プリミティブだけでなく鍵長と、モード/スキームをすべて指定します。

image-20201112155110080

語順や区切り文字に明確な決まりはありませんが、慣例的には、暗号プリミティブを最初に書き、ハイフンで区切って、鍵長をビット単位で記載することが多いようです。

アルゴリズムを一意に特定するために:ハッシュ

なお、ハッシュ関数は鍵を必要としませんが、方式や出力ビット長のバリエーションを持つものがあります。例えばSHA-1は1通りなので単にSHA-1と書きますが、SHA-2は6通りから選択可能ですのでSHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256などと表記することで特定します。

image-20201112174927663

image-20201112174936607

アルゴリズムを一意に特定するために:組み合わせ

また、MACや署名はハッシュを必要とする場合がありますので、使用するハッシュ関数も併記する必要があります。こちらは、基本的に後ろにハッシュ関数名を書くだけです。

image-20201112180138483

image-20201112180216048

暗号スキームや署名スキームは名称内にハイフンやアンダースコアを使うものがあるため、ハイフンやアンダースコアで接続するのを避けます。上記例ではスペースを使いました。

別名と英語名

次の表に、各用語の別名と英語名、および具体例を書き出しています。知っているキーワードがどれに当てはまるか分かれば、イメージを持ちやすくなるのではないでしょうか。

名称/別名 English
鍵無し unkeyed
共通鍵/対称鍵 common-key/shared-key/symmetric-key
公開鍵/非対称鍵 public-key/asymmetric-key
名称/別名 English
ハッシュ関数 hash function MD2, MD4, MD5, SHA-1, SHA-2(SHA-224, SHA-256, SHA-384, SHA-512), SHA-3, WHIRLPOOL
ブロック暗号 block cipher DES, 3DES, IDEA, AES, Blowfish, Twofish, MISTY1, RC2, RC5
ストリーム暗号 stream cipher RC4, ChaCha, MUGI
メッセージ認証コード/MAC Message Authentication Code/MAC HMAC, CMAC, CBC-MAC
鍵共有(共通鍵) key agreement AKEP2, shamir’s no-key protocol, Kerberos
公開鍵暗号 public-key cryptography RSA, ECC
鍵共有(公開鍵) key agreement DH, DHE, ECDH, ECDHE
名称/別名 English
暗号利用モード modes of operation ECB, CBC, CTR, CCM, GCM, OFB, CFB
暗号化スキーム encryption scheme RSAES-PKCS1-v1_5, RSAES-OAEP
署名スキーム signature scheme RSASSA-PKCS1-v1_5, RSASSA-PSS, DSA, ECDSA

なお、例の中には明らかに非推奨なもの(MD2など)も混じっていますので注意して下さい。推奨暗号アルゴリズムについては権威のある団体が公開しメンテナンスされているもの(CRYPTRECなど)を参照すると良いでしょう。

暗号利用モードと暗号/署名スキーム

暗号を実際に使おうとすると、暗号利用モード、暗号スキーム、署名スキームに関する単語が追加で登場します。軽く検索してもこの辺の仕組みや特徴に関する日本語の解説はあまり見つかりませんので、簡単に説明しておきます。

共通鍵暗号:暗号利用モード

共通鍵暗号の中でもブロック暗号は、その性質上、固定長のデータしか取り扱えません。例えばAES-128なら128bit(16Byte)固定です。16Byteの鍵と16Byteの平文(暗号化されていないデータのこと)を入力して、16Byteの暗号文を出力します。

ちなみに鍵長とブロック長(一度に処理できる平文の単位)は必ずしも一致しません。これは暗号アルゴリズムに依存しますが、例えばAESの場合、鍵長が128bitでも192bitでも256bitでも、ブロック長は128bitです。

image-20201116123156382

固定長の不自由さを解決するために登場するのが暗号利用モードとパディングです。入力データを処理単位の長さで分割し暗号処理に入力する方法のことを暗号利用モード、端数を適当なデータで埋めて揃えることをパディングと呼びます。埋めるデータ自体のことはパディングデータ(あるいはパディングストリング)と呼びますが、省略して単にパディングとだけ呼ばれることもあります。

76ByteのデータをAES-128で暗号化する場合を例に取って、図にしました。5つのブロックに分けて処理され、最終ブロックを16Byte単位にするため、4Byteのパディングを付けています。

image-20201116125502149

分割やパディングの方法は、暗号化する側と復号する側で合わせておかないとデータが正しく元に戻りません。名前を決めて事前に取り交わしておく必要があります。

なお、暗号利用モードもパディングも方法によっては脆弱性を作り込むことがあります。代表的なところではECBモードですね。上の図のように単純な分割と結合を行いますが、この方法だと16Byte単位で同じ平文は同じ暗号文になってしまいます。平文の値そのものは分からなくても、同じデータが繰り返し入力されていることがわかってしまうのです。この危険性についてはWikipediaの「暗号利用モード」の記事にあるペンギンの絵が分かりやすいのでおすすめです。

さて、ECBモードは危険ですので、当然世の中では他のモードが使われています。下の図に代表的なモードの一つであるCBCモードを図示します。(図が煩雑になるので鍵の入力は省略しています。また、入出力データ長はすべて16Byteです)

image-20210107105145392

これは前のブロックの暗号文を次の平文とXORしてから暗号化する、という方法です。前の暗号文とのXORがあることで入力が撹拌されるため、平文1と平文2が同じでも、暗号文1と暗号文2は違う値になってくれます。ただし、先頭のブロックには「前の」ブロックがありません。そこで登場するのがIV(Initialization Vector。初期化ベクトルとも呼ぶ)です。IVが予測されると暗号解読のヒントになり得るため、IVには使い捨ての乱数を用います。

IVは復号する際にも使いますので、受け渡しする際は暗号文と一緒に渡します。IVは(固定されたり予測されるのは困りますが)見られても困りません(暗号解読にはつながらないとされています。上図の右側をご覧ください。例えば攻撃者がIVと暗号文1を入手しても、鍵が分からないのでAES-128復号の出力は得られません。つまり平文1を得るために必要なXOR計算の入力が足りません)ので、平文のまま送って構いません。

暗号利用モードに関連する用語を整理します。

名称/別名 
English
意味 取り扱い
暗号利用モード
modes of operation
ブロック暗号でのデータの取り扱い方法 生成する側と受け取る側で、使うモードを事前に合わせておく ECB, CBC, CTR, CCM, GCM, OFB, CFB
パディング 
Padding
データがブロック長に足りない場合にデータを埋める方法 生成する側と受け取る側で、使うモードを事前に合わせておく PKCS#5, PKCS#7, ISO10126
パディングストリング/パディングデータ/PS 
Padding String/Padding Data
パディングで埋め込まれるデータ 暗号処理の際に生成し、暗号文に埋め込まれて渡される
初期化ベクトル/IV Initialization Vector ブロック暗号の暗号利用モードで最初のブロックに適用する値 暗号処理の際に生成し、平文のまま渡す

ちなみにパディング方法の例はブロック暗号に対して単独で用いられるものに限って記載しています。可変長を扱う前提の規格(署名スキーム、ハッシュ関数、SSL/TLS通信など)は、規格の中に独自のパディング仕様を抱え込んでいることがあるため、パディングの方法は例に挙げたもの以外にもたくさんあると考えて下さい。

ちなみに、ライブラリなどによってはNoPaddingというパディング方法が出てくる場合があります。これは入力がブロック長のN倍である前提でパディングを行わないという設定です。不適切な長さの入力に対してはエラーを返すライブラリがほとんどだと思いますが、エラーを返さなかったり、エラーハンドリングを失敗すると正しい処理結果が得られない(ことに気付かないまま処理を続けてしまう)可能性もありますので、使用する際は異常系の動作確認も行いましょう。

公開鍵暗号:暗号/署名スキーム

この章の内容は少々込み入っていますので、興味の無い方は読み飛ばしても良いかもしれません。章の最後に新しく登場するキーワードの一覧表がありますので、先に気になる単語が無いかチェックしてから飛ばすかどうか決めるのも良いでしょう。

さて、公開鍵暗号についても、ブロック暗号と同様、固定長のデータしか取り扱えません。例えばRSA-2048なら2048bit(256Byte)固定です。RSAの場合は鍵長と一度に扱えるデータの長さは一致しており、RSA-3072なら鍵長もデータ長も3072bit, RSA-4096なら鍵長もデータ長も4096bitになります。

本記事の最初の図に記載がありますが、公開鍵暗号で使うのはデータの暗号化/復号で使う「暗号スキーム」と、署名/検証で使う「署名スキーム」の2つです。

image-20201221101640698

公開鍵暗号を使った暗号化については、ブロック暗号とは違いデータ長の問題を解決せずに運用します。暗号化出来るサイズ内に限って使う、という割り切りがなされているとも言えます。一般に公開鍵暗号は共通鍵暗号よりも処理が重い(計算量が大きい)ため、大きなサイズのデータの暗号化は共通鍵暗号に任せましょう、という考え方です。公開鍵暗号の性質が欲しい場面(データを暗号化する人と復号する人が違う場合など)ではハイブリッド暗号などを利用します。

共通鍵暗号の暗号利用モードの主要な責務はデータ分割でした。じゃあ分割が必要ない公開鍵暗号の暗号スキームは空っぽな(何の処理もしない)のか、と言えばそうではありません。長さが足りない場合のパディング処理や、データの特徴を隠すためのマスク処理などを持っています(ので実際に暗号化できるメッセージの長さは鍵長より少し短くなるのが一般的です。具体的にはそれぞれのスキームによります)。パディングについては暗号利用モードの章で説明しました。マスク処理については次の署名スキームの方でまとめて説明します。

公開鍵暗号での署名については、ハッシュ関数を併用することで可変長のデータを取り扱えるようにします。署名はデータの改ざん有無をチェックするだけのものですので、暗号化と違って元の値に戻せなくても構いません。ハッシュ関数を使えば元のメッセージの特徴を持ちつつ、メッセージを固定長に変換することができます。RSASSA-PSSを例にとって具体的に見てみましょう。

image-20201116182919560

一見シンプルなインターフェイスですね。可変長のメッセージ(署名で保護すべき対象)と鍵を入力にして、固定長(RSA-2048だから256Byte)の出力が得られます。

しかし、暗号ライブラリによってはメッセージと鍵に加えて、SaltやHash関数を入力として指定するようになっています。これらはどのように決めればいいのでしょうか?また、どのように取り扱うべきでしょうか?

規格(RSASSA-PSSはRSA社によるPKCS1という文書に定義されています)を見てみましょう。

image-20201116183835723

RSASSA-PSSという方式はEMSA-PSSというエンコーディングとRSA-2048の組み合わせによって構成されており、EMSA-PSSにはSalt長、Hash関数、MGFという3つのパラメータを指定する必要がある、と分かります。これらのパラメータはどのように使われているのでしょうか?

さらに、EMSA-PSSの中身を覗いてみましょう。

image-20201116184502724

複雑な図になりましたが、ここまで掘り下げることで、ようやくポイントを理解することができます。

メッセージはHash関数を通ることで可変長から固定長の情報に不可逆圧縮されています。Hashを2回通っていることや、MGFとのXORは元データの特徴を隠す(ことで暗号解読を困難にする)ための工夫と考えられます。Salt(乱数)には、同じ入力(メッセージ)に対する処理でも実行のたびに出力(署名)を変える(ことで暗号解析を困難にする)目的があります。

使われている用語を書き出しておきましょう。

  • メッセージ:署名対象の(改ざんを防止したい)データ
  • Hash:ハッシュ関数。何を使うか指定する必要がある
  • Hash値:ハッシュ関数の出力。固定長になる
  • PS:Padding String。RSASSA-PSSでは可変長の0x00
  • Salt:署名値を撹拌するための値。乱数を用いる
  • 0x01:1Byte固定値
  • 0xbc:1Byte固定値
  • MGF:Mask Generation Functionの略
  • XOR値:XORの出力
  • 鍵:RSA-2048の鍵
  • 署名:メッセージに対するRSA-2048署名

外部入力になっているMGF、Salt、Hashについて、パラメータを指定できる程度に補足しておきます。

MGFについては、規格内のAppendixにあるMGF1が使われることが多く、パラメータ指定で悩むことはほとんどありません。内部ではハッシュ関数が使われていて、情報をマスクするのに適当な値を生み出します。

Saltについては、規格通り(lengthだけ指定してRSASSA-PSS内で乱数を振る)の実装のこともあれば、外部からSalt値を直接指定するインターフェイスのライブラリもあるようです。どの長さが良い(安全)かについては議論がありますが、規格ではハッシュ関数の出力と同じ長さ、あるいは0(使わない)を推奨しています。外部から値を直接指定する場合は乱数の品質(再使用しない、予測困難で、偏りが十分小さい、など)を確保するのを忘れないようにしましょう。

Hashについては、使うハッシュ関数を指定します。ここで、ハッシュ関数の制約や脆弱性(があるなら)を取り込んでしまうことに注意して下さい。意識したことが無い方が多いかもしれませんが、ハッシュ関数の多くは入力データ長に制限があります(SHA-1なら264-1bit)。RSASSA-PSSのメッセージ入力はoctet単位なのでSHA-1なら261-1octetが上限になります。ハッシュ関数の脆弱性は度々見つかっています。署名アルゴリズムの主要な構成要素ですので、脆弱性のあるハッシュ関数は使うべきではありません。

注意しておく点は、これらのパラメータは署名を生成する側と検証する側で揃えておく必要がある(でないと正しい署名を正しい鍵で検証しても結果が合わない)ということです。

署名スキームに関連する用語を整理します。

名称/別名 English 意味 取り扱い
暗号化スキーム encryption scheme 公開鍵暗号を暗号復号に使う場合のデータ取り扱い方法 生成する側と受け取る側で、使うスキームを事前に合わせておく RSAES-PKCS1-v1_5, RSAES-OAEP
署名スキーム signature scheme 公開鍵暗号を署名検証に使う場合のデータ取り扱い方法 生成する側と受け取る側で、使うスキームを事前に合わせておく RSASSA-PKCS1-v1_5, RSASSA-PSS, DSA, ECDSA
MGF Mask Generation Function データの特徴を隠すためのマスクを作る関数 生成する側と受け取る側で、使うMGFを事前に合わせておく MGF1
Salt 
Salt
処理の出力を攪拌するための乱数 暗号処理の際に生成し、処理中に消費される
Salt長 
Salt length
Saltの長さ 生成する側と受け取る側で、使う長さを事前に合わせておく
ハッシュ関数 hash function 可変長の入力から固定長の値を生成する関数 生成する側と受け取る側で、使う関数を事前に合わせておく MD2, MD4, MD5, SHA-1, SHA-2(SHA-224, SHA-256, SHA-384, SHA-512), SHA-3, WHIRLPOOL

Salt長は事前に取り交わしておく必要がありますが、Salt値自体は別に送らなくても良いことに注意して下さい。

データフォーマットに関する用語

バイナリデータ

暗号の仕様から見ますと、データの入出力の多くはbit stringかoctet stringで表現されます。つまり構造が無く、データパターンの組み合わせに制限がありません。

jpegファイルをJPEG parser処理が扱う場合と、AES-128暗号化の処理が扱う場合のイメージを次の図に示します。

image-20201221111133818

jpeg parserがファイル内の構造を読み取りマーカーやテーブルを解釈するのに対し、暗号処理は対象データをそのまま(ファイルの構造は解釈せずにバイナリデータとして)扱います。そのため、平文については特定のデータフォーマットを定義する必要がありません。テキストならtxt, jpegならjpg, データベースならdbなど、システムがデータを扱いたい形式のままで保持しておけば良いでしょう。

暗号文、署名、共通鍵暗号の鍵もひと固まりのバイナリデータで構造がありませんので、こちらも特定のデータフォーマットは必要ありません。環境によって.binや.datなどのバイナリデータを表す拡張子を付けたり、暗号文を表す.enc、署名を表す.sig、鍵を表す.keyなどを付けることがあります。ただし、処理系の違い(主にエンディアンの違い)には注意が必要です。

構造のあるデータ

暗号に関するデータで構造が出てくるのは、公開鍵暗号の鍵やPKI(Public Key Infrastructure。公開鍵認証基盤などと訳されます。公開鍵を運用するための仕組みとして、証明書フォーマットや管理組織などで構成される公開鍵の所有者を確認するための枠組み)関連です。

公開鍵暗号の鍵については、複数のパラメータで表現されるものが多いため、鍵ファイルは構造を持つことになります。フォーマットの規格は幾つかありますが、RSAの鍵であればPKCS#1やPKCS#12が有名です。前者は保護無しの形式、後者はパスワード保護ありの形式です。

証明書はパブリックキー格納方法の一つ、と見ることもできますが、関連する要素技術が多いことからPKI関連として次にまとめて述べます。

PKI関連のデータはインターネットでやり取りする前提ですので、フォーマットは規格で定められていますし、広く公開されています。証明書(certificate)、証明書失効リスト(CRL)、証明書署名要求(CSR)といったデータがよく登場します。ただしこれらはバイナリデータとして扱う場合と、Base64エンコードデータとして扱う場合がある上、拡張子が色々あってややこしいです。関係を図にしましたのでご覧ください。

image-20201130163626272

同じ内容(例:証明書)でも、拡張子が違うことがあります(CRTだったりCERだったりPEMだったりDERだったりする)。逆に拡張子(例:PEM)では内容を特定できないことがあります(証明書かもしれないし、失効リストかもしれないし、署名要求かもしれない)。分からない場合はファイルを開いて中身を見て確認しなければなりません。

なお、どのエンコード/拡張子を読めるかは環境依存ですので、どれを採用するかは使うライブラリ等の仕様を確認して決めます。変換が必要になる場合もあるため注意しましょう。

ここまでに出てきたデータフォーマット関連の用語を次の表にまとめました。

データ フォーマット仕様の例 拡張子の例 補足
平文 暗号処理への入出力はバイナリ
暗号文 enc, dat 暗号処理への入出力はバイナリ。
エンディアンに注意
署名 sig, dat 暗号処理への入出力はバイナリ。
エンディアンに注意
共通鍵暗号の鍵 key, dat 暗号処理への入力はバイナリ。
エンディアンに注意
公開鍵暗号の鍵 PKCS#1(RFC8017), PKCS#12(RFC7292) key, p12 パブリックキーだけの場合と
パブリックキーとプライベートキーの両方を含む場合がある
証明書 X.509(RFC5280) crt, cer, pem, der X.509は証明書と
証明書失効リストの両方を含む規格
証明書失効リスト X.509(RFC5280) crl, pem, der X.509は証明書と
証明書失効リストの両方を含む規格
証明書署名要求 PKCS#10(RFC2980) csr, pem

おわりに

とっつきにくい暗号関連の用語に馴染んでもらう一助になればと思って書き上げました。

この手の記事は生ものなのでいずれ陳腐化するかもしれませんが(10年くらいしたらここに書いた公開鍵関係のキーワードの大半が一掃されて、耐量子暗号の独壇場になってるかも?)、暗号に関する用語のインデックスとしてご活用頂ければ幸いです。

参考文献と参考ウェブサイト