簡體   English   中英

使用 C# 中的 OpenSSL 使用 PBKDF2 解密 AES-256-CBC

[英]Decrypt AES-256-CBC with PBKDF2 from OpenSSL in C#

我需要解密一個用 OpenSSL 加密的字符串,如下所示:

openssl rand -out secret.key -hex 192
openssl aes-256-cbc -pbkdf2 -in file_to_encrypt -out encrypted_file -pass file:secret.key

我不能讓它在 C# 中工作

  public void OnStartup()
  {
    using var rsa = RSA.Create();
    var privateKeyContent = File.ReadAllText("/cert/customer.pem");
    rsa.ImportFromPem(privateKeyContent);
    var encryptedSecret = File.ReadAllBytes("license/secret.key.enc");
    var decrypted = rsa.Decrypt(encryptedSecret, RSAEncryptionPadding.Pkcs1);
    _logger.LogInformation(Encoding.UTF8.GetString(decrypted));
    var bytes = File.ReadAllBytes("license/license.json.enc");
    var license = DecryptAesCbc(bytes, decrypted);
    _logger.LogInformation(license);
  }

  public string DecryptAesCbc(byte[] cipheredData, byte[] passphrase)
  {
    string decrypted = null;
    using (var ms = new MemoryStream(cipheredData))
    {
      // Get salt
      var salt = new byte[8];
      ms.Seek(8, SeekOrigin.Begin);
      ms.Read(salt, 0, 8);
      _logger.LogInformation("Salt: {Salt}", string.Concat(Array.ConvertAll(salt, x => x.ToString("X2"))));

      // Derive key and IV
      var pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, 10000, HashAlgorithmName.SHA256);
      byte[] key = pbkdf2.GetBytes(32);
      byte[] iv = pbkdf2.GetBytes(16);
      _logger.LogInformation("Key: {Key}", string.Concat(Array.ConvertAll(key, x => x.ToString("X2"))));
      _logger.LogInformation("IV: {IV}", string.Concat(Array.ConvertAll(iv, x => x.ToString("X2"))));

      using Aes aes = Aes.Create();
      aes.KeySize = 256;
      aes.Padding = PaddingMode.PKCS7;
      aes.Mode = CipherMode.CBC;
      aes.Key = key;
      aes.IV = iv;

      // Decrypt
      ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
                using var cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read);
      using var sr = new StreamReader(cs, Encoding.UTF8);
      decrypted = sr.ReadToEnd();
      }
      return decrypted;
    }

使用此代碼,我在decrypted = sr.ReadToEnd()處收到異常Padding is invalid and cannot be removed.

秘密通過RSA加密並解密,結果與解密文件相同,所以這應該可以工作。

我非常感謝您的幫助

解決方案:

public static string DecryptLicense(byte[] cipherData, byte[] passphrase)
{
  string decrypted = null;
  using (var ms = new MemoryStream(cipherData))
  {
    // Get salt
    var salt = new byte[8];
    ms.Seek(8, SeekOrigin.Begin);
    ms.Read(salt, 0, 8);

    // Derive key and IV
    var pbkdf2 = new Rfc2898DeriveBytes(passphrase, salt, 10000, HashAlgorithmName.SHA256);
    byte[] key = pbkdf2.GetBytes(32);
    byte[] iv = pbkdf2.GetBytes(16);

    using Aes aes = Aes.Create();
    aes.KeySize = 256;
    aes.Padding = PaddingMode.PKCS7;
    aes.Mode = CipherMode.CBC;
    aes.Key = key;
    aes.IV = iv;

    // Decrypt
    ICryptoTransform decipher = aes.CreateDecryptor(aes.Key, aes.IV);
    using var cs = new CryptoStream(ms, decipher, CryptoStreamMode.Read);
    using var sr = new StreamReader(cs, Encoding.UTF8);
    decrypted = sr.ReadToEnd();
  }

  return decrypted;
}

並使用以下命令生成密碼: openssl rand 192 | openssl enc -A -base64 -out secret.key openssl rand 192 | openssl enc -A -base64 -out secret.key

問題是一個用換行符生成的密碼,openssl 只使用密碼文件的第一行,但 C# 使用整個文件來派生密鑰。 為了防止這種情況,我現在生成一個沒有換行符的文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM