使用 Rfc2898DeriveBytes 将 C# PBKDF2 转换为 PHP

2024-01-30

长话短说,我们在 .NET 中内置了一个会员系统,我们正在将其移植到 WordPress,并且需要复制 PBKDF2 加密,以便用户无需重置密码。

使用已知的散列密码,我可以使用以下代码轻松在 .NET 中复制此内容:

static void Main(string[] args)
{
  var isValid = CheckPassword("#0zEZcD7uNmv", "5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ");
}

public static int PBKDF2IterCount = 10000;
public static int PBKDF2SubkeyLength = 256 / 8; // 256 bits
public static int SaltSize = 128 / 8; // 128 bits

private static bool CheckPassword(string Password, string ExistingHashedPassword)
{
  byte[] saltAndPassword = Convert.FromBase64String(ExistingHashedPassword);
  byte[] salt = new byte[SaltSize];

  Array.Copy(saltAndPassword, 0, salt, 0, SaltSize);

  Console.WriteLine("--Salt--");
  Console.WriteLine(Convert.ToBase64String(salt));

  string hashedPassword = HashPassword(Password, salt);

  Console.WriteLine("--HashedPassword--");
  Console.WriteLine(hashedPassword);

  return hashedPassword == ExistingHashedPassword;
}

private static string HashPassword(string Password, byte[] salt)
{
  byte[] hash = new byte[PBKDF2SubkeyLength];
  using (var pbkdf2 = new Rfc2898DeriveBytes(Password, salt, PBKDF2IterCount))
  {
    hash = pbkdf2.GetBytes(PBKDF2SubkeyLength);
  }

  byte[] hashBytes = new byte[PBKDF2SubkeyLength + SaltSize];
  Array.Copy(salt, 0, hashBytes, 0, SaltSize);
  Array.Copy(hash, 0, hashBytes, SaltSize, PBKDF2SubkeyLength);

  string hashedPassword = Convert.ToBase64String(hashBytes);
  return hashedPassword;
}

控制台应用程序将生成以下内容:

--Salt--
5SyOX+Rbclzvvit3MEM2nA==
--HashedPassword--
5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ
--IsValid--
True

然而在 PHP 方面我无法得到相同的结果。到目前为止我的代码如下。

$mySalt = base64_decode('5SyOX+Rbclzvvit3MEM2nA==');
$dev = pbkdf2('sha1', '#0zEZcD7uNmv', $mySalt, 10000, 48, true);
$key = substr($dev, 0, 32); //Keylength: 32
$iv = substr($dev, 32, 16); // IV-length: 16

echo 'PHP<br/>';
echo 'PASS: '.base64_encode($dev).'<br/>';
echo 'SALT: '.base64_encode($iv).'<br/><br/>'; 

echo '.NET<br/>';
echo 'PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ<br/>';
echo 'SALT: 5SyOX+Rbclzvvit3MEM2nA==<br/><br/>'; 

function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false)
{
    $algorithm = strtolower($algorithm);
    if(!in_array($algorithm, hash_algos(), true))
        die('PBKDF2 ERROR: Invalid hash algorithm.');
    if($count <= 0 || $key_length <= 0)
        die('PBKDF2 ERROR: Invalid parameters.');

    $hash_length = strlen(hash($algorithm, "", true));
    $block_count = ceil($key_length / $hash_length);

    $output = "";
    for($i = 1; $i <= $block_count; $i++) {
        // $i encoded as 4 bytes, big endian.
        $last = $salt . pack("N", $i);
        // first iteration
        $last = $xorsum = hash_hmac($algorithm, $last, $password, true);
        // perform the other $count - 1 iterations
        for ($j = 1; $j < $count; $j++) {
            $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true));
        }
        $output .= $xorsum;
    }
    return substr($output, 0, $key_length);
}

结果是:

PHP
PASS: FFo9WjYztlOzuffOddN/Jbg6HBOUku+lxSUKvJuWCRCsYe+1Tgbb8Ob4FtxumMal
SALT: rGHvtU4G2/Dm+BbcbpjGpQ==

.NET
PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ
SALT: 5SyOX+Rbclzvvit3MEM2nA==

任何帮助,将不胜感激。


最终使用https://github.com/defuse/password-hashing https://github.com/defuse/password-hashing库,进行了一些细微的更改,与我正在导入的数据库中使用的哈希格式相匹配。

但我的主要问题是这些行,我试图从哈希中获取密钥。

$dev = pbkdf2('sha1', '#0zEZcD7uNmv', $mySalt, 10000, 48, true);
$key = substr($dev, 0, 32); //Keylength: 32
$iv = substr($dev, 32, 16); // IV-length: 16

将其更改为以下内容,以便创建一个 32 位长的哈希值,并将返回的哈希值加入到 salt 中,从而解决了该问题。

$dev = pbkdf2('sha1', '#0zEZcD7uNmv', $mySalt, 10000, 32, true);
echo 'PASS: '.base64_encode($mySalt.$dev).'<br />';

下面的输出现在与 .NET 匹配:

PASS: 5SyOX+Rbclzvvit3MEM2nBRaPVo2M7ZTs7n3znXTfyW4OhwTlJLvpcUlCryblgkQ
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Rfc2898DeriveBytes 将 C# PBKDF2 转换为 PHP 的相关文章

