cryptography について
cryptographyは、暗号化、パスワードハッシュ、TLS、鍵管理、耐量子計算機の考慮事項を扱う開発者向け実装ガイドです。アルゴリズム選択の指針、例、セキュリティチェックリストを提供します。
主な機能
- 01共通鍵・公開鍵暗号の指針
- 02パスワードハッシュとコスト設定の指針
- 03TLSバージョンと設定の推奨事項
- 04鍵管理とローテーションの指針
- 05安全な乱数と耐量子計算機の考慮事項
- 06暗号実装のセキュリティチェックリスト
活用シーン
- 01保存データの暗号方式の選定
- 02パスワード保存と検証の実装
- 03TLS設定と鍵管理のレビュー
- 04耐量子計算機への備えの評価
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ melodic-software/ claude-code-plugins --skill cryptographyインストール後、Claude Code で/cryptographyを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/algorithm-selection.mdpassword-hashing.mdtls-configuration.md詳細
暗号技術
暗号化アルゴリズム、パスワードハッシュ、TLS、鍵管理を網羅した、安全な暗号処理の実装に関する包括的なガイダンスです。
このスキルを使用する場面
次の場合に、このスキルを使用してください。
- 暗号化アルゴリズムを選択するとき
- パスワードハッシュを実装するとき
- TLS/SSL を設定するとき
- 暗号鍵を管理するとき
- デジタル署名を実装するとき
- 乱数を生成するとき
- 暗号実装をレビューするとき
- ポスト量子暗号への対応を検討するとき
アルゴリズムのクイックリファレンス
暗号化アルゴリズム
| アルゴリズム | 種類 | 鍵長 | 用途 | ステータス |
|---|---|---|---|---|
| AES-256-GCM | 共通鍵 | 256 ビット | データ暗号化 | ✅ 推奨 |
| ChaCha20-Poly1305 | 共通鍵 | 256 ビット | データ暗号化(モバイル) | ✅ 推奨 |
| RSA-OAEP | 公開鍵 | 2048 ビット以上 | 鍵交換 | ✅ 推奨 |
| ECDH (P-256) | 公開鍵 | 256 ビット | 鍵共有 | ✅ 推奨 |
| X25519 | 公開鍵 | 256 ビット | 鍵共有 | ✅ 推奨 |
| DES | 共通鍵 | 56 ビット | なし | ❌ 非推奨 |
| 3DES | 共通鍵 | 168 ビット | レガシー用途のみ | ⚠️ 回避してください |
| Blowfish | 共通鍵 | 32~448 ビット | なし | ⚠️ 回避してください |
署名アルゴリズム
| アルゴリズム | 種類 | 鍵長 | 用途 | ステータス |
|---|---|---|---|---|
| Ed25519 | EdDSA | 256 ビット | 署名 | ✅ 推奨 |
| ECDSA (P-256) | ECC | 256 ビット | 署名、JWT | ✅ 推奨 |
| RSA-PSS | RSA | 2048 ビット以上 | 署名 | ✅ 推奨 |
| RSA PKCS#1 v1.5 | RSA | 2048 ビット以上 | レガシー署名 | ⚠️ 代わりに PSS を使用してください |
ハッシュ関数
| アルゴリズム | 出力サイズ | 用途 | ステータス |
|---|---|---|---|
| SHA-256 | 256 ビット | 汎用ハッシュ | ✅ 推奨 |
| SHA-384 | 384 ビット | より高いセキュリティ | ✅ 推奨 |
| SHA-512 | 512 ビット | 最高レベルのセキュリティ | ✅ 推奨 |
| SHA-3-256 | 256 ビット | SHA-2 の代替 | ✅ 推奨 |
| BLAKE2b | 256~512 ビット | 高速なハッシュ | ✅ 推奨 |
| MD5 | 128 ビット | なし(脆弱) | ❌ 絶対に使用しないでください |
| SHA-1 | 160 ビット | なし(脆弱) | ❌ 絶対に使用しないでください |
パスワードハッシュ
パスワードに汎用ハッシュ関数(SHA-256、MD5)を使用しないでください。
アルゴリズムの比較
| アルゴリズム | 推奨度 | メモリハード | 備考 |
|---|---|---|---|
| Argon2id | ✅ 最適 | はい | PHC の優勝アルゴリズム。新しいシステムに推奨 |
| bcrypt | ✅ 良好 | いいえ | 広くサポートされ、実績があります |
| scrypt | ✅ 良好 | はい | 優れていますが、調整が複雑です |
| PBKDF2 | ⚠️ 許容可能 | いいえ | NIST 承認済みですが、GPU による攻撃に脆弱です |
Argon2id(推奨)
using Konscious.Security.Cryptography;
using System.Security.Cryptography;
using System.Text;
/// <summary>
/// Argon2id password hasher with OWASP 2023 recommended parameters.
/// </summary>
public static class Argon2PasswordHasher
{
private const int DegreeOfParallelism = 4;
private const int MemorySize = 65536; // 64 MB
private const int Iterations = 3;
private const int HashLength = 32;
private const int SaltLength = 16;
/// <summary>
/// Hash password with Argon2id.
/// </summary>
public static string Hash(string password)
{
var salt = RandomNumberGenerator.GetBytes(SaltLength);
var hash = ComputeHash(password, salt);
// Return in PHC format: $argon2id$v=19$m=65536,t=3,p=4$salt$hash
return $"$argon2id$v=19$m={MemorySize},t={Iterations},p={DegreeOfParallelism}${Convert.ToBase64String(salt)}${Convert.ToBase64String(hash)}";
}
/// <summary>
/// Verify password against stored hash.
/// </summary>
public static bool Verify(string storedHash, string password)
{
var parts = ParseHash(storedHash);
if (parts is null) return false;
var computedHash = ComputeHash(password, parts.Value.Salt);
return CryptographicOperations.FixedTimeEquals(computedHash, parts.Value.Hash);
}
private static byte[] ComputeHash(string password, byte[] salt)
{
using var argon2 = new Argon2id(Encoding.UTF8.GetBytes(password))
{
Salt = salt,
DegreeOfParallelism = DegreeOfParallelism,
MemorySize = MemorySize,
Iterations = Iterations
};
return argon2.GetBytes(HashLength);
}
private static (byte[] Salt, byte[] Hash)? ParseHash(string storedHash)
{
// Parse PHC format: $argon2id$v=19$m=...,t=...,p=...$salt$hash
var parts = storedHash.Split('$');
if (parts.Length < 6) return null;
var salt = Convert.FromBase64String(parts[4]);
var hash = Convert.FromBase64String(parts[5]);
return (salt, hash);
}
}
// Usage
var hash = Argon2PasswordHasher.Hash("user_password");
// Returns: $argon2id$v=19$m=65536,t=3,p=4$...
if (Argon2PasswordHasher.Verify(hash, "user_password"))
{
// Password valid
}
bcrypt
using BCrypt.Net;
// Hash password (work factor 12 = 2^12 iterations)
var passwordHash = BCrypt.Net.BCrypt.HashPassword("user_password", workFactor: 12);
// Verify password
if (BCrypt.Net.BCrypt.Verify("user_password", passwordHash))
{
Console.WriteLine("Password valid");
}
ワークファクターのガイドライン
| アルゴリズム | 最小 | 推奨 | 高セキュリティ |
|---|---|---|---|
| Argon2id | t=2, m=19MB | t=3, m=64MB | t=4, m=128MB |
| bcrypt | 10 | 12 | 14 |
| scrypt | N=2^14 | N=2^16 | N=2^18 |
| PBKDF2 | 310,000 | 600,000 | 1,000,000 |
パスワードハッシュの詳細なガイダンス: パスワードハッシュのリファレンスを参照してください。
共通鍵暗号
AES-256-GCM(推奨)
using System.Security.Cryptography;
/// <summary>
/// AES-256-GCM encryption utilities.
/// </summary>
public static class AesGcmEncryption
{
private const int NonceSize = 12; // 96 bits
private const int TagSize = 16; // 128 bits
private const int KeySize = 32; // 256 bits
/// <summary>
/// Encrypt data with AES-256-GCM. Returns nonce + ciphertext + tag.
/// </summary>
public static byte[] Encrypt(ReadOnlySpan<byte> plaintext, ReadOnlySpan<byte> key)
{
var nonce = RandomNumberGenerator.GetBytes(NonceSize);
var ciphertext = new byte[plaintext.Length];
var tag = new byte[TagSize];
using var aes = new AesGcm(key, TagSize);
aes.Encrypt(nonce, plaintext, ciphertext, tag);
// Combine: nonce + ciphertext + tag
var result = new byte[NonceSize + ciphertext.Length + TagSize];
nonce.CopyTo(result.AsSpan(0, NonceSize));
ciphertext.CopyTo(result.AsSpan(NonceSize));
tag.CopyTo(result.AsSpan(NonceSize + ciphertext.Length));
return result;
}
/// <summary>
/// Decrypt data with AES-256-GCM. Input is nonce + ciphertext + tag.
/// </summary>
public static byte[] Decrypt(ReadOnlySpan<byte> combined, ReadOnlySpan<byte> key)
{
var nonce = combined[..NonceSize];
var ciphertext = combined[NonceSize..^TagSize];
var tag = combined[^TagSize..];
var plaintext = new byte[ciphertext.Length];
using var aes = new AesGcm(key, TagSize);
aes.Decrypt(nonce, ciphertext, tag, plaintext);
return plaintext;
}
/// <summary>
/// Generate a secure 256-bit key.
/// </summary>
public static byte[] GenerateKey() => RandomNumberGenerator.GetBytes(KeySize);
}
// Usage
var key = AesGcmEncryption.GenerateKey();
var encrypted = AesGcmEncryption.Encrypt("sensitive data"u8, key);
var decrypted = AesGcmEncryption.Decrypt(encrypted, key);
パスワードからの鍵導出
using System.Security.Cryptography;
using System.Text;
/// <summary>
/// Derive encryption key from password using PBKDF2.
/// </summary>
public static class KeyDerivation
{
private const int SaltSize = 16;
private const int KeySize = 32; // 256 bits for AES-256
private const int Iterations = 600000; // OWASP 2023 recommendation
/// <summary>
/// Derive encryption key from password. Returns (key, salt).
/// </summary>
public static (byte[] Key, byte[] Salt) DeriveKey(string password, byte[]? salt = null)
{
salt ??= RandomNumberGenerator.GetBytes(SaltSize);
var key = Rfc2898DeriveBytes.Pbkdf2(
password: Encoding.UTF8.GetBytes(password),
salt: salt,
iterations: Iterations,
hashAlgorithm: HashAlgorithmName.SHA256,
outputLength: KeySize
);
return (key, salt); // Store salt with encrypted data
}
}
公開鍵暗号
RSA 鍵の生成
using System.Security.Cryptography;
/// <summary>
/// RSA encryption with OAEP padding.
/// </summary>
public static class RsaEncryption
{
/// <summary>
/// Generate RSA key pair. Use 2048 minimum; 4096 for long-term security.
/// </summary>
public static RSA GenerateKeyPair(int keySizeInBits = 2048)
{
return RSA.Create(keySizeInBits);
}
/// <summary>
/// Encrypt with public key using OAEP-SHA256.
/// </summary>
public static byte[] Encrypt(byte[] plaintext, RSA publicKey)
{
return publicKey.Encrypt(plaintext, RSAEncryptionPadding.OaepSHA256);
}
/// <summary>
/// Decrypt with private key using OAEP-SHA256.
/// </summary>
public static byte[] Decrypt(byte[] ciphertext, RSA privateKey)
{
return privateKey.Decrypt(ciphertext, RSAEncryptionPadding.OaepSHA256);
}
}
// Usage
using var rsa = RsaEncryption.GenerateKeyPair(4096);
var publicKey = rsa.ExportRSAPublicKey();
var ciphertext = RsaEncryption.Encrypt(plaintext, rsa);
var decrypted = RsaEncryption.Decrypt(ciphertext, rsa);
デジタル署名
using System.Security.Cryptography;
/// <summary>
/// Ed25519 digital signatures (via ECDsa with curve).
/// Note: .NET 10 has native Ed25519 support.
/// </summary>
public static class DigitalSignatures
{
/// <summary>
/// Create ECDSA key pair (P-256, widely supported).
/// </summary>
public static ECDsa CreateEcdsaKeyPair()
{
return ECDsa.Create(ECCurve.NamedCurves.nistP256);
}
/// <summary>
/// Sign message with ECDSA-SHA256.
/// </summary>
public static byte[] Sign(byte[] message, ECDsa privateKey)
{
return privateKey.SignData(message, HashAlgorithmName.SHA256);
}
/// <summary>
/// Verify signature.
/// </summary>
public static bool Verify(byte[] message, byte[] signature, ECDsa publicKey)
{
return publicKey.VerifyData(message, signature, HashAlgorithmName.SHA256);
}
}
// Usage
using var ecdsa = DigitalSignatures.CreateEcdsaKeyPair();
var signature = DigitalSignatures.Sign(message, ecdsa);
if (DigitalSignatures.Verify(message, signature, ecdsa))
{
Console.WriteLine("Signature valid");
}
else
{
Console.WriteLine("Signature invalid");
}
アルゴリズム選択に関する詳細なガイダンス: アルゴリズム選択ガイドを参照してください。
TLS の設定
推奨 TLS 設定
# Nginx TLS configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
# HSTS (HTTP Strict Transport Security)
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
TLS バージョンの要件
| バージョン | ステータス | 備考 |
|---|---|---|
| TLS 1.3 | ✅ 必須 | 最高レベルのセキュリティとパフォーマンスの向上 |
| TLS 1.2 | ✅ 許容可能 | 適切な暗号スイートを使用すれば、引き続き安全です |
| TLS 1.1 | ❌ 非推奨 | 2020 年以降無効化 |
| TLS 1.0 | ❌ 非推奨 | 重大な脆弱性 |
| SSL 3.0 | ❌ 破損 | POODLE 攻撃 |
| SSL 2.0 | ❌ 破損 | 多数の脆弱性 |
TLS 設定の詳細: TLS 設定ガイドを参照してください。
鍵管理
鍵階層
┌─────────────────────────────────────┐
│ Master Key (KEK) │ <- Stored in HSM or KMS
│ - Encrypts all other keys │
└──────────────────┬──────────────────┘
│
┌───────────┴───────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Data Key 1 │ │ Data Key 2 │ <- Encrypted with KEK
│ (DEK) │ │ (DEK) │
└──────────────┘ └──────────────┘
鍵ローテーション戦略
/// <summary>
/// Key manager with automatic rotation support.
/// </summary>
public sealed class KeyManager(IKmsClient kmsClient) : IDisposable
{
private static readonly TimeSpan RotationPeriod = TimeSpan.FromDays(90);
private string? _currentKeyId;
private DateTime? _keyExpiry;
private readonly SemaphoreSlim _lock = new(1, 1);
/// <summary>
/// Get current encryption key, rotating if needed.
/// </summary>
public async Task<string> GetCurrentKeyAsync(CancellationToken cancellationToken = default)
{
await _lock.WaitAsync(cancellationToken);
try
{
if (NeedsRotation())
{
await RotateKeyAsync(cancellationToken);
}
return _currentKeyId!;
}
finally
{
_lock.Release();
}
}
private bool NeedsRotation() =>
_keyExpiry is null || DateTime.UtcNow > _keyExpiry;
private async Task RotateKeyAsync(CancellationToken cancellationToken)
{
// Create new key in KMS
var newKey = await kmsClient.CreateKeyAsync(
description: $"Data key created {DateTime.UtcNow:O}",
keyUsage: KeyUsage.EncryptDecrypt,
cancellationToken: cancellationToken
);
_currentKeyId = newKey.KeyId;
_keyExpiry = DateTime.UtcNow.Add(RotationPeriod);
// Keep old keys for decryption (don't delete immediately)
// Data encrypted with old keys can still be decrypted
}
public void Dispose() => _lock.Dispose();
}
// KMS client interface (implement for Azure Key Vault, AWS KMS, etc.)
public interface IKmsClient
{
Task<KmsKey> CreateKeyAsync(string description, KeyUsage keyUsage, CancellationToken cancellationToken);
}
public enum KeyUsage { EncryptDecrypt, SignVerify }
public sealed record KmsKey(string KeyId, DateTime CreatedAt);
乱数生成
using System.Security.Cryptography;
// For cryptographic use - ALWAYS use these
var secureRandomBytes = RandomNumberGenerator.GetBytes(32); // 32 random bytes
var secureRandomHex = Convert.ToHexString(RandomNumberGenerator.GetBytes(32)); // 64 hex chars
var secureRandomUrl = Convert.ToBase64String(RandomNumberGenerator.GetBytes(32))
.Replace('+', '-').Replace('/', '_').TrimEnd('='); // URL-safe base64
// For random integers in a range (e.g., tokens, OTPs)
var randomInt = RandomNumberGenerator.GetInt32(100000, 999999); // 6-digit OTP
// NEVER use for cryptography
var random = new Random();
random.Next(); // NOT cryptographically secure - for games/simulations only
ポスト量子暗号に関する考慮事項
現在の非対称アルゴリズム(RSA、ECDSA、ECDH)は、量子コンピューターに対して脆弱です。
NIST ポスト量子標準(2024年)
| アルゴリズム | 種類 | 状態 |
|---|---|---|
| ML-KEM (Kyber) | 鍵カプセル化 | ✅ 標準化済み |
| ML-DSA (Dilithium) | デジタル署名 | ✅ 標準化済み |
| SLH-DSA (SPHINCS+) | デジタル署名 | ✅ 標準化済み |
ハイブリッド方式(現時点で推奨)
// Combine classical and post-quantum algorithms
// If either is broken, the other still provides security
// Key exchange: X25519 + ML-KEM-768
// Signature: ECDSA P-256 + ML-DSA-65
// .NET 10+ will include ML-KEM and ML-DSA support
// Until then, use libraries like BouncyCastle for PQ algorithms
// This provides defense-in-depth during the transition period:
// 1. Classical algorithms handle today's threats
// 2. PQ algorithms protect against future quantum attacks
// 3. Combined key material ensures security if either is compromised
クイック判断ツリー
どの暗号操作が必要ですか?
- 保存データの暗号化 → AES-256-GCM
- 転送中のデータの暗号化 → TLS 1.3
- パスワードのハッシュ化 → Argon2id
- データのハッシュ化(パスワード以外) → SHA-256 または BLAKE2b
- デジタル署名 → Ed25519 または ECDSA P-256
- 鍵交換 → X25519 または ECDH P-256
- メッセージ認証 → HMAC-SHA256
- 乱数値の生成 →
RandomNumberGenerator.GetBytes()またはRandomNumberGenerator.GetInt32()
セキュリティチェックリスト
暗号化
- 認証付き暗号化(AES-GCM、ChaCha20-Poly1305)を使用する
- 十分なエントロピーを持つ鍵(256ビット)を生成する
- nonce/IVを再利用しない
- 適切な鍵管理を実装する
パスワードのハッシュ化
- Argon2id、bcrypt、または scrypt を使用する
- MD5、SHA-1、またはソルトなしのハッシュを使用しない
- 適切なワークファクターを使用する
- パラメーターの変更時に再ハッシュ化を実装する
TLS
- TLS 1.2 以上を使用し、TLS 1.3 を優先する
- 強力な暗号スイートのみを使用する
- 信頼できる CA による有効な証明書を使用する
- HSTS を有効にする
鍵
- 安全に鍵を生成する
- 適切に鍵を保管する(機密性の高い鍵には HSM/KMS を使用)
- 鍵のローテーションポリシーを定める
- 鍵を安全に破棄する
参考資料
- アルゴリズム選択ガイド - アルゴリズムの詳細な比較
- パスワードハッシュ化リファレンス - パスワードハッシュ化の詳細解説
- TLS 設定ガイド - 各種プラットフォームでの TLS 設定
関連スキル
| スキル | 関連性 |
|---|---|
authentication-patterns | JWT、セッションに暗号技術を使用 |
secrets-management | 暗号鍵を安全に保管 |
secure-coding | セキュアな実装パターン全般 |
バージョン履歴
- v1.0.0 (2025-12-26): アルゴリズム、パスワードハッシュ化、TLS、鍵管理を含む初回リリース
最終更新日: 2025-12-26
コメント
Markdown 対応