Microsoft SDL の暗号化に関する推奨事項
Microsoft が独自の製品およびサービスに求めるものと同じ API、アルゴリズム、プロトコル、およびキーの長さを使用するように製品を設計する際に参照としてこの情報を使用します。 内容の多くは、セキュリティ開発ライフサイクルの作成に使用される Microsoft 独自の内部セキュリティ標準に基づいています。
Windows 以外のプラットフォームの開発者にも、これらの推奨事項が役立つ可能性があります。 API とライブラリの名前は異なる場合がありますが、アルゴリズムの選択、キーの長さ、データ保護に関するベスト プラクティスは、プラットフォーム間で類似しています。
セキュリティ プロトコル、アルゴリズム、およびキーの長さに関する推奨事項
TLS/SSL バージョン
製品とサービスでは、暗号として安全な TLS/SSL のバージョンを使用する必要があります。
- TLS 1.3 を有効にする必要があります。
- 以前のクライアントとの互換性を向上させるために、TLS 1.2 を有効にすることができます。
- TLS 1.1、TLS 1.0、SSL 3、SSL 2 を無効にする必要があります
対称ブロック暗号、暗号モード、および初期化ベクトル
ブロック暗号
対称ブロック暗号を使用する製品では、次の点に注意してください。
- Advanced Encryption Standard (AES) が推奨されます。
- 3DES (トリプル DES/TDEA)、RC4 などのその他のブロック暗号を暗号化に使用する場合は、すべて置き換える必要があります。
対称ブロック暗号化アルゴリズムでは、128 ビットの最小キー長が必須となりますが、256 ビット キーをサポートすることを推奨します。 新しいコードに推奨される唯一のブロック暗号化アルゴリズムは AES です (AES-128、AES-192、および AES-256 はすべて許容されますが、AES-192 では一部のプロセッサで最適化されないことに注意してください)。
暗号モード
対称アルゴリズムはさまざまなモードで動作でき、そのほとんどは、プレーンテキストと暗号化テキストの後続のブロックに対する暗号化操作とリンクします。
対称ブロック暗号は、次のいずれかの暗号モードで使用する必要があります。
- 暗号ブロック チェーン (CBC)
- Cipherテキスト盗用 (CTS)
- Cipher Text Stealingを使用した XEX ベースの Tweaked-Codebook (XTS)
次に示すような他のいくつかの暗号モードには実装上の落とし穴があるため、誤って使用される可能性が高くなります。 特に、電子コード ブック (ECB) 動作モードは避ける必要があります。 CTR などの "ストリーム暗号モード" のブロック暗号で同じ初期化ベクトル (IV) を再利用すると、暗号化されたデータが漏洩する可能性があります。 以下のいずれかのモードを使用する場合は、追加のセキュリティ レビューをお勧めします。
- 出力フィードバック (OFB)
- 暗号フィードバック (CFB)
- Counter (CTR)
- 上記の "推奨される" リストにないその他のもの
初期化ベクトル (IV)
すべての対称ブロック暗号では、暗号強度の高い乱数を初期化ベクトルとして使用する必要もあります。 初期化ベクトルを定数値または予測可能な値にすることはできません。 暗号強度の高い乱数を生成する方法については、「乱数ジェネレーター」を参照してください。
初期化ベクトルは、複数の暗号化処理を実行する場合に再利用してはいけません。 再利用は、特に出力フィードバック (OFB) やカウンター (CTR) のようなストリーミング暗号モードを使用する場合、暗号化されているデータに関する情報が明らかになる可能性があります。
AES-GCM と AES-CCM の推奨事項
AES-GCM (Galois/Counter Mode) と AES-CCM (Counter with CBC-MAC) は、広く使用されている認証済み暗号化モードです。 このモードは機密性と整合性の保護を兼ね備えているため、セキュリティで保護された通信に役立ちます。 ただし、その脆弱性は nonce の再利用によるものです。 同じ nonce (初期化ベクトル) が 2 度使用されると、致命的な結果につながる可能性があります。
「NIST SP 800-38D や操作のブロック暗号化モードに関する推奨事項: Galois/Counter Mode (GCM) と GMAC」に記載されている nonce ガイドラインに従うことをお勧めします。ここでは、最大呼び出し回数に関するセクション 8.3 に特に注目しています。
もう 1 つのオプションは、暗号化されるメッセージごとに一意の AES-GCM/CCM キーを生成し、最大呼び出し回数を効果的に 1 に制限することです。 カウンターを使用したり、付与されたキーの最大呼び出し回数を追跡できるようにしたりすることが実用的でない場合に保存データを暗号化する場合には、この方法をお勧めします。
保存データを暗号化する場合、Encrypt-then-MAC スキームを使用する代わりに、メッセージ認証コード (MAC) を含む AES-CBC を使用することもできます。この場合は、暗号化および MAC 用に別のキーを使用してください。
整合性の検証
暗号化では、既定で機密性と整合性の両方が保証されるというのは、よく見られる誤解です。 多くの暗号化アルゴリズムは整合性チェックを提供しておらず、改ざん攻撃に対して脆弱である可能性があります。 送信前と受信後のデータの整合性を保証するために、追加の手順を進める必要があります。
AES-GCM などの関連データ付き認証暗号化アルゴリズム (AEAD) を使用できない場合、Encrypt-then-MAC スキームを使用してメッセージ認証コード (MAC) で整合性を検証する方法があります。この場合は、暗号化および MAC 用に別のキーを使用してください。
暗号化と MAC に個別のキーを使用することが非常に重要です。 2 つのキーを格納できない場合、暗号化の目的の 1 つであり MAC の 1 つでもある適切なキー派生関数 (KDF) を使用して、メイン キーから 2 つのキーを派生させる方法が有効です。 詳細については、「SP 800-108 Rev. 1: 擬似乱数関数を使用したキーの派生に関する推奨事項 | CSRC (nist.gov)」を参照してください。
非対称アルゴリズム、キーの長さ、パディング モード
RSA
- RSA は、暗号化、キー交換、署名に使用できます。
- RSA 暗号化では、OAEPまたはRSA-PSSのパディング モードを使用する必要があります。
- 既存のコードでは、互換性の確保のみを目的として、PKCS #1 v1.5 パディング モードを使用できます。
- null パディングは使用しないことをお勧めします。
- 少なくとも 2048 ビットのキーの長さが推奨されますが、3072 ビットのキーの長さをサポートすることをお勧めします。
ECDSA と ECDH
- ECDH ベースのキー交換と ECDSA ベースの署名では、NIST が承認した 3 つの曲線 (P-256、P-384、P521) のいずれかを使用する必要があります。
- P-256 のサポートは最小限とみなす必要がありますが、P-384 のサポートをお勧めします。
"整数の Diffie-Hellman"
- キーの長さ >= 2048 ビットが recommended0
- グループ パラメーターは、既知の名前付きグループ (RFC 7919 など) であるか、信頼された相手によって生成され使用前に認証されている必要があります。
キーの有効期間
- すべてのキーに対して cryptoperiod を定義します。
- 例: データ暗号化用の共通キーは、多くの場合データ暗号化キーまたは DEK と呼ばれ、データを暗号化するために最大 2 年の使用期間 (発信者使用期間) がある場合があります。 暗号化解除のための有効な使用期間 (受信者使用期間) がさらに 3 年間あると定義する場合もあります。
- 有効期間が制限されるようにするには、キーを置き換えるためのメカニズムを提供するかプロセスを用意する必要があります。 有効期間が終了した後は、新しいデータを生成する (たとえば暗号化や署名を行う) ためにキーを使用することはできませんが、データの読み取り (暗号化解除や検証など) のために使用することはできます。
乱数ジェネレーター
ランダム性が必要な場合は、すべての製品とサービスで暗号として安全な乱数ジェネレーターを使用する必要があります。
CNG
- BCRYPT_USE_SYSTEM_PREFERRED_RNG フラグを含む BCryptGenRandom を使用します。
Win32/64
- レガシ コードでは、カーネル モードで RtlGenRandom を使用できます。
- 新しいコードでは、BCryptGenRandom または CryptGenRandom を使用する必要があります。
- C 関数 Rand_s() も推奨されます (Windows では CryptGenRandom を呼び出します)。
- Rand_s() は、Rand()の安全でパフォーマンスの高い Rand()の代替手段です。
- Rand() を暗号化アプリケーションに使用することはできません。
.NET
- RandomNumberGenerator を使用します。
PowerShell
- Get-SecureRandom (PowerShell) を使用します。
Windows ストア アプリ
- Windows Store アプリでは、CryptographicBuffer.GenerateRandom または CryptographicBuffer.GenerateRandomNumber を使用できます。
Linux/macOS
/dev/urandom
デバイスには、getrandom(2)
システム呼び出しと同様に、暗号的に強力なランダム データのソースが用意されています。
非推奨
- 乱数生成に関する安全でない関数: rand、System.Random (.NET)、GetTickCount、GetTickCount64、Get-Random (PowerShell cmdlet) など。
- 双対楕円曲線乱数ジェネレーター (DUAL_EC_DRBG) アルゴリズムの使用は許可されていません。
Windows プラットフォームでサポートされている暗号化ライブラリ
Windows プラットフォームでは、オペレーティング システムに組み込まれている暗号化 APIを使用することをお勧めします。 他のプラットフォームでは、開発者はプラットフォーム以外の暗号化ライブラリの使用を評価することを選択できます。 一般に、プラットフォーム暗号化ライブラリは、アプリケーションにバンドルされるのではなく、オペレーティング システムの一部として付属しているため、より頻繁に更新されます。
プラットフォームとプラットフォーム以外の暗号化に関する使用上のすべての決定は、次の要件に従って行われる必要があります。
- ライブラリは、セキュリティ上の既知の脆弱性がない現在サポートされているバージョンである必要があります。
- 最新のセキュリティ プロトコル、アルゴリズム、およびキーの長さをサポートする必要があります。
- (オプション) ライブラリは旧バージョンとの互換性を保つ目的に限り、古いセキュリティ プロトコルまたはアルゴリズムをサポートできる必要があります。
[ネイティブ コード]
- 暗号化プリミティブ: ご使用のリリースが Windows である場合、可能であれば CNG を使用します。
- コード署名の検証: WinVerifyTrust は、Windows プラットフォームでコード署名を検証するためにサポートされている API です。
- 証明書の検証 (コード署名または SSL、TLS、DTLS の制限付き証明書の検証で使用されたもの): CAPI2 API。たとえば、CertGetCertificateChain および CertVerifyCertificateChainPolicy。
マネージド コード (.NET)
- 暗号化プリミティブ: System.Security.Cryptography 名前空間で定義されている API を使用します。
- 最新バージョンの .NET が利用可能です。
キー派生関数
キーの派生は、共有シークレットまたは既存の暗号化キーから暗号化キー マテリアルを派生させるプロセスです。 製品では、推奨されるキー派生関数を使用する必要があります。 ユーザーが選択したパスワード、または認証システムでの保管のためのハッシュ パスワードからのキーの派生は、このガイダンスで説明されていない特殊なケースです。開発者は専門家に相談する必要があります。
次の標準では、使用が推奨される KDF 関数が指定されています。
- NIST SP 800-108 (Revision 1): 擬似乱数関数を使用したキーの派生に関する推奨事項。 特に、HMACを疑似乱数関数として持つカウンター モードの KDF
- NIST SP 800-56A (Revision 3): 離散対数暗号を使用したペアワイズ キー確立スキームの推奨事項。
既存のキーからキーを派生させるには、次のいずれかのアルゴリズムを使用して、BCryptKeyDerivation APIを使用します。
- BCRYPT_SP800108_CTR_HMAC_ALGORITHM
- BCRYPT_SP80056A_CONCAT_ALGORITHM
共有シークレット (キーの承諾の出力) からキーを派生させるには、次のいずれかのアルゴリズムを使用して BCryptDeriveKey API を使用します。
- BCRYPT_KDF_SP80056A_CONCAT
- BCRYPT_KDF_HMAC
証明書の検証
TLS または DTLS を使用する製品は、接続先エンティティの X.509 証明書を完全に検証する必要があります。 このプロセスには、証明書の次の部分の検証が含まれます。
- ドメイン名
- 有効期間 (開始日と有効期限)。
- 失効状態。
- 使用状況 ("サーバー認証" (サーバーの場合)、"クライアント認証" (クライアントの場合) など)。
- 信頼チェーン。 プラットフォームによって信頼されている、または管理者によって明示的に構成されているルート証明機関 (CA) に、証明書がチェーンされている必要があります。
これらの検証テストのいずれかが失敗した場合、製品はエンティティとの接続を終了する必要があります。
"自己署名" 証明書は使用しないでください。 自己署名では本質的に、信頼の伝達、失効のサポート、およびキーの更新のサポートは行われません。
暗号化ハッシュ関数
製品では、SHA-2 ファミリのハッシュ アルゴリズム (SHA-256、SHA-384、SHA-512) を使用する必要があります。 セキュリティ上の目的で暗号化ハッシュを切り捨てる場合、128 ビット未満に切り捨てることは許可されていません。 SHA-256 の使用は最小限ですが、SHA-384 をサポートすることをお勧めします。
MAC、HMAC、キー付きハッシュ アルゴリズム
メッセージ認証コード (MAC) はメッセージに添付される情報の一部です。MAC により、メッセージの受信者は、秘密キーを使用して送信元の信頼性とメッセージの整合性を確認することが可能になります。
基になるすべてのハッシュ アルゴリズムまたは対称暗号化アルゴリズムも使用が推奨されていれば、ハッシュ ベースの MAC (HMAC) またはブロック暗号ベースの MAC の使用が推奨されます。現時点では、これには HMAC-SHA2 関数 (HMAC-SHA256、HMAC-SHA384、HMAC-SHA512) が含まれます。 HMAC-SHA256 の使用は最小限ですが、HMAC-SHA384 をサポートすることをお勧めします。
HMAC を 128 ビット未満に切り捨てることは推奨されていません。
設計および運用面の考慮事項
- 必要に応じて暗号化キーを交換するメカニズムを提供する必要があります。 キーは、アクティブな有効期間が終了するか、暗号化キーが侵害されたときに交換する必要があります。
- 証明書を更新するときは、常に新しいキーを使用して証明書を更新する必要があります。
- 暗号化アルゴリズムを使用してデータを保護する製品には、将来のさまざまなアルゴリズムへの移行をサポートするために、そのコンテンツと共に十分なメタデータを含める必要があります。 このメタデータには使用されるアルゴリズム、キーのサイズ、パディング モードなどがあります。
- 暗号化方式の指定の詳細については、暗号化の機敏性に関する記事を参照してください。
- 可能な場合は、署名形式 (例: 標準形式や既存の形式の使用) など、製品ではプロトコルを再実装するのではなく、確立された、プラットフォームで提供される暗号化プロトコルを使用する必要があります。
- 暗号化操作の失敗をエンドユーザーに報告しないでください。 リモートの呼び出し元 (Web クライアントや、クライアントとサーバーのシナリオでのクライアントなど) にエラーを返す場合は、一般的なエラー メッセージのみを使用してください。
- 範囲外または無効な長さのエラーを直接報告するなど、不要な情報を提供することは避けてください。 詳細ログが有効になっている場合に限り、サーバー側でのみ詳細エラーをログに記録します。
- 次の項目を含む設計については、追加のセキュリティ レビューを強くお勧めします。
- セキュリティに重点を置いた新しいプロトコル (認証または認可プロトコルなど)
- 新規あるいは標準外の方法の暗号化を使用する新しいプロトコル。 考慮事項の例を次に示します。
- 当該プロトコルを実装する製品は、プロトコル実装の一部として任意の暗号化の API またはメソッドを呼び出しますか。
- 当該プロトコルは、認証または認可に使用される他のプロトコルに依存していますか。
- 当該プロトコルは、キーなどの暗号化要素の保管形式を定義しますか。
- 自己署名証明書は推奨されていません。 未加工の暗号化キーを使用するなど、自己署名証明書を使用しても、信頼の決定を行うための根拠がユーザーや管理者に本質的に提供されません。
- これに対して、信頼された証明機関をルートとする証明書を使用すると、関連付けられている秘密キーに依存する根拠が明確になり、セキュリティ障害が発生した場合に失効と更新を行うことができます。