【问题标题】:How to use Rijndael encryption with a .Net Core class library? (Not .Net Framework)如何将 Rijndael 加密与 .Net Core 类库一起使用? (不是 .Net 框架)
【发布时间】:2016-07-12 15:54:24
【问题描述】:

我们如何在 .Net Core 类库中使用 Rijndael 加密? (不是 .Net Framework 类库)我们需要创建一个共享的 .Net Core 库以在多个项目中使用,并且需要实现跨项目使用相同 Rijndael 加密的 Encrypt 和 Decrypt 方法。

我们目前正在使用:

  • VS 企业 2015
  • c#
  • .Net Core 类库
  • .NETStandard,版本=v1.6 参考

.Net Core 1.0 版本似乎缺少 Rijndael 和 AES 的实现......它似乎只包括基类。我们如何将 Rijndael 或 AES 加密的 .Net Core 实现添加为对新 .Net Core 类库项目的引用?

以下是适用于 .Net Framework 4.5.2 的 Encrypt 方法:

public static string Encrypt(string valueToEncrypt, string symmetricKey, string initializationVector)
{
    string returnValue = valueToEncrypt;

    var aes = new System.Security.Cryptography.RijndaelManaged();
    try
    {
        aes.Key = ASCIIEncoding.ASCII.GetBytes(symmetricKey);
        aes.IV = ASCIIEncoding.ASCII.GetBytes(initializationVector);
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.ISO10126;

        var desEncrypter = aes.CreateEncryptor();
        var buffer = ASCIIEncoding.ASCII.GetBytes(valueToEncrypt);

        returnValue = Convert.ToBase64String(desEncrypter.TransformFinalBlock(buffer, 0, buffer.Length));
    }
    catch (Exception)
    {
        returnValue = string.Empty;
    }

    return returnValue;
}

【问题讨论】:

  • .NET Core 有什么问题?缺少图书馆吗?
  • 似乎它在 1.1 版本的路线图上:github.com/dotnet/corefx/issues/9984
  • 正确的 Nate,主要问题似乎是当前版本的 .Net Core 的 Cryptography 参考中缺少 Rijndael 实现......只是基类抽象实现。
  • 1. ISO10126 已被撤销,PKCS#7 可能是更好的选择,实际上似乎符合 ISO10126 规范。 2. 最好使用随机 iv 否则相同的消息具有相同的加密字节。通常,iv 是从 CPRNG 创建的,并添加到加密数据之前,以便在解密期间使用。 3. 使用字符串作为加密不是特别安全,可能会导致密钥长度问题。最好使用 PBKFD1 等密钥派生函数。也有盲目的希望密码是ACIII,而不是unicode等其他编码。

标签: c# .net cryptography .net-core rijndaelmanaged


【解决方案1】:

Rijndael 和 AES 之间的区别(在 .NET 中)是 Rijndael 允许更改块大小,但 AES 不允许。由于 RijndaelManaged 的​​默认块大小与 AES 块大小(128 位/16 字节)相同,因此您实际上是在使用 AES。

不用按名称实例化实现类型,只需使用工厂 (Aes.Create())。这适用于 .NET Core 和 .NET Framework。

其他值得一提的事情:

  • 所有 SymmetricAlgorithm 实例都是 IDisposable,您应该在 using 语句中使用它们。
  • 所有 ICryptoTransform 实例(例如您错误命名的 desEncryptor)都是 IDisposable,您应该在 using 语句中使用它们。
  • ISO10126 填充在 .NET Core 1.0 中不可用。如果您需要与现有流兼容,您可以自己应用填充并指定 PaddingMode.None。否则,PKCS7 更标准。
  • 您的 AES 密钥不是很随机,因为它来自 ASCII 字符串(很多值都无效)。
    • Base64 至少有完整的取值范围
    • PBKDF2(基于密码的密钥派生函数 2)通过 Rfc2898DeriveBytes 类允许共享字符串秘密输入、可预测的噪声输出。
    • KeyAgreement 通常更好,但 .NET Core 1.0 中既不提供 ECDH 也不提供经典 DH。
  • 通常加密器应该计算一个随机IV(如果对多个操作使用相同的对象,请调用aes.GenerateIV())并将其与密文一起呈现。所以 encrypt 需要一个密钥和明文并产生一个密文和 IV。解密获取(密钥、IV、密文)并生成明文。

【讨论】:

  • bartonjs:对不起,如果这是一个愚蠢的问题,但我试图搜索如何做到这一点......我将如何手动应用 ISO10126 填充?我们确实需要与现有的流兼容。
  • 将数组扩展为块对齐(如果已经是,则添加另一个块)并按照en.wikipedia.org/wiki/Padding_(cryptography)#ISO_10126 填充它。如果您使用流,您可以将其排入数组或制作自定义 ICryptoTramsform 来包装当前的并应用/删除 TransformFinalBlock 中的填充。 (当然,自定义转换也适用于直接字节)。
  • 将 CFB 与 NoPadding 一起使用时。从Aes创建的CreateEncryptor不能有InputBlockSize == 1。RijndaelManaged没有这个问题。
  • 我有用 blocksize=256 加密的东西。我将如何完成解密?
【解决方案2】:

如果您只想加密/解密内容,请避免直接使用 Rijndael,因为 asp.net 核心有一些更好的包装器,这些包装器更易于使用,并且默认情况下更可能得到适当的保护。它被称为数据保护。

using Microsoft.AspNetCore.DataProtection;

// During startup add DP
serviceCollection.AddDataProtection();

...

// the 'provider' parameter is provided by DI
public MyClass(IDataProtectionProvider provider)
{
    _protector = provider.CreateProtector("Contoso.MyClass.v1");
}

...

// protect the payload
string protectedPayload = _protector.Protect(input);
Console.WriteLine($"Protect returned: {protectedPayload}");

...

// unprotect the payload
string unprotectedPayload = _protector.Unprotect(protectedPayload);
Console.WriteLine($"Unprotect returned: {unprotectedPayload}");

查看data protection docs了解更多信息

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 1970-01-01
    相关资源
    最近更新 更多