duan0714 2018-04-03 17:39
浏览 54
已采纳

C#SSO哈希迁移到PHP

I'm working on an SSO implementation in PHP that authenticates to a system written in C#. Here's some pseudo code to demonstrate:

$token = "MqsXexqpYRUNAHR_lHkPRic1g1BYhH6bFNVPagEkuaL8Mf80l_tOirhThQYIbfWYErgu4bDwl-7brVhXTWnJNQ2";
$id = "bob@company.com";
$ssokey = "7MpszrQpO95p7H";
$idAndKey = $id . $ssokey;
$salt = base64_decode(substr($token, 0, -1));
$hashed = hash_pbkdf2("sha256", $idAndKey, mb_convert_encoding($salt, 'UTF-16LE'), 1000, 24, false);
$data = base64_encode($hashed);

This outputs: NWZiMTBhZmNhNTlmYzMxMTEzMThhZmVl

Here's the C# version from the system with which I'm integrating:

var token = "MqsXexqpYRUNAHR_lHkPRic1g1BYhH6bFNVPagEkuaL8Mf80l_tOirhThQYIbfWYErgu4bDwl-7brVhXTWnJNQ2";
var id = "bob@company.com";
var ssokey = "7MpszrQpO95p7H";
string idAndKey = id + ssokey;
var salt = HttpServerUtility.UrlTokenDecode(token);
var pbkdf2 = new Rfc2898DeriveBytes(idAndKey, salt) {IterationCount = 1000};
var key = HttpServerUtility.UrlTokenEncode(pbkdf2.GetBytes(24)); 
Console.WriteLine(key.ToString());

This outputs: aE1k9-djZ66WbUATqdHbWyJzskMI5ABS0

I cannot figure out how to get my PHP code to do the same thing. I have a feeling it is in the salt generation.

I've tried to translate the C# HttpServerUtility.UrlTokenDecode function to PHP like so:

function UrlTokenDecode($token) {
    $numPadChars = substr($token, -1);

    // add the padded count to the end
    $salt = substr($token, 0, -1) . $numPadChars;

    // Transform the "-" to "+", and "*" to "/"
    $salt = str_replace('-', '+', str_replace('*', '/', $salt));

    // base64_decode
    $salt = base64_decode($salt);

    return $salt;
}

That didn't get me to where I needed to go. Halp!

This is for Absorb LMS. Documentation of their methods are here: https://support.absorblms.com/hc/en-us/articles/222446647-Incoming-Absorb-Single-Sign-On#Methods

Thanks!

  • 写回答

2条回答 默认 最新

  • dsdsm2016 2018-04-03 20:10
    关注

    I don't know php at all, but still can help I think. First, as stated in my comment, Rfc2898DeriveBytes in C# uses SHA1 as hash function, not SHA256, doesn't matter what your documentation says.

    Next, UrlTokenDecode (and Encode) is quite strange thing I rarely seen in practice. It converts regular base64 to "url safe" version as follows:

    • replaces '+' with '-'
    • replaces '/' with '_'
    • removes padding ('==' at the end) and appends length of removed padding as a number as last character (if there were no padding - it still appends "0"). This step doesn't make any sense to me, but it's how it works.

    So to replicate you need to base64_encode, replace, remove padding, and then add padding length as character. So if your base64 string ended with == - you remove that and add "2" at the end. If there was no padding - you add "0".

    So to decode that string you need to make back replacement, then remove last character and add that much '=' to the end as indicated by that character.

    So string

    MqsXexqpYRUNAHR_lHkPRic1g1BYhH6bFNVPagEkuaL8Mf80l_tOirhThQYIbfWYErgu4bDwl-7brVhXTWnJNQ2
    

    In normal base64 is MqsXexqpYRUNAHR/lHkPRic1g1BYhH6bFNVPagEkuaL8Mf80l/tOirhThQYIbfWYErgu4bDwl+7brVhXTWnJNQ==

    Then, I have no idea why you do that

    mb_convert_encoding($salt, 'UTF-16LE')
    

    Just remove it (though as I don't know php - there might be some reason you are doing that, but I just cannot imagine which, so take care).

    Then as other answer states - the last argument to hash_pbkdf2() should be true.

    After making this changes your code will work (I used token already converted to normal base64 string):

    $token = "MqsXexqpYRUNAHR/lHkPRic1g1BYhH6bFNVPagEkuaL8Mf80l/tOirhThQYIbfWYErgu4bDwl+7brVhXTWnJNQ==";
    $id = "bob@company.com";
    $ssokey = "7MpszrQpO95p7H";
    $idAndKey = $id . $ssokey;
    $salt = base64_decode($token);
    $hashed = hash_pbkdf2("sha1", $idAndKey, $salt, 1000, 24, true);
    $data = base64_encode($hashed);
    echo $data;
    

    produces expected answer (in normal base64 - you need to "url encode" it to get exact match).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下
  • ¥15 setInterval 页面闪烁,怎么解决
  • ¥15 如何让企业微信机器人实现消息汇总整合
  • ¥50 关于#ui#的问题:做yolov8的ui界面出现的问题
  • ¥15 如何用Python爬取各高校教师公开的教育和工作经历
  • ¥15 TLE9879QXA40 电机驱动
  • ¥20 对于工程问题的非线性数学模型进行线性化