【问题标题】:Digest calculation of signature fails on Windows, Java 1.8签名的摘要计算在 Windows、Java 1.8 上失败
【发布时间】: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 以在运行时获得“调试信息”。真的是一个奇怪的老式和丑陋的东西...... 但结果很有趣!

  1. 从未设置 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


【解决方案1】:

经过一些测试,结果发现还有一个额外的编码问题...... :-(((

原始签名文件采用 UTF-8 格式,但由于 Windows 使用 ISO-xyz_whatever 它不匹配。

第一个解决方法是将JVM的编码放在调用jar的脚本中,所以:

java -Dfile.encoding=UTF8 <programm>.jar

【讨论】:

  • 更好的解决方法是在将文件中的字节转换为字符时指定编码。如果没有完整的代码,我不知道你哪里出错了,但这通常发生在 InputStreamReader 中。
  • 如果这解决了问题,那么您应该通过明确指定读取文件的编码来修复您的应用程序,而不是覆盖默认文件编码的权宜之计。
  • 意识到编码问题,我们改编了10多年前的文件读取......关键是更新第三方组件时出现了错误。 wss4j 从 1.5.8 到 2.1.9; xmlsec 作为新的依赖项。那里一定有一些非常隐藏的错误。另一方面,如果我在 Windows 机器上运行实际上使用相同类的 web 服务项目,则没有问题......(!?!?!?)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多