WS-Security 中 PasswordDigest 的工作算法
本文关键字:工作 算法 PasswordDigest WS-Security | 更新日期: 2023-09-27 18:35:47
我在使用 WS-Security 时遇到了问题,并创建了一个正确的随机数和密码摘要。
我成功地使用SoapUI将数据发送到Oracle系统。所以我能够拦截 SoapUI 的调用(将代理更改为 127.0.0.1 端口 8888 以在因 SSL 而失败时使用 Fiddler) - 拦截很重要,因为这些值只能使用一次。然后,我可以获取随机数,创建的时间戳和密码摘要将它们放入我的代码中(我只有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 Stralh 的帖子)
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 编码的随机数。如果你想使用"UIYifr1SPoNlrmmKGSVOug=="形式的随机数,那么你需要解码它。
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,这听起来可能很明显,但有些人在时间戳中包含毫秒,有些人则不包含 - 没关系,它只需要保持一致。
此外,用户名令牌XML中的Id字段无关紧要 - 它不需要更改。
下面是创建上述 Nonce 的方法,如果您不想像 Rick 那样使用 GUID:
private byte[] CreateNonce()
{
var Rand = new RNGCryptoServiceProvider();
//make random octets
byte[] buf = new byte[0x10];
Rand.GetBytes(buf);
return buf;
}
我希望这对某人有所帮助 - 这让我经历了很多挫折、反复试验、搜索网页和一般的头部/墙壁撞击。