Я создал службу шифрования, используя AES-GCM, чтобы зашифровать конфиденциальные данные в базе данных. Во-первых, я генерирую криптографический ключ из пароля (вероятно, он будет храниться в Kubernetes Secrets) с помощью Rfc2898DeriveBytes. Затем передать этот ключ экземпляру AesGcm.Вы можете найти реализацию ниже.
открытый класс CryptoService: ICryptoService, IDisposable
{
частный только для чтения AesGcm _aesGcm;
общедоступный CryptoService (строковый пароль, строковая соль)
{
ключ байта [] = новый Rfc2898DeriveBytes (пароль, Encoding.UTF8.GetBytes (соль), 200000, HashAlgorithmName.SHA512).GetBytes (32);
// Получает безопасно сгенерированный случайным образом зашифрованный ключ шифрования данных из хранилища Azure.
строка зашифрованнаяEncryptionKey = AzureVault.GetDataEncryptionKey();
byte[] EncryptionKey = AzureVault.Decrypt(encryptedEncryptionKey, ключ);
_aesGcm = новый AesGcm (Ключ шифрования);
}
общедоступная строка Шифрование (строка простого текста)
{
byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
int nonceSize = AesGcm.NonceByteSizes.MaxSize;
int tagSize = AesGcm.TagByteSizes.MaxSize;
int cipherSize = plainBytes.Length;
// Объединяем для упрощения кодирования
intcryptedDataLength = 4 + nonceSize + 4 + tagSize + cipherSize;
Span<байт> зашифрованные данные = длина зашифрованных данных < 1024 ? stackalloc byte[encryptedDataLength] : новый байт[encryptedDataLength].AsSpan();
BinaryPrimitives.WriteInt32LittleEndian (encryptedData.Slice (0, 4), nonceSize);
BinaryPrimitives.WriteInt32LittleEndian(encryptedData.Slice(4 + nonceSize, 4), tagSize);
var nonce = зашифрованные данные.Slice(4, nonceSize);
var tag = зашифрованные данные.Slice(4 + nonceSize + 4, tagSize);
var cipherBytes = зашифрованные данные.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
RandomNumberGenerator.Fill(одноразовый);
_aesGcm.Encrypt(nonce, plainBytes.AsSpan(), cipherBytes, тег);
вернуть Convert.ToBase64String (зашифрованные данные);
}
общедоступная строка Расшифровать (строка cipherText)
{
Span<byte> зашифрованные данные = Convert.FromBase64String(cipherText).AsSpan();
int nonceSize = BinaryPrimitives.ReadInt32LittleEndian (encryptedData.Slice (0, 4));
int tagSize = BinaryPrimitives.ReadInt32LittleEndian (encryptedData.Slice (4 + nonceSize, 4));
int cipherSize = зашифрованные данные. длина - 4 - nonceSize - 4 - tagSize;
var nonce = зашифрованные данные.Slice(4, nonceSize);
var tag = зашифрованные данные.Slice(4 + nonceSize + 4, tagSize);
var cipherBytes = зашифрованные данные.Slice(4 + nonceSize + 4 + tagSize, cipherSize);
Span<byte> plainBytes = cipherSize < 1024? stackalloc byte[cipherSize] : новый байт[cipherSize];
_aesGcm.Decrypt(nonce, cipherBytes, tag, plainBytes);
вернуть Encoding.UTF8.GetString(plainBytes);
}
}
Вот мой вопрос. Мне интересно, достаточно ли безопасна эта реализация, поскольку я не эксперт в области безопасности. Я упустил какую-то точку или дыру в безопасности, кроме защиты паролем? Любые советы и предложения будут с благодарностью.
Спасибо.