1

证明密钥验证器总是返回无效的证明密钥。

我指的是https://github.com/Microsoft/Office-Online-Test-Tools-and-Documentation/blob/master/samples/java/ProofKeyTester.java

@GET
@Path("/{file_id}")
@Produces(APPLICATION_JSON)
public Response checkFileInfo(@PathParam("file_id") String fileId, @QueryParam("access_token") String accessToken, @Context HttpHeaders httpHeaders, @Context HttpServletRequest request) {
    try {
        String proof = httpHeaders.getRequestHeader("X-WOPI-Proof") != null ? httpHeaders.getRequestHeader("X-WOPI-Proof").get(0) : null;
        String proofOld = httpHeaders.getRequestHeader("X-WOPI-ProofOld") != null ? httpHeaders.getRequestHeader("X-WOPI-ProofOld").get(0) : null;
        String wopiTimeStamp = httpHeaders.getRequestHeader("X-WOPI-TimeStamp") != null ? httpHeaders.getRequestHeader("X-WOPI-TimeStamp").get(0) : null;
        String urlSrc = request.getRequestURL().toString();
        String replacedStr = HTTP.matcher(urlSrc).replaceAll("https");
        validateProofKey(proof, proofOld, wopiTimeStamp, replacedStr, accessToken);

}

private void validateProofKey(String proof, String proofOld, String timeStamp, String urlSrc, String accessToken) throws Exception {
    LOGGER.info("verifying proof key");
    ProofKeyManager proofKeyManager = getBean(ProofKeyManager.class);
    String url = urlSrc + (urlSrc.contains(".wopitest") ? "?TESTCATEGORY=OFFICEONLINE&ACCESS_TOKEN=" : "?ACCESS_TOKEN=") + accessToken;
    byte[] expectedProof = proofKeyManager.getExpectedProofBytes(url, accessToken, timeStamp);
    WopiDiscovery wopiDiscovery = getBean(WopiDiscoveryProcessService.class).getWopiDiscoveryData();
    String modulus = wopiDiscovery.getProofKey().getModulus();
    String exponent = wopiDiscovery.getProofKey().getExponent();
    String oldModulus = wopiDiscovery.getProofKey().getOldmodulus();
    String oldExponent = wopiDiscovery.getProofKey().getOldexponent();
    boolean validScenario = proofKeyManager.verifyProofKey(modulus, exponent, proof, expectedProof);
    boolean validScenarioWithOld = proofKeyManager.verifyProofKey(modulus, exponent, proofOld, expectedProof);
    boolean oldPK = proofKeyManager.verifyProofKey(oldModulus, oldExponent, proof, expectedProof);
    if (proofKeyManager.verifyProofKey(modulus, exponent, proof, expectedProof) || proofKeyManager.verifyProofKey(modulus, exponent, proofOld, expectedProof) || proofKeyManager.verifyProofKey(oldModulus, oldExponent, proof, expectedProof)) {
        LOGGER.info("proof key is valid");
    } else {
        LOGGER.error("proof key is not valid");
        //throw new Exception("Invalid proof key");
    }

}

如果请求是由 Office Online 生成的,它应该记录“证明密钥有效”。但即使在有效的情况下,它也会记录“证明密钥无效”。

4

1 回答 1

0

我不能直接回答这个问题,但我最近在 PHP 中实现证明密钥验证时遇到了同样的问题。由于未正确阅读文档或文档未指定某些内容,我做错了很多事情。最后通过将链接的 github 存储库中的示例测试翻译成 PHP 来解决它。我遇到的两个主要问题是:

  1. 从模数和指数创建公钥 发现过程中给定的模数和指数是 base64 编码的二进制,表示一个很大的十进制数。你需要base64解码,然后转换成十六进制,再转换成十进制。根据您的语言/系统,您可能需要一些小数点周围的包装库,因为它可能太大而无法放入intor double

  2. 编码预期证明的数字您需要获取访问令牌和 url 的长度,然后对它们进行编码。我为此使用了php函数pack('J', $number)

您还需要对我使用的时间戳进行编码pack('N', $number),计算它的长度,然后使用上述方法对长度进行编码。

最后,这是很多试验结束错误。我克隆了示例存储库并运行了python 验证测试,一路打印出不同的值(例如,模数、指数、访问令牌的长度、url、时间戳以及它们编码的内容)并将其与我的代码输出的内容进行比较.

不是一个完美的答案,但这是一个艰难的过程,因此希望可以为人们指明正确的方向。

于 2020-12-16T02:08:10.463 回答