【问题标题】:Working algorithm for PasswordDigest in WS-SecurityWS-Security 中 PasswordDigest 的工作算法
【发布时间】:2013-10-26 14:36:48
【问题描述】:

我在使用 WS-Security 时遇到问题,并创建了正确的随机数和密码摘要。

我成功地使用 SoapUI 将数据发送到 Oracle 系统。所以我能够拦截 SoapUI 的调用(将代理更改为 127.0.0.1 端口 8888 以使用 Fiddler,因为它通过 SSL 失败) - 拦截很重要,因为这些值只能使用一次。然后我可以抓取随机数、创建的时间戳和密码摘要将它们放入我的代码中(我只有 30 秒的时间来执行此操作,因为这些值不会持续!)并且我获得了成功。

所以我知道这没什么——只是密码摘要。

我使用的值如下:

Nonce: UIYifr1SPoNlrmmKGSVOug==
Created Timestamp: 2009-12-03T16:14:49Z
Password: test8
Required Password Digest: yf2yatQzoaNaC8BflCMatVch/B8=

我知道创建摘要的算法是:

Password_Digest = Base64 ( SHA-1 ( nonce + created + password ) )

使用以下代码(来自Rick Strahl's post

protected string GetSHA1String(string phrase)
{
    SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider();
    byte[] hashedDataBytes = sha1Hasher.ComputeHash(Encoding.UTF8.GetBytes(phrase));
    return Convert.ToBase64String(hashedDataBytes);
}

我明白了:

GetSHA1String("UIYifr1SPoNlrmmKGSVOug==" + "2009-12-03T16:14:49Z" + "test8") = "YoQKI3ERlMDGEXHlztIelsgL50M="

我尝试了各种 SHA1 方法,都返回相同的结果(我猜这是一件好事!):

SHA1 sha1 = SHA1.Create();
SHA1 sha1 = SHA1Managed.Create();

// Bouncy Castle:
protected string GetSHA1usingBouncyCastle(string phrase)
{
    IDigest digest = new Sha1Digest();
    byte[] resBuf = new byte[digest.GetDigestSize()];
    byte[] bytes = Encoding.UTF8.GetBytes(phrase);
    digest.BlockUpdate(bytes, 0, bytes.Length);
    digest.DoFinal(resBuf, 0);
    return Convert.ToBase64String(resBuf);
}

关于如何获得正确哈希的任何想法?

【问题讨论】:

    标签: c# xml soapui sha1 ws-security


    【解决方案1】:

    问题是随机数。

    我尝试使用已经过 Base64 编码的随机数。如果您想使用“UIYifr1SPoNlrmmKGSVOug==”形式的 Nonce,则需要对其进行解码。

    Convert.FromBase64String("UIYifr1SPoNlrmmKGSVOug==") 这是一个字节数组。

    所以我们需要一个新方法:

    public string CreatePasswordDigest(byte[] nonce, string createdTime, string password)
    {
        // combine three byte arrays into one
        byte[] time = Encoding.UTF8.GetBytes(createdTime);
        byte[] pwd = Encoding.UTF8.GetBytes(password);
        byte[] operand = new byte[nonce.Length + time.Length + pwd.Length];
        Array.Copy(nonce, operand, nonce.Length);
        Array.Copy(time, 0, operand, nonce.Length, time.Length);
        Array.Copy(pwd, 0, operand, nonce.Length + time.Length, pwd.Length);
    
        // create the hash
        var sha1Hasher = new SHA1CryptoServiceProvider();
        byte[] hashedDataBytes = sha1Hasher.ComputeHash(operand);
        return Convert.ToBase64String(hashedDataBytes);
    }
    
    CreatePasswordDigest(Convert.FromBase64String("UIYifr1SPoNlrmmKGSVOug=="), "2009-12-03T16:14:49Z", "test8")
    

    根据我们的需要返回 yf2yatQzoaNaC8BflCMatVch/B8=。

    请记住在摘要中使用与您在 XML 中输入相同的 createdTime,这听起来很明显,但有些人在他们的时间戳中包含毫秒,有些则没有 - 没关系,它只需要保持一致.

    UsernameToken XML 中的 Id 字段也无关紧要 - 它不需要更改。

    如果您不想像 Rick 那样使用 GUID,这里有一种创建像上面那样的 Nonce 的方法:

    private byte[] CreateNonce()
    {
        var Rand = new RNGCryptoServiceProvider();
        //make random octets
        byte[] buf = new byte[0x10];
        Rand.GetBytes(buf);
        return buf;
    }
    

    我希望对某人有所帮助 - 我经历了很多挫折、反复试验、搜索网页以及一般的头/墙碰撞。

    【讨论】:

    • 我在做同样的事情,却没有意识到。这个答案为我节省了几个小时。很好的答案。
    猜你喜欢
    • 2014-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2023-03-20
    • 2011-03-07
    • 2012-03-11
    • 2019-04-16
    相关资源
    最近更新 更多