📖 数据密集型设计

数据加密算法与密钥管理

深入探讨加密算法原理与密钥管理实践

一、数据加密概述

数据加密是将明文转换为密文的过程,在数据密集型应用中,加密是保障数据安全的核心技术,包括传输加密和存储加密两个方面。

二、加密算法分类

2.1 加密算法分类

graph TD A[加密算法] --> B[对称加密] A --> C[非对称加密] A --> D[哈希算法] A --> E[消息认证码] B --> B1[AES] B --> B2[DES] B --> B3[3DES] C --> C1[RSA] C --> C2[ECC] C --> C3[DSA] D --> D1[SHA-256] D --> D2[SHA-3] D --> D3[MD5] E --> E1[HMAC] E --> E2[CMAC]

2.2 加密算法对比

算法类型 代表算法 密钥长度 性能 安全性 适用场景
对称加密 AES-256 256位 极高 数据加密
非对称加密 RSA-2048 2048位 密钥交换
非对称加密 ECC-256 256位 中等 移动端
哈希算法 SHA-256 256位 数据校验
消息认证码 HMAC-SHA256 256位 身份验证

三、对称加密算法

3.1 AES加密实现

public class AesEncryptionService
{
    public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
    {
        using var aes = Aes.Create();
        aes.Key = key;
        aes.IV = iv;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        
        using var encryptor = aes.CreateEncryptor();
        using var memoryStream = new MemoryStream();
        using var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
        
        cryptoStream.Write(data, 0, data.Length);
        cryptoStream.FlushFinalBlock();
        
        return memoryStream.ToArray();
    }
    
    public byte[] Decrypt(byte[] encryptedData, byte[] key, byte[] iv)
    {
        using var aes = Aes.Create();
        aes.Key = key;
        aes.IV = iv;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        
        using var decryptor = aes.CreateDecryptor();
        using var memoryStream = new MemoryStream(encryptedData);
        using var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
        using var resultStream = new MemoryStream();
        
        cryptoStream.CopyTo(resultStream);
        
        return resultStream.ToArray();
    }
    
    public (byte[] Key, byte[] IV) GenerateKeyAndIV()
    {
        using var aes = Aes.Create();
        aes.GenerateKey();
        aes.GenerateIV();
        
        return (aes.Key, aes.IV);
    }
    
    public string EncryptToBase64(string plainText, string keyBase64)
    {
        var key = Convert.FromBase64String(keyBase64);
        var (_, iv) = GenerateKeyAndIV();
        var plainBytes = Encoding.UTF8.GetBytes(plainText);
        var encrypted = Encrypt(plainBytes, key, iv);
        
        return Convert.ToBase64String(iv.Concat(encrypted).ToArray());
    }
    
    public string DecryptFromBase64(string cipherTextBase64, string keyBase64)
    {
        var key = Convert.FromBase64String(keyBase64);
        var cipherBytes = Convert.FromBase64String(cipherTextBase64);
        var iv = cipherBytes.Take(16).ToArray();
        var encrypted = cipherBytes.Skip(16).ToArray();
        var decrypted = Decrypt(encrypted, key, iv);
        
        return Encoding.UTF8.GetString(decrypted);
    }
}

3.2 AES-GCM加密(带认证)

public class AesGcmEncryptionService
{
    public byte[] Encrypt(byte[] data, byte[] key, byte[] nonce, byte[] associatedData)
    {
        var tag = new byte[16];
        var encrypted = new byte[data.Length];
        
        using var aes = Aes.Create();
        aes.Key = key;
        
        using var gcm = new GcmAuthenticatedEncryption(aes);
        gcm.Encrypt(nonce, data, encrypted, tag, associatedData);
        
        return nonce.Concat(tag).Concat(encrypted).ToArray();
    }
    
    public byte[] Decrypt(byte[] encryptedData, byte[] key, byte[] associatedData)
    {
        var nonce = encryptedData.Take(12).ToArray();
        var tag = encryptedData.Skip(12).Take(16).ToArray();
        var cipherText = encryptedData.Skip(28).ToArray();
        var decrypted = new byte[cipherText.Length];
        
        using var aes = Aes.Create();
        aes.Key = key;
        
        using var gcm = new GcmAuthenticatedEncryption(aes);
        gcm.Decrypt(nonce, cipherText, tag, decrypted, associatedData);
        
        return decrypted;
    }
    
    public byte[] GenerateNonce()
    {
        var nonce = new byte[12];
        RandomNumberGenerator.Fill(nonce);
        
        return nonce;
    }
}

