web-dev-qa-db-ja.com

.NET Coreの文字列を暗号化する

キーを使用して.NET Coreの文字列を暗号化します。クライアント/サーバーのシナリオがあり、クライアントで文字列を暗号化し、サーバーに送信して解読したいと考えています。

.NET Coreはまだ初期段階にあるため(たとえば、Rijndaelはまだ利用できません)、私のオプションは何ですか?

22
dknaack

.NETでRijndael/RijndaelManagedを使用するべきではありません。 BlockSize値を128(デフォルト)で使用している場合、A 同様の質問で説明 のようにAESを使用しています。

.NET Coreで使用可能な対称暗号化オプションは次のとおりです。

  • AES(System.Security.Cryptography.Aes.Create())
  • 3DES(System.Security.Cryptography.TripleDES.Create())

そして非対称暗号化のために

  • RSA(System.Security.Cryptography.RSA.Create())

特に.NET Coreでは、現在実行中のオペレーティングシステムで動作するオブジェクトを返すため、ファクトリーが最適な方法です。たとえば、RSACngはパブリックタイプですが、Windowsでのみ機能します。 RSAOpenSslはパブリックタイプですが、LinuxとmacOSでのみサポートされています。

30
bartonjs

これに対する答えはすでにありますが、より簡単なソリューションを提供できると思います。

単純にprotectにしたい場合は、暗号化の頭痛から解放される.NET Coreの実装があります。 DataProtectionProvider

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDataProtection(); //Add this
    [..]
    services.AddMvc();
}

必要に応じて、アルゴリズムを指定することができます(Microsoft.AspNetCore.DataProtection)次のように、暗号化と検証に使用されます。

services.AddDataProtection()
       .UseCryptographicAlgorithms(new AuthenticatedEncryptionSettings()
       {
           EncryptionAlgorithm = EncryptionAlgorithm.AES_256_GCM,
           ValidationAlgorithm = ValidationAlgorithm.HMACSHA256
       });

次に、次のようなサービスを使用して暗号化/復号化します。

public class CipherService : ICipherService
{
    private readonly IDataProtectionProvider _dataProtectionProvider;
    private const string Key = "my-very-long-key-of-no-exact-size";

    public CipherService(IDataProtectionProvider dataProtectionProvider)
    {
        _dataProtectionProvider = dataProtectionProvider;
    }

    public string Encrypt(string input)
    {
        var protector = _dataProtectionProvider.CreateProtector(Key);
        return protector.Protect(input);
    }

    public string Decrypt(string cipherText)
    {
        var protector = _dataProtectionProvider.CreateProtector(Key);
        return protector.Unprotect(cipherText);
    }
}

編集以下のコメントで述べたように、このようなDataProtectionProviderの使用は、ローカルディスクに保存されたキーを持つ同じマシンでのみ機能することを理解することをお勧めします。

21
Marcus

ここに簡単なサンプルがありますwithout認証:

var text = "Hello World";
var buffer = Encoding.UTF8.GetBytes(text);

var iv = GetRandomData(128);
var keyAes = GetRandomData(256);


byte[] result;
using (var aes = Aes.Create())
{
    aes.Key = keyAes;
    aes.IV = iv;

    using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
    using (var resultStream = new MemoryStream())
    {
        using (var aesStream = new CryptoStream(resultStream, encryptor, CryptoStreamMode.Write))
        using (var plainStream = new MemoryStream(buffer))
        {
            plainStream.CopyTo(aesStream);
        }

        result = resultStream.ToArray();
    }
}

キー生成の場合:

private static byte[] GetRandomData(int bits)
{
    var result = new byte[bits / 8];
    RandomNumberGenerator.Create().GetBytes(result);
    return result;
}
14
dhcgn

