【发布时间】:2017-06-01 08:17:16
【问题描述】:
要做的工作:
我有一个签名的 SOAP 请求,我必须检查签名是否正常。 SOAP 消息的时间戳不重要。
到目前为止我的解决方案:
我创建了一个 org.apache.wss4j.dom.engine.WSSecurityEngine 的子类,其中在方法 processSecurityHeader 中检查 TimestampProcessor 是出于考虑:
public class SignatureSecurityEngine extends WSSecurityEngine {
...
public WSHandlerResult processSecurityHeader(Element securityHeader, RequestData requestData) throws org.apache.wss4j.common.ext.WSSecurityException {
...
Processor p = cfg.getProcessor(el);
if (p != null) {
try {
results = p.handleToken((Element) node, requestData, wsDocInfo);
} catch (Exception e){
if (p instanceof TimestampProcessor) {
// it's okay if timestamp is too old
} else {
throw e;
}
}
}
...
事实上,它只是 WSSecurityEngine 的一个副本,为时间戳处理器添加了 try/catch。
我使用旧版本的 wss4j 和 xmlsec 这工作正常。
组件版本升级后,出现以下奇怪问题:
在 org.apache.jcp.xml.dsig.internal.dom.DOMReference.validate(...) 中计算签名摘要失败 如果:
- 程序在 Windows (JRE) 上运行
- 我在 Windows (JDK) 上调试
- 我在 Linux (JDK) 上调试
但是:
如果程序在 Linux (JRE) 上运行,一切正常!
对于both(Windows/Linux),配置为:
- wss4j 2.1.9
- xmlsec 2.0.8
- Java 版本:1.8.0_131(内部版本 1.8.0_131-b11)
观察:
计算的摘要似乎还有一个标准值 ( 2jmj7l5rSw0yVb/vlWAYkK/YBwk= )。
有什么想法吗?
其他事实(2017-06-13):
在 Maartens 发表评论之后,我(重新)编写了一些类(实际上是复制和粘贴)并添加了一些 System.out.println 以在运行时获得“调试信息”。真的是一个奇怪的老式和丑陋的东西...... 但结果很有趣!
- 从未设置 MessageDigest 流。因此,这解释了 2jmj7l5rSw0yVb/vlWAYkK/YBwk=,它是带有 SHA-1 的空字符串的摘要(感谢 Maarten!)
然后我设法修复了 - 所以现在在我复制的“调试”类中设置了流。
结果:如果我现在用我的 IDE 调试,计算功能!
但是:如果我在运行时运行检查失败 :-(((原因:计算值不等于预期值。
进一步的观察表明:ev。错误的计算取决于必须计算摘要的数据长度 (!?!?!?)。
让我们看看我的日志:
*** Digest for Timestamp
VGDOMReference.validate -> transform:
Expected digest: LxfIdEUVsbyLaevptByfIf2L0PA=
Actual digest: LxfIdEUVsbyLaevptByfIf2L0PA=
Reference[#Timestamp-31b20235-a1e2-4ed0-9658-67611572108e]
*** Digest for Body
Expected digest: Yv+zLpkog+xzAdMlSjoIaZntZLs=
Actual digest: sj2Gb0GEyjWuxoCmnBzDY266aG8=
Reference[#Body-c9761a98-46bb-4175-8f8b-bfa9b5c75509]
如您所见,时间戳的计算是正确的。但是用于身体的那个是错误的。
也许是一些没有完全写入的流缓冲区?
【问题讨论】:
-
异常/堆栈跟踪?可重现的测试用例,带配置?
-
注意 DOMReference.validate(...):你有 this.digestValue {taken from the file} 和 this.calcDigestValue {newly computed}。行 this.validationStatus = Arrays.equals(this.digestValue, this.calcDigestValue);验证状态的结果为假。您使用哪个肥皂签名文件似乎是独立的,calcDigestValue 的结果始终是 2jmj7l5rSw0yVb/vlWAYkK/YBwk=
-
您必须确保在与 XML 签名验证有关的任何场景中引用/命名空间都是正确的。我必须显式添加检查,因为 XML digsig 使用了路径,而 SOAP 使用了元素的 id(或者相反?)。如果每次引用可能关闭时您都获得相同的哈希值。请注意,您的摘要值是空字符串的 SHA-1 哈希。
-
现在可能是您最后的担心了,但使用 SHA-1 进行签名生成/验证当然不再是个好主意了。
-
SHA-1 真的是我最不担心的事了... - 不过:如果 check 签名,你必须拿它已经完成的那个!
标签: java windows signature digest