四、非对称加密算法

4.1 RSA加密实现

public class RsaEncryptionService
{
    public (byte[] PublicKey, byte[] PrivateKey) GenerateKeyPair(int keySize = 2048)
    {
        using var rsa = RSA.Create(keySize);
        
        return (
            rsa.ExportSubjectPublicKeyInfo(),
            rsa.ExportPkcs8PrivateKey()
        );
    }
    
    public byte[] Encrypt(byte[] data, byte[] publicKey)
    {
        using var rsa = RSA.Create();
        rsa.ImportSubjectPublicKeyInfo(publicKey, out _);
        
        return rsa.Encrypt(data, RSAEncryptionPadding.OaepSHA256);
    }
    
    public byte[] Decrypt(byte[] encryptedData, byte[] privateKey)
    {
        using var rsa = RSA.Create();
        rsa.ImportPkcs8PrivateKey(privateKey, out _);
        
        return rsa.Decrypt(encryptedData, RSAEncryptionPadding.OaepSHA256);
    }
    
    public byte[] Sign(byte[] data, byte[] privateKey)
    {
        using var rsa = RSA.Create();
        rsa.ImportPkcs8PrivateKey(privateKey, out _);
        
        return rsa.SignData(data, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
    }
    
    public bool VerifySignature(byte[] data, byte[] signature, byte[] publicKey)
    {
        using var rsa = RSA.Create();
        rsa.ImportSubjectPublicKeyInfo(publicKey, out _);
        
        return rsa.VerifyData(data, signature, HashAlgorithmName.SHA256, RSASignaturePadding.Pss);
    }
}

4.2 ECC加密实现

public class EccEncryptionService
{
    public (byte[] PublicKey, byte[] PrivateKey) GenerateKeyPair()
    {
        using var ecc = ECDsa.Create(ECCurve.NamedCurves.nistP256);
        
        return (
            ecc.ExportSubjectPublicKeyInfo(),
            ecc.ExportPkcs8PrivateKey()
        );
    }
    
    public byte[] Sign(byte[] data, byte[] privateKey)
    {
        using var ecc = ECDsa.Create();
        ecc.ImportPkcs8PrivateKey(privateKey, out _);
        
        return ecc.SignData(data, HashAlgorithmName.SHA256);
    }
    
    public bool VerifySignature(byte[] data, byte[] signature, byte[] publicKey)
    {
        using var ecc = ECDsa.Create();
        ecc.ImportSubjectPublicKeyInfo(publicKey, out _);
        
        return ecc.VerifyData(data, signature, HashAlgorithmName.SHA256);
    }
    
    public byte[] DeriveSharedSecret(byte[] privateKey, byte[] otherPublicKey)
    {
        using var ecc = ECDiffieHellman.Create();
        ecc.ImportPkcs8PrivateKey(privateKey, out _);
        
        var otherEcc = ECDiffieHellman.Create();
        otherEcc.ImportSubjectPublicKeyInfo(otherPublicKey, out _);
        
        return ecc.DeriveKeyMaterial(otherEcc.PublicKey);
    }
}

五、哈希算法

5.1 SHA-256哈希实现

public class HashService
{
    public byte[] ComputeSha256(byte[] data)
    {
        using var sha256 = SHA256.Create();
        
        return sha256.ComputeHash(data);
    }
    
    public string ComputeSha256Hex(string input)
    {
        var bytes = Encoding.UTF8.GetBytes(input);
        var hash = ComputeSha256(bytes);
        
        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }
    
    public byte[] ComputeSha384(byte[] data)
    {
        using var sha384 = SHA384.Create();
        
        return sha384.ComputeHash(data);
    }
    
    public byte[] ComputeSha512(byte[] data)
    {
        using var sha512 = SHA512.Create();
        
        return sha512.ComputeHash(data);
    }
    
    public byte[] ComputeSha3(byte[] data)
    {
        using var sha3 = SHA3.Create();
        
        return sha3.ComputeHash(data);
    }
    
    public bool VerifyHash(byte[] data, byte[] expectedHash)
    {
        var computedHash = ComputeSha256(data);
        
        return computedHash.SequenceEqual(expectedHash);
    }
}

5.2 HMAC消息认证码

public class HmacService
{
    public byte[] ComputeHmacSha256(byte[] data, byte[] key)
    {
        using var hmac = new HMACSHA256(key);
        
        return hmac.ComputeHash(data);
    }
    
