简体   繁体   English

WS-Security中PasswordDigest的工作算法

[英]Working algorithm for PasswordDigest in WS-Security

I'm having trouble with WS-Security, and creating a nonce and password digest that is correct. 我遇到了WS-Security的问题,并创建了一个正确的随机数和密码摘要。

I am successfully using SoapUI to send data to an Oracle system. 我成功使用SoapUI将数据发送到Oracle系统。 So I'm able to intercept SoapUI's call (change proxy to 127.0.0.1 port 8888 to use Fiddler where it fails because it's over SSL) - intercepting is important because these values can only be used once. 所以我能够拦截SoapUI的调用(将代理更改为127.0.0.1端口8888以使用Fiddler失败,因为它是通过SSL) - 拦截非常重要,因为这些值只能使用一次。 I can then grab the nonce, created timestamp and password digest put them into my code (I've only got 30 seconds to do this as the values don't last!) and I get a success. 然后我可以抓取nonce,创建时间戳和密码摘要将它们放入我的代码中(我只有30秒才能完成这个,因为值不会持续!)并且我获得了成功。

So I know it's nothing else - just the Password Digest. 所以我知道它不是别的 - 只是密码摘要。

The values I use are the following: 我使用的值如下:

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

I know the algorithm for creating the Digest is: 我知道创建摘要的算法是:

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

using the following code (from Rick Strahl's post ) 使用以下代码(来自Rick Strahl的帖子

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

I get: 我明白了:

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

I have tried various SHA1 methods, all return the same results (which is a good thing I guess!): 我尝试了各种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);
}

Any ideas on how to get the correct hash? 关于如何获得正确哈希的任何想法?

The problem was the nonce. 问题是随机数。

I was trying to use a nonce that had already been Base64 encoded. 我试图使用已经被Base64编码的nonce。 If you want to use a Nonce that is in the form "UIYifr1SPoNlrmmKGSVOug==" then you need to decode it. 如果要使用“UIYifr1SPoNlrmmKGSVOug ==”形式的Nonce,则需要对其进行解码。

Convert.FromBase64String("UIYifr1SPoNlrmmKGSVOug==") which is a byte array. Convert.FromBase64String("UIYifr1SPoNlrmmKGSVOug==")这是一个字节数组。

So we need a new method: 所以我们需要一种新方法:

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")

which returns yf2yatQzoaNaC8BflCMatVch/B8= as we want. 返回yf2yatQzoaNaC8BflCMatVch / B8 =我们想要的。

Remember to use the same createdTime in the digest as you put in the XML, this might sound obvious, but some people include milliseconds on their timestamps and some don't - it doesn't matter, it just needs to be consistent. 请记住在XML中使用相同的createdTime,这可能听起来很明显,但是有些人在时间戳上包含毫秒而有些人没有 - 这没关系,只需要保持一致。

Also the Id field in the UsernameToken XML doesn't matter - it doesn't need to change. UsernameToken XML中的Id字段也无关紧要 - 它不需要更改。

Here's a method to create a Nonce like the one above, if you don't want to use GUIDs like Rick uses: 如果您不想使用Rick使用的GUID,这里有一个创建上述Nonce的方法:

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

I hope that helps someone - it took me lots of frustration, trial and error, searching web pages, and general head/wall banging. 我希望能帮到某人 - 它带给我很多挫折,试验和错误,搜索网页,以及一般的头/墙敲打。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM