0

我正在尝试使用证明密钥验证请求是否来自 Office Online

我正在使用 nodejs 实现 wopi 主机,上面的链接中有代码示例使用 .NET 实现了证明密钥过程,因此我使用edge包能够使用 nodejs 运行 .NET 代码。

问题是代码运行良好,但它总是返回请求中的证明密钥无效,即使请求来自 wopi 客户端也是如此。

解释:有 3 个函数:
validateProofKey - 主函数 - 获取所有需要的参数来验证证明密钥,如果它们有效,则使用以下函数返回 bool:constructProofKeyTryProofkeyVerification
构造ProofKey - 声明 .NET 函数(来自示例代码的 constructProofKey),运行它并返回构造的证明
密钥 TryProofkeyVerification的结果- 声明 .NET 函数(来自 .NET 示例代码的 TryProofkeyVerification),运行它并返回布尔结果

编码 :

    static async validateProofKey(access_token: string, request_url: string, X_WOPI_TimeStamp: string, X_WOPI_Proof: string, X_WOPI_Proof_old: string): Promise<boolean> {

        //get public key provided in WOPI discovery:
        if (!wopiDiscovery) { wopiDiscovery = await this.getWopiDiscovery() }

        const public_Keys: iWopiDiscoveryProofKey = wopiDiscovery["wopi-discovery"]["proof-key"];
        const public__Key: string = public_Keys.value;
        const old_public_Key: string = public_Keys.oldvalue;


        this.printProofkeyArgs(access_token, request_url, X_WOPI_TimeStamp, X_WOPI_Proof, X_WOPI_Proof_old, public__Key, old_public_Key, modulus_b64, exp_b64);
        //1. Create the expected value of the proof headers.
        let expectedProofKey: Buffer = await this.constructProofKey(access_token, request_url, X_WOPI_TimeStamp);



        //2.Use the public key provided in WOPI discovery to decrypt the proof provided in the X-WOPI-Proof header.

        const verified: boolean = await this.TryProofkeyVerification(expectedProofKey, X_WOPI_Proof, public__Key) ||
            await this.TryProofkeyVerification(expectedProofKey, X_WOPI_Proof_old, public__Key) ||
            await this.TryProofkeyVerification(expectedProofKey, X_WOPI_Proof, old_public_Key)

        return verified;
    }

构造证明密钥

private static constructProofKey(access_token: string, request_url: string, X_WOPI_TimeStamp: string): Promise<Buffer> {
    return new Promise((resolve, reject) => {
        const proofParams = {
            access_token: access_token,
            request_url: request_url,
            X_WOPI_TimeStamp: X_WOPI_TimeStamp
        }

        const constructProofKey = edge.func(`
        using System.Threading.Tasks;
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Security.Cryptography;
        using System.Text;
        public class Startup
        {
            public async Task<object> Invoke(dynamic proofParams)
            {

                return Helper.constructProofKey(proofParams);
            }
        }

        static class Helper
        {
            public static byte[] constructProofKey(dynamic proofParams) 
            {

                // Encode values from headers into byte[]
                long timestamp = Convert.ToInt64(proofParams.X_WOPI_TimeStamp);
                var accessTokenBytes = Encoding.UTF8.GetBytes(proofParams.access_token);
                var hostUrlBytes = Encoding.UTF8.GetBytes(proofParams.request_url.ToUpperInvariant());
                var timeStampBytes = EncodeNumber(timestamp);
                      // prepare a list that will be used to combine all those arrays together
                      List < byte > expectedProof = new List<byte>(
                          4 + accessTokenBytes.Length +
                          4 + hostUrlBytes.Length +
                          4 + timeStampBytes.Length);

                expectedProof.AddRange(EncodeNumber(accessTokenBytes.Length));
                expectedProof.AddRange(accessTokenBytes);
                expectedProof.AddRange(EncodeNumber(hostUrlBytes.Length));
                expectedProof.AddRange(hostUrlBytes);
                expectedProof.AddRange(EncodeNumber(timeStampBytes.Length));
                expectedProof.AddRange(timeStampBytes);

                // create another byte[] from that list
                    byte[] expectedProofArray = expectedProof.ToArray();
                        return expectedProofArray;
            }
            private static byte[] EncodeNumber(long value)
            {
                return BitConverter.GetBytes(value).Reverse().ToArray();
            }
        }
        `)

        constructProofKey(proofParams, (error, result) => {
            if (error) {
                reject(error);
            }
            resolve(result);
        });
    })

}

TryProofkeyVerification

private static TryProofkeyVerification(expectedProofKey: Buffer, private_proofkey: string, public_proofkey: string): Promise<boolean> {
    return new Promise((resolve, reject) => {
        const proofParams = {
            expectedProofKey: expectedProofKey,
            private_proofkey: private_proofkey,
            public_proofkey: public_proofkey
        }
        //declare .NET code
        const TryVerification = edge.func(`
        using System.Threading.Tasks;
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Security.Cryptography;
        using System.Text;
        public class Startup
        {
            public async Task<object> Invoke(dynamic proofParams)
            {
                return Helper.TryVerification(proofParams);
            }
        }

        static class Helper
        {
            public static bool TryVerification(dynamic proofParams)
            {   

                byte[] expectedProofKey = (byte[])proofParams.expectedProofKey;

                 using(RSACryptoServiceProvider rsaAlg = new RSACryptoServiceProvider())
                 {

                    byte[] publicKey = Convert.FromBase64String(proofParams.public_proofkey);
                    byte[] signedProofBytes = Convert.FromBase64String(proofParams.private_proofkey);
                    try
                    {

                        rsaAlg.ImportCspBlob(publicKey);
                        return rsaAlg.VerifyData(expectedProofKey, "SHA256", signedProofBytes);

                    }
                    catch(FormatException)
                    {
                        Console.WriteLine("Format Exception");
                        return false;
                    }
                    catch(CryptographicException e)
                    {
                        Console.WriteLine("CryptographicException Exception");

                        return false;
                    }
                 }
            }
        }
        `);
        //Invoke .NET code
        TryVerification(proofParams, (error, result) => {
            if (error) {
                reject(error);
            }
            resolve(result);
        });
    })

}

注意 - 我已经将参数记录到控制台以确保参数在所有过程中正确传输

4

0 回答 0