Claude
Skills
Sign in
Back

dotnet-cryptography

Included with Lifetime
$97 forever

Choosing crypto algorithms, hashing, encryption, or key derivation. AES-GCM, RSA, ECDSA, PQC.

Web3

What this skill does


# dotnet-cryptography

Modern .NET cryptography covering hashing (SHA-256/384/512), symmetric encryption (AES-GCM), asymmetric cryptography (RSA, ECDSA), key derivation (PBKDF2, Argon2), and post-quantum algorithms (ML-KEM, ML-DSA, SLH-DSA) for .NET 10+. Includes TFM-aware guidance: what's available on net10.0 vs fallback strategies for net8.0/net9.0.

**Out of scope:** Secrets management and configuration binding -- see [skill:dotnet-secrets-management]. OWASP vulnerability categories and deprecated security patterns -- see [skill:dotnet-security-owasp]. Authentication/authorization implementation (JWT, OAuth, Identity) -- see [skill:dotnet-api-security] and [skill:dotnet-blazor-auth]. Cloud-specific key management (Azure Key Vault, AWS KMS) -- cloud epics. TLS/HTTPS configuration -- covered by ASP.NET Core middleware.

Cross-references: [skill:dotnet-security-owasp] for OWASP A02 (Cryptographic Failures) and deprecated pattern warnings, [skill:dotnet-secrets-management] for storing keys and secrets securely.

---

## Scope Boundary

**In scope:** Algorithm selection, correct usage of `System.Security.Cryptography` APIs, key derivation, hashing for integrity, symmetric/asymmetric encryption, post-quantum cryptography, and deprecated algorithm warnings.

**Not in scope:** Key storage (use secrets management), TLS termination (infrastructure), authentication protocols (see [skill:dotnet-api-security]), cloud HSM/KMS services (cloud epics).

---

## Prerequisites

- .NET 8.0+ (LTS baseline for classical algorithms)
- .NET 10.0+ for post-quantum algorithms (ML-KEM, ML-DSA, SLH-DSA)
- Platform support for PQC: Windows 11 (November 2025+) or OpenSSL 3.5+ on Linux/macOS

---

## Hashing (SHA-2 Family)

Use SHA-256/384/512 for integrity verification, checksums, and content-addressable storage. Never use hashing alone for passwords (see Key Derivation below).

```csharp
using System.Security.Cryptography;

// Hash a byte array
byte[] data = "Hello, world"u8.ToArray();
byte[] hash = SHA256.HashData(data);

// Hash a stream (efficient for large files)
await using var stream = File.OpenRead("largefile.bin");
byte[] fileHash = await SHA256.HashDataAsync(stream);

// Compare hashes securely (constant-time comparison prevents timing attacks)
bool isEqual = CryptographicOperations.FixedTimeEquals(hash1, hash2);
```

```csharp
// HMAC for authenticated hashing (message authentication codes)
byte[] key = RandomNumberGenerator.GetBytes(32); // 256-bit key
byte[] mac = HMACSHA256.HashData(key, data);

// Verify HMAC
byte[] computedMac = HMACSHA256.HashData(key, receivedData);
if (!CryptographicOperations.FixedTimeEquals(mac, computedMac))
{
    throw new CryptographicException("Message authentication failed");
}
```

---

## Symmetric Encryption (AES-GCM)

AES-GCM is the recommended symmetric encryption for .NET. It provides both confidentiality and authenticity (authenticated encryption with associated data -- AEAD).

```csharp
using System.Security.Cryptography;

public static class AesGcmEncryptor
{
    private const int NonceSize = 12; // 96-bit nonce (required by GCM)
    private const int TagSize = 16;   // 128-bit authentication tag

    public static byte[] Encrypt(byte[] plaintext, 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);

        // Prepend nonce + append tag for transport
        var result = new byte[NonceSize + ciphertext.Length + TagSize];
        nonce.CopyTo(result, 0);
        ciphertext.CopyTo(result, NonceSize);
        tag.CopyTo(result, NonceSize + ciphertext.Length);
        return result;
    }

    public static byte[] Decrypt(byte[] encryptedData, byte[] key)
    {
        var nonce = encryptedData.AsSpan(0, NonceSize);
        var ciphertext = encryptedData.AsSpan(NonceSize, encryptedData.Length - NonceSize - TagSize);
        var tag = encryptedData.AsSpan(encryptedData.Length - TagSize);
        var plaintext = new byte[ciphertext.Length];

        using var aes = new AesGcm(key, TagSize);
        aes.Decrypt(nonce, ciphertext, tag, plaintext);
        return plaintext;
    }
}
```

