加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

C#和OpenSSL:AES加密的输出不同

发布时间:2020-12-15 21:43:30 所属栏目:百科 来源:网络整理
导读:我正在尝试编写一个C#方法,它会像openssl二进制文件一样吐出相同的加密字符串(Base64),但是我很快就会把事情搞得一团糟. 很多终端输出和C#跟随……:P 我们将使用密码“123”加密字符串“a”的非常令人兴奋的例子. 首先是openssl,当我提供我的静态salt和密码
我正在尝试编写一个C#方法,它会像openssl二进制文件一样吐出相同的加密字符串(Base64),但是我很快就会把事情搞得一团糟.

很多终端输出和C#跟随……:P

我们将使用密码“123”加密字符串“a”的非常令人兴奋的例子.

首先是openssl,当我提供我的静态salt和密码时(这是理想运行命令的方式,也就是我希望我的C#输出匹配):

dev@magoo ~# echo -n a | openssl enc -aes-128-cbc -S cc77e2a591358a1c -pass pass:123 -a -p
salt=CC77E2A591358A1C
key=7B2AD689138A44AD32297BBAAA5B0EEE
iv =EC4F0416B2E9A9B2FEEF2E66FF982159
U2FsdGVkX1/Md+KlkTWKHOtnt1ftHSKyWiz6GxkBVck=

第二个是openssl,当我提供我的静态盐,以及从该盐派生的密钥和iv(来自第一个命令的输出的C P’d)但没有密码(因为即使文档说这将是一个不好的理念):

dev@magoo ~# echo -n a | openssl enc -aes-128-cbc -S cc77e2a591358a1c -K 7b2ad689138a44ad32297bbaaa5b0eee -iv ec4f0416b2e9a9b2feef2e66ff982159 -a -p
salt=E85778B7FFFFFFFF
key=7B2AD689138A44AD32297BBAAA5B0EEE
iv =EC4F0416B2E9A9B2FEEF2E66FF982159
62e3V+0dIrJaLPobGQFVyQ==

这让我很奇怪.将第一个命令中的“debug”输出(-p param)中的键值和iv值添加到同一个salt中,我会以某种方式获得不同的盐! (CC77E2A591358A1C vs E85778B7FFFFFFFF [这里的0xff的4个字节似乎很有趣]).

第三是我的申请的输出:

dev@magoo ~# mono aestest.exe "a" "123"
==> INPUT     : a
==> SECRET    : 123
==> SALT      : cc77e2a591358a1c
==> KEY       : 7b2ad689138a44ad32297bbaaa5b0eee
==> IV        : ec4f0416b2e9a9b2feef2e66ff982159
==> ENCRYPTED : 62e3V+0dIrJaLPobGQFVyQ==

因此,当我手动指定密钥和IV(然后以某种方式生成不同的盐)时,C#匹配openssl命令的输出,但这似乎是错误的.在我看来,C#应用程序的输出应该匹配第一组OpenSSL的输出,不应该吗?

C#代码:

public static string EncryptString(string plainText,string password)
{
  byte[] salt = Encryption.GetStaticSalt();
  byte[] key,iv;

  Encryption.DeriveKeyAndIV(password,salt,out key,out iv);

  var amAes = new AesManaged();
  amAes.Mode = CipherMode.CBC;
  amAes.KeySize = 128;
  amAes.BlockSize = 128;
  amAes.Key = key;
  amAes.IV = iv;

  var icTransformer = amAes.CreateEncryptor();
  var msTemp = new MemoryStream();

  var csEncrypt = new CryptoStream(msTemp,icTransformer,CryptoStreamMode.Write);
  var sw = new StreamWriter(csEncrypt);
  sw.Write(plainText);
  sw.Close();
  sw.Dispose();

  csEncrypt.Clear();
  csEncrypt.Dispose();

  byte[] bResult = msTemp.ToArray();
  string sResult = Convert.ToBase64String(bResult);

  if (System.Diagnostics.Debugger.IsAttached)
  {
    string debugDetails = "";
    debugDetails += "==> INPUT     : " + plainText + Environment.NewLine;
    debugDetails += "==> SECRET    : " + password + Environment.NewLine;
    debugDetails += "==> SALT      : " + Encryption.ByteArrayToHexString(salt) + Environment.NewLine;
    debugDetails += "==> KEY       : " + Encryption.ByteArrayToHexString(amAes.Key) + " (" + amAes.KeySize.ToString() + ")" + Environment.NewLine;
    debugDetails += "==> IV        : " + Encryption.ByteArrayToHexString(amAes.IV) + Environment.NewLine;
    debugDetails += "==> ENCRYPTED : " + sResult;
    Console.WriteLine(debugDetails);
  }

  return sResult;
}

private static string ByteArrayToHexString(byte[] bytes)
{
  StringBuilder sbHex = new StringBuilder();

  foreach (byte b in bytes)
    sbHex.AppendFormat("{0:x2}",b);

  return sbHex.ToString();
}

public static byte[] GetStaticSalt()
{
  // Just random bytes.
  return new byte[]
  {
    0xcc,0x77,0xe2,0xa5,0x91,0x35,0x8a,0x1c
  };
}

// largely hijacked from https://stackoverflow.com/a/8011654/97423
public static void DeriveKeyAndIV(string password,byte[] bSalt,out byte[] bKey,out byte[] bIV)
{
  int keyLen = 16;
  int ivLen = 16;

  byte[] bPassword = Encoding.UTF8.GetBytes(password);

  using (var md5Gen = MD5.Create())
  {
    List<byte> lstHashes = new List<byte>(keyLen + ivLen);
    byte[] currHash = new byte[0];

    int preHashLength = bPassword.Length + bSalt.Length;
    byte[] preHash = new byte[preHashLength];

    Buffer.BlockCopy(bPassword,preHash,bPassword.Length);
    Buffer.BlockCopy(bSalt,bPassword.Length,bSalt.Length);

    currHash = md5Gen.ComputeHash(preHash);
    lstHashes.AddRange(currHash);

    while (lstHashes.Count < (keyLen + ivLen))
    {
      preHashLength = currHash.Length + password.Length + bSalt.Length;
      preHash = new byte[preHashLength];

      Buffer.BlockCopy(currHash,currHash.Length);
      Buffer.BlockCopy(bPassword,currHash.Length,password.Length);
      Buffer.BlockCopy(bSalt,currHash.Length + password.Length,bSalt.Length);

      currHash = md5Gen.ComputeHash(preHash);
      lstHashes.AddRange(currHash);
    }

    bKey = new byte[keyLen];
    bIV = new byte[ivLen];

    lstHashes.CopyTo(0,bKey,keyLen);
    lstHashes.CopyTo(keyLen,bIV,ivLen);
  }
}

我在这里遗漏了一些非常明显的东西,还是这个更微妙的东西?我环顾四周,看过很多关于C#,OpenSSL和AES的内容,但没有关于这个特定问题的内容……那么,halp?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读