    public string ComputeHmacSha256Hex(string input, string key)
    {
        var dataBytes = Encoding.UTF8.GetBytes(input);
        var keyBytes = Encoding.UTF8.GetBytes(key);
        var hash = ComputeHmacSha256(dataBytes, keyBytes);
        
        return BitConverter.ToString(hash).Replace("-", "").ToLower();
    }
    
    public byte[] ComputeHmacSha512(byte[] data, byte[] key)
    {
        using var hmac = new HMACSHA512(key);
        
        return hmac.ComputeHash(data);
    }
    
    public bool VerifyHmac(byte[] data, byte[] expectedHmac, byte[] key)
    {
        var computedHmac = ComputeHmacSha256(data, key);
        
        return computedHmac.SequenceEqual(expectedHmac);
    }
    
    public string GenerateToken(string userId, string secretKey, TimeSpan expiresIn)
    {
        var payload = new
        {
            UserId = userId,
            ExpiresAt = DateTime.UtcNow.Add(expiresIn).ToUnixTimeSeconds()
        };
        
        var payloadJson = JsonSerializer.Serialize(payload);
        var payloadBytes = Encoding.UTF8.GetBytes(payloadJson);
        var keyBytes = Encoding.UTF8.GetBytes(secretKey);
        var signature = ComputeHmacSha256(payloadBytes, keyBytes);
        
        return $"{Convert.ToBase64String(payloadBytes)}.{Convert.ToBase64String(signature)}";
    }
    
    public bool ValidateToken(string token, string secretKey)
    {
        var parts = token.Split('.');
        
        if (parts.Length != 2)
        {
            return false;
        }
        
        var payloadBytes = Convert.FromBase64String(parts[0]);
        var signature = Convert.FromBase64String(parts[1]);
        var keyBytes = Encoding.UTF8.GetBytes(secretKey);
        var computedSignature = ComputeHmacSha256(payloadBytes, keyBytes);
        
        if (!computedSignature.SequenceEqual(signature))
        {
            return false;
        }
        
        var payloadJson = Encoding.UTF8.GetString(payloadBytes);
        var payload = JsonSerializer.Deserialize(payloadJson);
        
        return payload.ExpiresAt > DateTime.UtcNow.ToUnixTimeSeconds();
    }
}

六、密钥管理

6.1 密钥管理架构

graph TD A[密钥管理] --> B[密钥生成] A --> C[密钥存储] A --> D[密钥分发] A --> E[密钥轮换] A --> F[密钥销毁] B --> B1[随机数生成] B --> B2[密钥派生] C --> C1[密钥库] C --> C2[HSM] D --> D1[TLS] D --> D2[非对称加密] E --> E1[定期轮换] E --> E2[事件触发] F --> F1[安全擦除] F --> F2[密钥归档]

6.2 密钥管理实现

public class KeyManagementService
{
    public async Task GenerateKeyAsync(string keyId, KeyType keyType, int keySize = 256)
    {
        byte[] key = null;
        
        switch (keyType)
        {
            case KeyType.Aes:
                key = GenerateAesKey(keySize);
                break;
            case KeyType.Rsa:
                var (publicKey, privateKey) = _rsaService.GenerateKeyPair(keySize);
                key = privateKey;
                break;
        }
        
        var keyInfo = new KeyInfo
        {
            KeyId = keyId,
            KeyType = keyType,
            KeySize = keySize,
            CreatedAt = DateTime.UtcNow,
            Status = KeyStatus.Active,
            Version = 1
        };
        
        await _keyStorage.StoreKeyAsync(keyId, key, keyInfo);
        
        return keyInfo;
    }
    
    public async Task GetKeyAsync(string keyId)
    {
        return await _keyStorage.GetKeyAsync(keyId);
    }
    
    public async Task RotateKeyAsync(string keyId)
    {
        var oldKeyInfo = await _keyStorage.GetKeyInfoAsync(keyId);
        
        var newKey = GenerateAesKey(oldKeyInfo.KeySize);
        
        var newKeyInfo = new KeyInfo
        {
            KeyId = keyId,
            KeyType = oldKeyInfo.KeyType,
            KeySize = oldKeyInfo.KeySize,
            CreatedAt = DateTime.UtcNow,
            Status = KeyStatus.Active,
            Version = oldKeyInfo.Version + 1
        };
        
        await _keyStorage.ArchiveKeyAsync(keyId, oldKeyInfo.Version);
        await _keyStorage.StoreKeyAsync(keyId, newKey, newKeyInfo);
        
        return newKeyInfo;
    }
    