```csharp
// ASP.NET Core Data Protection API -- preferred for web application scenarios
// Handles key management, rotation, and storage automatically
using Microsoft.AspNetCore.DataProtection;

public sealed class TokenProtector(IDataProtectionProvider provider)
{
    private readonly IDataProtector _protector =
        provider.CreateProtector("Tokens.V1");

    public string Protect(string plaintext) => _protector.Protect(plaintext);
    public string Unprotect(string ciphertext) => _protector.Unprotect(ciphertext);
}

// Registration:
builder.Services.AddDataProtection()
    .SetApplicationName("MyApp")
    .PersistKeysToFileSystem(new DirectoryInfo("/keys"));
```

---

## Asymmetric Cryptography (RSA, ECDSA)

### RSA

Use RSA for encryption of small payloads (key wrapping) and digital signatures. Minimum 2048-bit keys; prefer 4096-bit for new systems.

```csharp
using System.Security.Cryptography;

// Generate an RSA key pair
using var rsa = RSA.Create(4096);

// Sign data
byte[] signature = rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);

// Verify signature (with public key)
byte[] publicKeyBytes = rsa.ExportRSAPublicKey();
using var rsaPublic = RSA.Create();
rsaPublic.ImportRSAPublicKey(publicKeyBytes, out _);
bool valid = rsaPublic.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);

// Encrypt with OAEP padding (never use PKCS#1 v1.5 for new code)
byte[] encrypted = rsaPublic.Encrypt(smallPayload, RSAEncryptionPadding.OaepSHA256);
byte[] decrypted = rsa.Decrypt(encrypted, RSAEncryptionPadding.OaepSHA256);
```

### ECDSA

Prefer ECDSA over RSA for digital signatures in new projects -- smaller keys with equivalent security.

```csharp
using System.Security.Cryptography;

// Generate ECDSA key (P-256 = NIST curve, widely supported)
using var ecdsa = ECDsa.Create(ECCurve.NamedCurves.nistP256);

// Sign data
byte[] signature = ecdsa.SignData(data, HashAlgorithmName.SHA256);

// Export public key for verification
byte[] publicKey = ecdsa.ExportSubjectPublicKeyInfo();

// Import and verify
using var ecdsaPublic = ECDsa.Create();
ecdsaPublic.ImportSubjectPublicKeyInfo(publicKey, out _);
bool valid = ecdsaPublic.VerifyData(data, signature, HashAlgorithmName.SHA256);
```

---

## Key Derivation (Password Hashing)

### PBKDF2 (Built-in)

PBKDF2 is built into .NET and acceptable for password hashing. Use at least 600,000 iterations with SHA-256 (OWASP recommendation).

```csharp
using System.Buffers.Binary;
using System.Security.Cryptography;

public static class PasswordHasher
{
    private const int SaltSize = 16;       // 128-bit salt
    private const int HashSize = 32;       // 256-bit derived key
    private const int Iterations = 600_000; // OWASP 2023 recommendation for SHA-256
    private const int PayloadSize = 4 + SaltSize + HashSize; // iteration count + salt + hash

    public static string HashPassword(string password)
    {
        byte[] salt = RandomNumberGenerator.GetBytes(SaltSize);
        byte[] hash = Rfc2898DeriveBytes.Pbkdf2(
            password,
            salt,
            Iterations,
            HashAlgorithmName.SHA256,
            HashSize);

        // Store iteration count (fixed little-endian), salt, and hash together
        byte[] result = new byte[PayloadSize];
        BinaryPrimitives.WriteInt32LittleEndian(result, Iterations);
        salt.CopyTo(result.AsSpan(4));
        hash.CopyTo(result.AsSpan(4 + SaltSize));
        return Convert.ToBase64String(result);
    }

    public static bool VerifyPassword(string password, string stored)
    {
        // Defensive parsing: reject malformed input without exceptions
        Span<byte> decoded =
Files: 1
Size: 18.7 KB
Complexity: 21/100
Category: Web3

Related in Web3