キーを使用して文字列を暗号化し、スクランブルされた文字列を取得し、同じキーで再度復号化できるようにする別の方法があります。以下の拡張方法を参照してください。

    public static string Encrypt(this string text, string key)
    {
        if (string.IsNullOrEmpty(key))
            throw new ArgumentException("Key must have valid value.", nameof(key));
        if (string.IsNullOrEmpty(text))
            throw new ArgumentException("The text must have valid value.", nameof(text));

        var buffer = Encoding.UTF8.GetBytes(text);
        var hash = new SHA512CryptoServiceProvider();
        var aesKey = new byte[24];
        Buffer.BlockCopy(hash.ComputeHash(Encoding.UTF8.GetBytes(key)), 0, aesKey, 0, 24);

        using (var aes = Aes.Create())
        {
            if (aes == null)
                throw new ArgumentException("Parameter must not be null.", nameof(aes));

            aes.Key = aesKey;

            using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
            using (var resultStream = new MemoryStream())
            {
                using (var aesStream = new CryptoStream(resultStream, encryptor, CryptoStreamMode.Write))
                using (var plainStream = new MemoryStream(buffer))
                {
                    plainStream.CopyTo(aesStream);
                }

                var result = resultStream.ToArray();
                var combined = new byte[aes.IV.Length + result.Length];
                Array.ConstrainedCopy(aes.IV, 0, combined, 0, aes.IV.Length);
                Array.ConstrainedCopy(result, 0, combined, aes.IV.Length, result.Length);

                return Convert.ToBase64String(combined);
            }
        }
    }

    public static string Decrypt(this string encryptedText, string key)
    {
        if (string.IsNullOrEmpty(key))
            throw new ArgumentException("Key must have valid value.", nameof(key));
        if (string.IsNullOrEmpty(encryptedText))
            throw new ArgumentException("The encrypted text must have valid value.", nameof(encryptedText));

        var combined = Convert.FromBase64String(encryptedText);
        var buffer = new byte[combined.Length];
        var hash = new SHA512CryptoServiceProvider();
        var aesKey = new byte[24];
        Buffer.BlockCopy(hash.ComputeHash(Encoding.UTF8.GetBytes(key)), 0, aesKey, 0, 24);

        using (var aes = Aes.Create())
        {
            if (aes == null)
                throw new ArgumentException("Parameter must not be null.", nameof(aes));

            aes.Key = aesKey;

            var iv = new byte[aes.IV.Length];
            var ciphertext = new byte[buffer.Length - iv.Length];

            Array.ConstrainedCopy(combined, 0, iv, 0, iv.Length);
            Array.ConstrainedCopy(combined, iv.Length, ciphertext, 0, ciphertext.Length);

            aes.IV = iv;

            using (var decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
            using (var resultStream = new MemoryStream())
            {
                using (var aesStream = new CryptoStream(resultStream, decryptor, CryptoStreamMode.Write))
                using (var plainStream = new MemoryStream(ciphertext))
                {
                    plainStream.CopyTo(aesStream);
                }

                return Encoding.UTF8.GetString(resultStream.ToArray());
            }
        }
    }
7
iss0

データ保護システムは、ASP.NET Coreアプリケーションに対してデフォルトで有効になっています。デフォルトのキーストレージの場所またはキーの有効期間を再構成する場合を除き、StartUpメソッドで何もする必要はありません。その場合、ConfigureServicesメソッドで次のことを行います。

services.ConfigureDataProtection(dp =>
    {
        dp.PersistKeysToFileSystem(new DirectoryInfo(@"c:\keys"));
        dp.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
    });

データ保護システムはデフォルトでアプリケーションのサービスコレクションに含まれているため、依存性注入を介して利用可能にすることができます。 IDataProtectionProviderをコントローラーに挿入し、それを使用してコントローラーのコンストラクターでIDataProtectorのインスタンスを作成する方法は次のとおりです。

public class HomeController : Controller
{
    IDataProtector _protector;

    public HomeController(IDataProtectionProvider provider)
    {
        _protector = provider.CreateProtector(GetType().FullName);
    }
}

その後、プロテクターを呼び出して、次のようにコンテンツを暗号化できます。

public IActionResult Index()
{
    var model = _service.GetAll().Select(c => new ContractViewModel {
        Id = _protector.Protect(c.Id.ToString()),
        Name = c.Name }).ToList();
    return View(model);
}

これが役立つことを願っています:)

3
Webezine