mcpField
C
cryptography

cryptography

github.com/melodic-softwareセキュリティ2888 回インストール今日更新
リポジトリ

cryptography について

cryptographyは、暗号化、パスワードハッシュ、TLS、鍵管理、耐量子計算機の考慮事項を扱う開発者向け実装ガイドです。アルゴリズム選択の指針、例、セキュリティチェックリストを提供します。

主な機能

  1. 01共通鍵・公開鍵暗号の指針
  2. 02パスワードハッシュとコスト設定の指針
  3. 03TLSバージョンと設定の推奨事項
  4. 04鍵管理とローテーションの指針
  5. 05安全な乱数と耐量子計算機の考慮事項
  6. 06暗号実装のセキュリティチェックリスト

活用シーン

  1. 01保存データの暗号方式の選定
  2. 02パスワード保存と検証の実装
  3. 03TLS設定と鍵管理のレビュー
  4. 04耐量子計算機への備えの評価

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/melodic-software/claude-code-plugins --skill cryptography

インストール後、Claude Code で/cryptographyを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
algorithm-selection.md
password-hashing.md
tls-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 ビットなし⚠️ 回避してください
署名アルゴリズム
アルゴリズム種類鍵長用途ステータス
Ed25519EdDSA256 ビット署名✅ 推奨
ECDSA (P-256)ECC256 ビット署名、JWT✅ 推奨
RSA-PSSRSA2048 ビット以上署名✅ 推奨
RSA PKCS#1 v1.5RSA2048 ビット以上レガシー署名⚠️ 代わりに PSS を使用してください
ハッシュ関数
アルゴリズム出力サイズ用途ステータス
SHA-256256 ビット汎用ハッシュ✅ 推奨
SHA-384384 ビットより高いセキュリティ✅ 推奨
SHA-512512 ビット最高レベルのセキュリティ✅ 推奨
SHA-3-256256 ビットSHA-2 の代替✅ 推奨
BLAKE2b256~512 ビット高速なハッシュ✅ 推奨
MD5128 ビットなし(脆弱)❌ 絶対に使用しないでください
SHA-1160 ビットなし(脆弱)❌ 絶対に使用しないでください

パスワードハッシュ

パスワードに汎用ハッシュ関数(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");
}
ワークファクターのガイドライン
アルゴリズム最小推奨高セキュリティ
Argon2idt=2, m=19MBt=3, m=64MBt=4, m=128MB
bcrypt101214
scryptN=2^14N=2^16N=2^18
PBKDF2310,000600,0001,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

クイック判断ツリー

どの暗号操作が必要ですか?

  1. 保存データの暗号化 → AES-256-GCM
  2. 転送中のデータの暗号化 → TLS 1.3
  3. パスワードのハッシュ化 → Argon2id
  4. データのハッシュ化(パスワード以外) → SHA-256 または BLAKE2b
  5. デジタル署名 → Ed25519 または ECDSA P-256
  6. 鍵交換 → X25519 または ECDH P-256
  7. メッセージ認証 → HMAC-SHA256
  8. 乱数値の生成 → 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 を使用)
  • 鍵のローテーションポリシーを定める
  • 鍵を安全に破棄する

参考資料

関連スキル

スキル関連性
authentication-patternsJWT、セッションに暗号技術を使用
secrets-management暗号鍵を安全に保管
secure-codingセキュアな実装パターン全般

バージョン履歴

  • v1.0.0 (2025-12-26): アルゴリズム、パスワードハッシュ化、TLS、鍵管理を含む初回リリース

最終更新日: 2025-12-26

コメント