You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用pkijs在TypeScript中解码验证OCSP响应以校验证书

OCSP请求解码问题及解决方案

目标

我们需要判断证书是否有效或已被吊销,为此使用pkijs包发起OCSP请求,发送与证书相关的关键信息,比如hashAlgorithm、issuerNameHash、issuerKeyHash等(代码见下文)。

问题

成功获取OCSP响应后,响应内容大部分是编码状态,难以直接解读,只能看到少量证书类型相关元素,无法提取更多可读的证书状态信息。

尝试操作

我们调用用于校验证书状态的函数,测试时使用以下硬编码参数:

await checkCertificateWithOcsp({
    hashAlgorithm: 'SHA256',
    issuerKeyHash: '7870177724f6234dccf87a8a43c84551533f831257519f90b12bb8eecae0',
    issuerNameHash: 'cbe609c06ec9bd944a5d8cf94aee2979d4396fe00f68c6d215e233766514a1',
    responderURL: 'https://7kravoouwj.execute-api.eu-west-1.amazonaws.com/test/OCSP-Responder',
    serialNumber: '2',
});

对应的函数实现代码:

import * as asn1js from 'asn1js';

import { AlgorithmIdentifier, CertID, Extension, OCSPRequest, OCSPResponse, Request } from 'pkijs';
import Axios from 'axios';

public static async checkCertificateWithOcsp(ocspRequest: OCSPRequestData) {
    // 将十六进制字符串转换为字节数组(Uint8Array)
    const issuerNameHashBytes = new Uint8Array(ocspRequest.issuerNameHash.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
    const issuerKeyHashBytes = new Uint8Array(ocspRequest.issuerKeyHash.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
    const serialNumberBytes = new Uint8Array(ocspRequest.serialNumber.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));

    // 1. 使用PKI.js构建OCSP请求
    const request = new OCSPRequest();
    request.tbsRequest.requestList[0] = new Request();
    request.tbsRequest.requestExtensions = [
      new Extension({
        extnID: "1.3.6.1.5.5.7.48.1.2",
        critical: false,
        extnValue: new asn1js.OctetString().toBER(),
      })
    ];
    request.tbsRequest.requestList[0].reqCert = new CertID({
      hashAlgorithm: new AlgorithmIdentifier({ algorithmId: "1.3.14.3.2.26" }),
      issuerNameHash: new asn1js.OctetString({ valueHex: issuerNameHashBytes }),
      issuerKeyHash: new asn1js.OctetString({ valueHex: issuerKeyHashBytes }),
      serialNumber: new asn1js.Integer({ valueHex: serialNumberBytes }),
    });
    // 2. 编码OCSP请求
    const encodedOcspReq = request.toSchema(true).toBER(false);

    // 3. 使用Axios调用OCSP接口
    const response: any = await Axios.post<ArrayBuffer>(ocspRequest.responderURL, encodedOcspReq,
      {
        headers: {
          'Content-Type': 'application/ocsp-request',
        },
      },
    );

    // 4. 将响应转换为ASN1格式
    const ocspResponseBuffer = Buffer.from(ocspResponse.data);
    const rawOcspResponseBuffer = new Uint8Array(ocspResponseBuffer.buffer);
    const asn1 = asn1js.fromBER(rawOcspResponseBuffer.buffer);

    // 5. 尝试解码获取证书状态时触发PKI.js错误
    const decodedOcspResponse = new OCSPResponse({ schema: asn1.result });
}

代码步骤说明

  • 借助PKI.js和ASN1.js包构建OCSP请求
  • 对OCSP请求进行编码,发送至OCSP接口
  • 接收包含编码数据的响应
  • 将编码的OCSP响应转换为ASN1格式
  • 尝试解码响应以获取证书状态信息

错误描述

执行步骤5时,PKI.js抛出错误:Object's schema was not verified against input data for OCSPResponse。

由于对证书安全领域不熟悉,虽已做调研,但仍无法定位错误原因及修复方法。

编辑1:原始响应内容

OCSP服务返回的response.data值如下(包含不可读的编码内容):

0�{
��t0�p  +0�a0�]0�ȡK0I10U    V2GRootCA10U
Smartlab10
    �&amp;���,dV2G10    UDE20230927144339Z0h0f0O0   +�� �nɽ�J]��J�)y�9o�h���3ve�xpw$�#M��z�C�EQS?�WQ���+�����20230927144339Z0*�H�=���2���S�`���̥��0���oN6N8�'��2ř��=O�l,�&gt;&gt;jA���&lt;~�`f}�%�2���S�`���̥��0���oN6N8�'��2ř��=O�l,�&gt;&gt;jA���&lt;~�`f

无法识别该编码类型。

编辑2:解决方案

问题根源在于Axios未指定响应类型,需在请求配置中添加responseType: 'arraybuffer',修改后的代码如下:

const response: any = await Axios.post<ArrayBuffer>(ocspRequest.responderURL, encodedOcspReq,
  {
    headers: {
      'Content-Type': 'application/ocsp-request',
    },
    responseType: 'arraybuffer',
  },
);

内容的提问来源于stack exchange,提问作者Namachi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 01:30:07