사용자가 제공 한 암호 (키)와 salt를 기반으로 문자열을 인코딩하고 디코딩해야하는 dotnet 코어에 대한 간단한 도우미 작업을하고 있습니다.dotnet 코어에서 문자열과 암호를 사용하여 문자열을 인 코드하고 디코드하십시오.
전체 .NET Framework와 달리 dotnet core에는 현재 RijndaelManaged 클래스에 대한 구현이 없습니다. 거의 모든 C#의 암호화/해독 샘플은이 클래스를 기반으로하므로 dotnet 코어에서 쓸모 없게 만듭니다. CoreFX repo on GitHub에는 많은 논란이 있습니다. 내가 반 말했다
internal class CryptographyHelpers
{
internal static string Decrypt(string password, string salt, string encrypted_value)
{
string decrypted;
using (var aes = Aes.Create())
{
var keys = GetAesKeyAndIV(password, salt, aes);
aes.Key = keys.Item1;
aes.IV = keys.Item2;
// create a decryptor to perform the stream transform.
var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
// create the streams used for encryption.
var encrypted_bytes = ToByteArray(encrypted_value);
using (var memory_stream = new MemoryStream(encrypted_bytes))
{
using (var crypto_stream = new CryptoStream(memory_stream, decryptor, CryptoStreamMode.Read))
{
using (var reader = new StreamReader(crypto_stream))
{
decrypted = reader.ReadToEnd();
}
}
}
}
return decrypted;
}
internal static string Encrypt(string password, string salt, string plain_text)
{
string encrypted;
using (var aes = Aes.Create())
{
var keys = GetAesKeyAndIV(password, salt, aes);
aes.Key = keys.Item1;
aes.IV = keys.Item2;
var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using (var memory_stream = new MemoryStream())
{
using (var crypto_stream = new CryptoStream(memory_stream, encryptor, CryptoStreamMode.Write))
{
using (var writer = new StreamWriter(crypto_stream))
{
writer.Write(plain_text);
}
var encrypted_bytes = memory_stream.ToArray();
encrypted = ToString(encrypted_bytes);
}
}
}
return encrypted;
}
private static byte[] ToByteArray(string input)
{
return Encoding.Unicode.GetBytes(input);
}
private static string ToString(byte[] input)
{
return Encoding.Unicode.GetString(input);
}
private static Tuple<byte[], byte[]> GetAesKeyAndIV(string password, string salt, SymmetricAlgorithm symmetricAlgorithm)
{
const int bits = 8;
var key = new byte[16];
var iv = new byte[16];
var derive_bytes = new Rfc2898DeriveBytes(password, ToByteArray(salt));
key = derive_bytes.GetBytes(symmetricAlgorithm.KeySize/bits);
iv = derive_bytes.GetBytes(symmetricAlgorithm.BlockSize/bits);
return new Tuple<byte[], byte[]>(key, iv);
}
}
:
그러나, 모두 (구) MSDN article on AesManaged의 조합과 article by Troy Hunt으로 - - 리팩토링을 언급하지 않기 위하여 나는 다음과 같은 반 가공 예 맥주를 양조 할 수 있었다 작업 예를 의미합니다 ... 가끔. 그리고 그 문제가 있습니다. 테스트를 임의로 실행하면 대부분의 경우 성공합니다.
Message: Expected string to be "lorem ipsum dom dolor sit amet", but " �R��k6��o��do�Lr sit amet" differs near ">�R" (index 0).
그것은 유니 코드 문제처럼 보이지만 Encoding.UTF8에 헬퍼의 Encoding.Unicode 변경이 오류에 이르게 : 무작위로 4 회 중 약, 그것은 다음과 같은 메시지와 함께 실패
System.Security.Cryptography.CryptographicException : The input data is not a complete block.
Encoding.ASCII에 인코딩을 변경하면 다음과 같은 오류에 이르게 :
System.Security.Cryptography.CryptographicException : Specified padding mode is not valid for this algorithm.
내가 사용 테스트는 다음과 같습니다
[Fact]
public void Decrypt_Should_Decode_An_Encrypted_String()
{
// arrange
var key = Guid.NewGuid().ToString();
var salt = Guid.NewGuid().ToString();
var original_value = "lorem ipsum dom dolor sit amet";
var encrypted_value = CryptographyHelpers.Encrypt(key, salt, original_value);
// act
var target = CryptographyHelpers.Decrypt(key, salt, encrypted_value);
// assert
target.Should().NotBeNullOrEmpty();
target.Should().Be(original_value);
}
그래서 내 기본 질문은 입니다. 왜 내 imlementation (테스트)가 실패합니까?
나는 확실히 암호에 대한 전문가는 아니지만, 높은 수준에서 몇 가지 기본 개념을 알고 있습니다. 또한 유사한 질문 "How to use Rijndael encryption with a .Net Core class library?"이 게시되었지만 유일한 대답은 구체적인 구현이 결여 된 개념적 수준에 머물러 있습니다.
이것이 '충분히 좋은'구현인지에 대한 모든 팁과 주장도 매우 높이 평가할 것입니다.
감사합니다. 당신이 경우에
하기는 _salt_ 등으로 새로운 Rfc2898DeriveBytes를 사용하려고 바이트 배열을 int로 사용하면 IV에 대해 일관된 결과를 얻을 수 없습니다. –