【问题标题】:PHP use password and salt to get IV and Key alternative to C# Rfc2898DeriveBytes (AES256)PHP 使用密码和盐来获取 IV 和密钥替代 C# Rfc2898DeriveBytes (AES256)
【发布时间】:2016-06-09 01:51:33
【问题描述】:

我想从我存储的密码和盐中重新生成我的 IV 和密钥。 在我的 C# 程序中,我按以下方式进行操作:

//passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);

PHP 返回的代码是返回不同的 IV 和 Key:

<?php
include("enctest_inc.php");

$password = "mypassword";
$salt = "mysalthereitis";

$hasher = "SHA256";
$iterations = 1000;
$keysize = 256;
$ivsize = 128;

$out = pbkdf2($hasher, $password, base64_decode($salt), $iterations, ($keysize+$ivsize)/8, true);

// split key and IV
$key = substr($out, 0, $keysize/8);
$iv = substr($out, $ivsize/8);

// print for demonstration purposes
echo base64_encode($key);
echo "<br>";
echo base64_encode($iv);
echo '<br>';
echo '<br>';

echo 'KEY : LNY893Wa00onNQh4ignFdjaVkg6GdxomMZoR/axB+Mw='; //KEY FROM SSH PROGRAM WHICH IS THE RIGHT RETURN;
echo '<br>';
echo 'IV : //QxQj7PDMRE1YUVo+mJvQ==' //IV FROM SSH PROGRAM WHICH IS THE RIGHT RETURN;

我真的很想知道问题出在哪里或如何调试?

PHP 和 C# 中的设置相同:

PHP 代码:

$hasher = "SHA256";
$iterations = 1000;
$keysize = 256;
$ivsize = 128;

C#代码:

string random_string_pwd = "mypassword";
byte[] passwordBytes = Encoding.UTF8.GetBytes(random_string_pwd);

//var random_salt = new ClientTools();
//string random_string_salt = random_pwd.RndStrings(15);
string random_string_salt = "mysalthereitis";
byte[] Salt = Encoding.UTF8.GetBytes(random_string_salt);

// Hash the password with SHA256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
AES.KeySize = 256;
AES.BlockSize = 128;

var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);

【问题讨论】:

  • 你能给出一些输出字符串的例子吗?

标签: c# php cryptography pbkdf2


【解决方案1】:

在 PHP 中,你使用 Base64 解码盐,但它不是 base64 编码:
base64_decode($salt)

在 C# 中,您只需获取 salt 的字节:
byte[] Salt = Encoding.UTF8.GetBytes(random_string_salt);

在 PHP 中,您使用的是 SHA256
在 C# 中,您使用的是使用 SHA1 的 MSN Rfc2898DeriveBytes:
Rfc2898DeriveBytes Class 指定:使用基于 HMACSHA1 的伪随机数生成器。
在 password bytes 上使用 SHA256 并不能修复 MSN rfc2898derivebytes。这是一个 MSN 问题,因为它不允许指定 HAMC。

解决方案是将 PHP 更改为仅获取字符串字节作为数据,而不是尝试使用 Base64 解码非 Base64 编码的内容。

  1. 至少在每种语言中做同样的事情
  2. 如果您需要使用 MSN Rfc2898DeriveBytes,请将 PHP HMAC 更改为 SHA1。
  3. 不要对非 Base64 编码的字符串进行 Base64 解码,这通常会失败。事实上 Base64 解码肌腱炎”

【讨论】:

  • 感谢您抽出宝贵时间回答这个问题。没有注意到 base64_decode 错误,也谢谢你。 1. 我相信我在 C# 和 PHP 2 中都做了同样的事情。我将其更改为 sha1 并删除了 base64 解码,但结果仍然不同。有趣的是,我真的相信它用 passwordBytes = SHA256.Create().ComputeHash(passwordBytes); 更改为 sha256;
  • @AVGG 你删除那个passwordBytes = SHA256.Create().ComputeHash(passwordBytes); 步骤怎么样,因为那也不在 PHP 代码中。
  • 也将这一行从 $iv = substr($out, $ivsize/8);到 $iv = substr($out, $keysize/8, $ivsize/8);现在它的工作。但我想知道是否删除 SHA256.Create().ComputeHash(passwordBytes);不会创建弱安全性、容易破解的密码..
  • @AVGG 请务必使用完整的工作代码发布您自己的答案。不,如果 PBKDF2 的迭代次数很大,那么额外的 SHA-256 绝对不会提高安全性。
  • 谢谢,还有 2 个问题为什么我需要使用 sha1,我没有在 C# 源代码中看到任何地方指定它?以及 MSN rfc2898derivebytes zaph 所说的问题是什么。
猜你喜欢
  • 2017-08-02
  • 1970-01-01
  • 2014-07-15
  • 2015-01-07
  • 1970-01-01
  • 2012-06-08
  • 1970-01-01
  • 2016-12-02
  • 1970-01-01
相关资源
最近更新 更多