我们的目标是确定证书是否良好或是否已被吊销。 为了实现这一目标,我们使用 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) {
// Convert hexadecimal strings into bytes (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. Create OCSP Request with PKI.js
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. Encode OCSP request
const encodedOcspReq = request.toSchema(true).toBER(false);
// 3. OCSP API Call with Axios
const response: any = await Axios.post<ArrayBuffer>(ocspRequest.responderURL, encodedOcspReq,
{
headers: {
'Content-Type': 'application/ocsp-request',
},
},
);
// 4. Convert response to ASN1
const ocspResponseBuffer = Buffer.from(ocspResponse.data);
const rawOcspResponseBuffer = new Uint8Array(ocspResponseBuffer.buffer);
const asn1 = asn1js.fromBER(rawOcspResponseBuffer.buffer);
// 5. Error occurred in PKI.JS OCSPResponse Class
const decodedOcspResponse = new OCSPResponse({ schema: asn1.result });
}
第5步,PKI端出现错误,错误信息如下:
Object's schema was not verified against input data for OCSPResponse
。
由于证书安全根本不是我们的专业领域,尽管我们努力进行研究,但我们无法确定错误可能在哪里以及如何纠正它。
预先感谢您的帮助。
您遇到的错误消息“未根据 OCSPResponse 的输入数据验证对象的架构”表明 OCSP 响应的预期架构与收到的实际数据之间存在不匹配。这通常意味着接收到的数据不符合预期的 ASN.1 模式。
以下步骤可帮助您排除故障并可能解决此问题:
验证响应内容类型: 确保从服务器收到的 OCSP 响应的内容类型与预期的内容类型匹配。在代码中,您在发出 OCSP 请求时将“Content-Type”标头设置为“application/ocsp-request”。确保服务器使用正确的“Content-Type”标头进行响应,对于 OCSP 响应,该标头应为“application/ocsp-response”。
示例:
headers: {
'Content-Type': 'application/ocsp-response',
},
检查 OCSP 响应编码: OCSP 响应采用 DER 编码。确保您收到的响应是 DER 编码且未损坏。如果不是 DER 编码,您可能需要以不同的方式处理解码。
示例:
const ocspResponseBuffer = Buffer.from(response.data, 'binary');
确保响应数据完整: 验证您是否收到来自服务器的完整 OCSP 响应。它应该包括所有必要的组件,例如响应状态、响应字节和响应数据。不完整的响应可能会导致架构验证问题。
检查可能的网络错误: 确保传输过程中不存在导致数据损坏的网络相关问题。您可以添加错误处理来检查网络错误,例如超时或连接问题。
示例:
try {
const response = await Axios.post<ArrayBuffer>(ocspRequest.responderURL, encodedOcspReq, {
headers: {
'Content-Type': 'application/ocsp-request',
},
});
// Handle the response here
} catch (error) {
console.error('Network error:', error);
// Handle the error gracefully
}
验证 ASN.1 架构: 确保用于解码 OCSP 响应的 ASN.1 架构与从服务器收到的响应的结构相匹配。您可以参考 PKI.js 文档来确认预期的结构。
记录和调试: 在代码的各个阶段添加日志记录语句以检查数据并确定架构和数据之间可能发生不匹配的位置。这可以帮助查明问题。
通过系统地检查这些要点并调试代码,您应该能够识别错误来源并进行必要的更正,以成功解码 OCSP 响应并确定证书状态。