    public async Task DeleteKeyAsync(string keyId)
    {
        await _keyStorage.DeleteKeyAsync(keyId);
    }
    
    private byte[] GenerateAesKey(int keySize)
    {
        var key = new byte[keySize / 8];
        RandomNumberGenerator.Fill(key);
        
        return key;
    }
}

6.3 密钥存储

public class KeyStorageService
{
    public async Task StoreKeyAsync(string keyId, byte[] key, KeyInfo keyInfo)
    {
        var encryptedKey = _aesService.Encrypt(key, _masterKey, _masterIv);
        
        await _database.SaveKeyAsync(new KeyRecord
        {
            KeyId = keyId,
            EncryptedKey = encryptedKey,
            KeyInfo = keyInfo,
            CreatedAt = DateTime.UtcNow
        });
    }
    
    public async Task GetKeyAsync(string keyId)
    {
        var keyRecord = await _database.GetKeyAsync(keyId);
        
        return _aesService.Decrypt(keyRecord.EncryptedKey, _masterKey, _masterIv);
    }
    
    public async Task ArchiveKeyAsync(string keyId, int version)
    {
        await _database.ArchiveKeyAsync(keyId, version);
    }
    
    public async Task DeleteKeyAsync(string keyId)
    {
        await _database.DeleteKeyAsync(keyId);
    }
    
    public async Task GetKeyInfoAsync(string keyId)
    {
        var keyRecord = await _database.GetKeyAsync(keyId);
        
        return keyRecord.KeyInfo;
    }
}

七、传输加密

7.1 TLS配置

public class TlsConfigurationService
{
    public SslStream CreateSslStream(Stream innerStream, bool leaveInnerStreamOpen)
    {
        var sslOptions = new SslServerAuthenticationOptions
        {
            ServerCertificate = _certificate,
            EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13,
            ClientCertificateRequired = false,
            EncryptionPolicy = EncryptionPolicy.RequireEncryption
        };
        
        return new SslStream(innerStream, leaveInnerStreamOpen);
    }
    
    public HttpClient CreateSecureHttpClient()
    {
        var handler = new HttpClientHandler
        {
            SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13,
            ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
            {
                if (sslPolicyErrors == SslPolicyErrors.None)
                {
                    return true;
                }
                
                return false;
            }
        };
        
        return new HttpClient(handler);
    }
    
    public void ConfigureHttpsServer(WebHostBuilder builder)
    {
        builder.UseKestrel(options =>
        {
            options.ListenAnyIP(443, listenOptions =>
            {
                listenOptions.UseHttps(_certificatePath, _certificatePassword);
                listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
            });
        });
    }
}

八、加密最佳实践

8.1 加密算法选型

场景 推荐算法 密钥长度
数据加密 AES-GCM 256位
密钥交换 RSA-OAEP 2048+位
数字签名 ECDSA 256位
哈希校验 SHA-256 256位
消息认证 HMAC-SHA256 256位

8.2 密钥管理最佳实践

  • 使用随机数生成器生成密钥
  • 定期轮换密钥
  • 使用HSM存储主密钥
  • 加密存储密钥
  • 限制密钥访问权限

8.3 安全注意事项

public class EncryptionSecurityService
{
    public bool ValidateKeySize(KeyType keyType, int keySize)
    {
        return keyType switch
        {
            KeyType.Aes => keySize >= 256,
            KeyType.Rsa => keySize >= 2048,
            KeyType.Ecc => keySize >= 256,
            _ => false
        };
    }
    
    public void ValidateEncryptionMode(CipherMode mode)
    {
        if (mode != CipherMode.CBC && mode != CipherMode.GCM)
        {
            throw new InvalidOperationException("Unsupported cipher mode");
        }
    }
    
    public bool IsAlgorithmSupported(string algorithm)
    {
        var supportedAlgorithms = new[] { "AES", "RSA", "ECDSA", "SHA-256", "SHA-384", "SHA-512" };
        
        return supportedAlgorithms.Contains(algorithm);
    }
    
    public void ValidateNonce(byte[] nonce)
    {
        if (nonce == null || nonce.Length != 12)
        {
            throw new InvalidOperationException("Invalid nonce");
        }
    }
}

九、总结

数据加密是保障数据安全的核心技术。对称加密适合大量数据加密,非对称加密适合密钥交换,哈希算法适合数据校验,HMAC适合消息认证。通过合理选择加密算法、实现密钥管理、配置传输加密,能够构建安全的数据密集型应用。