【问题标题】:Encrypt using AES 256 Mode-CBC IV(0)使用 AES 256 模式-CBC IV(0) 加密
【发布时间】:2015-04-17 10:27:01
【问题描述】:

我正在寻求一些帮助,以进行 AES 256 位加密,模式为 CBC,IV 为(16 字节)00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

基本上我想复制在this link 上所做的事情。所有的键都是十六进制的。以下是我从其他链接复制的内容。

以下解决方案中的几个问题:

  1. 如何使 IV 键全为零?
  2. 如何判断我的所有密钥都是十六进制的,而输出也必须是十六进制的?


public static String Encrypt(String plainText, String key)
{
    var plainBytes = Encoding.UTF8.GetBytes(plainText);
    return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(key)));
}

static RijndaelManaged GetRijndaelManaged(String secretKey)
{
    var keyBytes = new byte[16];
    var secretKeyBytes = Encoding.ASCII.GetBytes(secretKey);
    Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
    return new RijndaelManaged
    {
        Mode = CipherMode.ECB,
        Padding = PaddingMode.PKCS7,
        KeySize = 128,
        BlockSize = 128,
        Key = keyBytes,
        IV = keyBytes

    };
}

static byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
{
    return rijndaelManaged.CreateEncryptor()
        .TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}

【问题讨论】:

  • 你的意思是IV = new byte[16]KeySize = 256
  • 是的,先生,它的值必须全为零
  • 是的,字节数组的默认值全为零:stackoverflow.com/questions/22506274/…
  • 是的,密钥大小是 256 位
  • 这是我的钥匙 d651b30f-9c4c-4be0-83b8-2d7816256f64

标签: c# encryption cryptography aes


【解决方案1】:

两种简单的加解密方法兼容链接页面:

public static byte[] HexToBytes(string str, string separator = " ")
{
    if (str == null)
    {
        throw new ArgumentNullException();
    }

    if (separator == null)
    {
        separator = string.Empty;
    }

    if (str == string.Empty)
    {
        return new byte[0];
    }

    int stride = 2 + separator.Length;

    if ((str.Length + separator.Length) % stride != 0)
    {
        throw new FormatException();
    }

    var bytes = new byte[(str.Length + separator.Length) / stride];

    for (int i = 0, j = 0; i < str.Length; i += stride)
    {
        bytes[j] = byte.Parse(str.Substring(i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
        j++;

        // There is no separator at the end!
        if (j != bytes.Length && separator != string.Empty)
        {
            if (string.CompareOrdinal(str, i + 2, separator, 0, separator.Length) != 0)
            {
                throw new FormatException();
            }
        }
    }

    return bytes;
}

public static string BytesToHex(byte[] bytes, string separator = " ")
{
    if (bytes == null)
    {
        throw new ArgumentNullException();
    }

    if (separator == null)
    {
        separator = string.Empty;
    }

    if (bytes.Length == 0)
    {
        return string.Empty;
    }

    var sb = new StringBuilder((bytes.Length * (2 + separator.Length)) - 1);

    for (int i = 0; i < bytes.Length; i++)
    {
        if (i != 0)
        {
            sb.Append(separator);
        }

        sb.Append(bytes[i].ToString("x2"));
    }

    return sb.ToString();
}

public static byte[] SimpleEncrypt(SymmetricAlgorithm algorithm, CipherMode cipherMode, byte[] key, byte[] iv, byte[] bytes)
{
    algorithm.Mode = cipherMode;
    algorithm.Padding = PaddingMode.Zeros;
    algorithm.Key = key;
    algorithm.IV = iv;

    using (var encryptor = algorithm.CreateEncryptor())
    {
        return encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
    }
}

public static byte[] SimpleDecrypt(SymmetricAlgorithm algorithm, CipherMode cipherMode, byte[] key, byte[] iv, byte[] bytes)
{
    algorithm.Mode = cipherMode;
    algorithm.Padding = PaddingMode.Zeros;
    algorithm.Key = key;
    algorithm.IV = iv;

    using (var encryptor = algorithm.CreateDecryptor())
    {
        return encryptor.TransformFinalBlock(bytes, 0, bytes.Length);
    }
}

像这样使用它:

string text = "xxxyyy";
string key = "da 39 a3 ee 5e 6b 4b 0d 32 55 bf ef 95 60 18 90";
string iv = "f8 01 8b 76 7c db 80 9c ed 66 fd 63 e8 41 d6 04";

var encrypted = BytesToHex(
    SimpleEncrypt(
        new RijndaelManaged(), 
        CipherMode.CBC, 
        HexToBytes(key), 
        HexToBytes(iv),
        Encoding.UTF8.GetBytes(text)));

var decrypted = Encoding.UTF8.GetString(
    SimpleDecrypt(
        new RijndaelManaged(), 
        CipherMode.CBC, 
        HexToBytes(key), 
        HexToBytes(iv),
        HexToBytes(encrypted))).TrimEnd('\0');

请注意,该页面不适用于二进制数据,因为它使用Padding.Zeros。问题是明文由这些字节组成:

00 01 02 03 04 05 06 07 

转换为

00 01 02 03 04 05 06 07 00 00 00 00 00 00 00 00 

在加密之前,因为它被填充为 16 个字符。此操作无法撤消。您使用的PaddingMode.PKCS7 更好,因为它可以反转,但与该页面不兼容!如果您处理加密字符串,这不是问题,因为您可以执行TrimEnd('\0') 并删除多余的\0。您可以通过获取一个大小不能被 16 整除的小 zip 文件来检查它,通过页面对其进行加密(“输入类型”选择文件),然后按加密,然后按下载为二进制文件。然后按浏览,选择刚刚下载的文件,按解密,按下载为二进制文件。文件大小将与原始文件不同,但您仍然可以使用 zip 打开它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    相关资源
    最近更新 更多