WS-Security中PasswordDigest的工作算法

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

我成功使用SoapUI将数据发送到Oracle系统。 所以我能够拦截SoapUI的调用(将代理更改为127.0.0.1端口8888以使用Fiddler失败,因为它是通过SSL) – 拦截非常重要,因为这些值只能使用一次。 然后我可以获取nonce,创建时间戳和密码摘要将它们放入我的代码中(我只有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的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); } 

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

问题是现时。

我试图使用已经被Base64编码的nonce。 如果要使用“UIYifr1SPoNlrmmKGSVOug ==”forms的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; } 

我希望能帮到某人 – 它带给我很多挫折,试验和错误,搜索网页,以及一般的头/墙敲打。