随机推荐

  • 如何在UITableView后面添加MKMapKit?就像 svpply 一样

    这样 cell就可以覆盖MKMapView了 当表格向下滚动时 MKMapView 可以被触摸 如何 特别感谢 1 为表格视图添加标题视图 320px高度 背景色清晰 2 将MKMapView放在UITableView下 3 覆盖表视图的h
  • Eclipse hibernate pojo 生成包括外键

    我一直在遵循一个关于使用 hibernate 从 mysql 数据库生成 pojo 的优秀指南 人们可以在这里找到指南以供参考 使用 hibernate 生成 pojo http www javacodegeeks com 2013 10
  • 特定 std::bind 返回的数据类型到底是什么?

    首先我不得不说我必须知道 std bind 返回的数据类型 我有一个结构体定义为 typedef struct UINT ID CString NAME boost any Func auto doesn t work here CALLB
  • swagger-ui.html 400 错误请求

    我已将 swagger 集成到我的 Spring Boot 项目中 所有 swagger 端点都工作正常 但是 product swagger ui html给出 400 错误 经过一些调试 我发现两个端点之间存在冲突 在我的 applic
  • Android Media Codec 视频解码

    这是我的第一个问题 如果我遗漏了什么 请告诉我 使用 Android API 16 的新媒体编解码器实现来尝试解码视频 以便我可以发送要作为纹理应用的帧 纹理部分已经完成 所以我在堆栈外的一些帮助下想出了以下代码 但在runOutputBu
  • 如何在python中修改Yolo .txt文件的值

    我想修改包含 txt 文件的文件夹 txt 文件如下所示 3 0 695312 0 523958 0 068750 0 052083 3 0 846875 0 757292 0 071875 0 031250 3 0 830469 0 71
  • 如何检查 UIWebView 是否为空

    我需要检查加载完成后的网络视图是否有任何内容 我的要求很简单 它是我页面底部的一个小网络视图条 就像广告一样 I call NSURLRequest request NSURLRequest requestWithURL adURL gWe
  • 这里的地图导航 - 留下的痕迹

    我使用 Here 地图 sdk 作为导航解决方案 到目前为止一切都很好 除了有点不方便 在导航模式下 我看到计算的路线如何在 3D 模式下围绕当前位置渲染 以及当前位置如何正确显示在地图上 在onPositionUpdated打回来 但是
  • 让 Kinect SDK 在 C++ 中与 Visual Studio 2010 配合使用

    我一直在遵循微软为使用 c 设置 Kinect SDK 所做的指南 他们创建的步骤如下 在源代码中包含 windows h 要使用 NUI API 请包含 MSR NuiApi h 位置 Program Files Microsoft Re
  • Firefox DOM解析器问题

    由于某种原因 DOMParser 为每个换行符添加了一些额外的 text 元素 n对于这个网址 http rt com Root rss http rt com Root rss 以及我尝试过的许多其他 RSS 我检查了 cnn bbc f
  • React 在没有构造函数的情况下定义状态 [重复]

    这个问题在这里已经有答案了 我见过一些 React 开发人员在没有构造函数的情况下定义状态 我喜欢这样简化代码 但是这样做安全吗 class Dog extends React Component state sound Woof retu
  • 我可以在 Play! 中使用什么 SBT 构建设置? 2 框架将包含类路径上源树中的特定资源

    我想在构建中添加一个设置 该设置将从 src 树中的某个位置复制特定文件 以便它们在开发和生产模式下的类路径上可用 我不想把它们放在public文件夹 因为我不希望它们可供下载 我不想把它们放在conf文件夹 因为我想保持配置文件的干净 例
  • 查找networkx中满足特定条件的边

    我有一个网络x有向图 http networkx github io documentation latest reference classes digraph html具有节点上的属性 并且我想找到特定节点属性不同的所有边 有没有办法自
  • MongoDB 中的批量更新/更新插入?

    是否可以在 MongoDB 中进行批量更新 更新插入 而不是插入 如果是 请指出与此相关的任何文档 Thanks 您可以使用命令行程序蒙戈进口公司它应该在你的 MongoDB bin 目录中 您需要考虑使用两个选项upsert upsert
  • 具有多线程的实体框架事务

    我有一个运行多个线程的应用程序 线程不共享 ObjectContext 每个线程都有自己的 我知道它们不是线程安全的 然而 线程都在共享事务下运行 原始线程创建一个 TransactionScope 它生成的每个线程都使用主线程上的 Tra
  • 创建 SKSpriteNode 子类的子类

    假设我想创建一堆不同类型的宇宙飞船 我想设置一个基本的宇宙飞船类 我可以用它来创建其他有细微差别的宇宙飞船 我的基类看起来像这样 BaseSpaceship h interface SpaceshipNode SKSpriteNode pr
  • 致命错误:在展开可选值时意外发现 nil [重复]

    这个问题在这里已经有答案了 我当时用的是UICollectionView在 Swift 中 但当我尝试更改单元格标签的文本时 我得到了 func collectionView collectionView UICollectionView
  • VB6中Property Set和Property Let有什么区别?

    我刚刚创建了几个Property Set方法 但它们没有编译 当我将它们更改为Property Let 一切都很好 此后我研究了文档以找出两者之间的区别Property Set and Property Let 但必须承认自己并不明智 有什
  • 如何在初始开发过程中使用 Clojure 库的本地存储库?

    我有一个关于开发 Clojure 库的问题 该问题在库开发和分发的建议工作流程中没有得到解答 如下所述 http clojure doc org articles ecosystem libraries authoring html htt
  • 使用 Rfc2898DeriveBytes 将 C# PBKDF2 转换为 PHP

    长话短说 我们在 NET 中内置了一个会员系统 我们正在将其移植到 WordPress 并且需要复制 PBKDF2 加密 以便用户无需重置密码 使用已知的散列密码 我可以使用以下代码轻松在 NET 中复制此内容 static void Ma