类 OpenSSL::Timestamp::Response
时间戳服务器在收到关联的 Request
后返回的时间戳响应的不可变且只读表示。允许访问有关响应的特定信息,但也允许验证 Response
。
常量
- GRANTED
表示成功响应。等于
0
。- GRANTED_WITH_MODS
表示成功响应,可能包含来自初始请求的修改。等于
1
。- REJECTION
表示失败。没有创建时间戳令牌。等于
2
。- REVOCATION_NOTIFICATION
表示失败。没有创建时间戳令牌。证书已被吊销。等于
5
。- REVOCATION_WARNING
表示失败。没有创建时间戳令牌。证书即将吊销。等于
4
。- WAITING
表示失败。没有创建时间戳令牌。等于
3
。
公共类方法
从 File
或 string
参数创建 Response
,相应的 File
或 string
必须是 DER 编码的。请注意,Response
是一个不可变的只读类。如果您想创建时间戳,请参考 Factory
。
static VALUE ossl_ts_resp_initialize(VALUE self, VALUE der) { TS_RESP *ts_resp = DATA_PTR(self); BIO *in; der = ossl_to_der_if_possible(der); in = ossl_obj2bio(&der); ts_resp = d2i_TS_RESP_bio(in, &ts_resp); BIO_free(in); if (!ts_resp) { DATA_PTR(self) = NULL; ossl_raise(eTimestampError, "Error when decoding the timestamp response"); } DATA_PTR(self) = ts_resp; return self; }
公共实例方法
在没有创建时间戳令牌的情况下,此字段包含有关响应创建失败原因的更多信息。该方法返回 nil(请求成功并创建了时间戳令牌)或以下之一
-
:BAD_ALG - 表示时间戳服务器拒绝了在
Request
中使用的消息指纹算法 -
:BAD_REQUEST - 表示时间戳服务器无法正确处理
Request
-
:BAD_DATA_FORMAT - 表示时间戳服务器无法解析
Request
中的某些数据 -
:TIME_NOT_AVAILABLE - 表示服务器无法访问其时间源
-
:UNACCEPTED_POLICY - 表示时间戳服务器不识别或不支持请求的策略标识符
-
:UNACCEPTED_EXTENSIION - 表示
Request
中的扩展不被时间戳服务器支持 -
:ADD_INFO_NOT_AVAILABLE - 表示请求的附加信息要么不被理解,要么当前不可用
-
:SYSTEM_FAILURE -
Timestamp
创建失败,因为时间戳服务器上发生了内部错误
static VALUE ossl_ts_resp_get_failure_info(VALUE self) { TS_RESP *resp; TS_STATUS_INFO *si; /* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this * const. */ #if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO) const ASN1_BIT_STRING *fi; #else ASN1_BIT_STRING *fi; #endif GetTSResponse(self, resp); si = TS_RESP_get_status_info(resp); fi = TS_STATUS_INFO_get0_failure_info(si); if (!fi) return Qnil; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_ALG)) return sBAD_ALG; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_REQUEST)) return sBAD_REQUEST; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_BAD_DATA_FORMAT)) return sBAD_DATA_FORMAT; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_TIME_NOT_AVAILABLE)) return sTIME_NOT_AVAILABLE; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_POLICY)) return sUNACCEPTED_POLICY; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_UNACCEPTED_EXTENSION)) return sUNACCEPTED_EXTENSION; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_ADD_INFO_NOT_AVAILABLE)) return sADD_INFO_NOT_AVAILABLE; if (ASN1_BIT_STRING_get_bit(fi, TS_INFO_SYSTEM_FAILURE)) return sSYSTEM_FAILURE; ossl_raise(eTimestampError, "Unrecognized failure info."); }
返回以下之一:GRANTED
、GRANTED_WITH_MODS
、REJECTION
、WAITING
、REVOCATION_WARNING
或 REVOCATION_NOTIFICATION
。只有当 status
等于 GRANTED
或 GRANTED_WITH_MODS
时,才会创建时间戳令牌。
static VALUE ossl_ts_resp_get_status(VALUE self) { TS_RESP *resp; TS_STATUS_INFO *si; const ASN1_INTEGER *st; GetTSResponse(self, resp); si = TS_RESP_get_status_info(resp); st = TS_STATUS_INFO_get0_status(si); return asn1integer_to_num(st); }
在发生故障的情况下,此字段可能包含一个字符串数组,进一步描述故障的来源。
static VALUE ossl_ts_resp_get_status_text(VALUE self) { TS_RESP *resp; TS_STATUS_INFO *si; const STACK_OF(ASN1_UTF8STRING) *text; ASN1_UTF8STRING *current; int i; VALUE ret = rb_ary_new(); GetTSResponse(self, resp); si = TS_RESP_get_status_info(resp); if ((text = TS_STATUS_INFO_get0_text(si))) { for (i = 0; i < sk_ASN1_UTF8STRING_num(text); i++) { current = sk_ASN1_UTF8STRING_value(text, i); rb_ary_push(ret, asn1str_to_str(current)); } } return ret; }
以 DER 编码形式返回 Response
。
static VALUE ossl_ts_resp_to_der(VALUE self) { TS_RESP *resp; GetTSResponse(self, resp); return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP); }
如果存在时间戳令牌,则以 OpenSSL::PKCS7
的形式返回它。
static VALUE ossl_ts_resp_get_token(VALUE self) { TS_RESP *resp; PKCS7 *p7, *copy; VALUE obj; GetTSResponse(self, resp); if (!(p7 = TS_RESP_get_token(resp))) return Qnil; obj = NewPKCS7(cPKCS7); if (!(copy = PKCS7_dup(p7))) ossl_raise(eTimestampError, NULL); SetPKCS7(obj, copy); return obj; }
获取响应的令牌信息(如果存在)。
static VALUE ossl_ts_resp_get_token_info(VALUE self) { TS_RESP *resp; TS_TST_INFO *info, *copy; VALUE obj; GetTSResponse(self, resp); if (!(info = TS_RESP_get_tst_info(resp))) return Qnil; obj = NewTSTokenInfo(cTimestampTokenInfo); if (!(copy = TS_TST_INFO_dup(info))) ossl_raise(eTimestampError, NULL); SetTSTokenInfo(obj, copy); return obj; }
如果 Request
指定请求 TSA 证书 (Request#cert_requested = true),则此字段包含时间戳颁发机构的证书。
static VALUE ossl_ts_resp_get_tsa_certificate(VALUE self) { TS_RESP *resp; PKCS7 *p7; PKCS7_SIGNER_INFO *ts_info; X509 *cert; GetTSResponse(self, resp); if (!(p7 = TS_RESP_get_token(resp))) return Qnil; ts_info = sk_PKCS7_SIGNER_INFO_value(p7->d.sign->signer_info, 0); cert = PKCS7_cert_from_signer_info(p7, ts_info); if (!cert) return Qnil; return ossl_x509_new(cert); }
通过检查签名、验证由 tsa_certificate
隐含的证书链以及检查与给定 Request
的一致性来验证时间戳令牌。必需参数是与该 Response
关联的 Request
,以及一个包含受信任根证书的 OpenSSL::X509::Store
。
可以可选地提供中间证书以创建证书链。这些中间证书必须都是 OpenSSL::X509::Certificate
的实例。
如果验证失败,可能会引发几种类型的异常。
-
如果类型不匹配,则引发 TypeError。
-
TimestampError
如果时间戳令牌本身存在问题,如果它不符合Request
,或者如果时间戳证书链的验证失败。
static VALUE ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self) { VALUE ts_req, store, intermediates; TS_RESP *resp; TS_REQ *req; X509_STORE *x509st; TS_VERIFY_CTX *ctx; STACK_OF(X509) *x509inter = NULL; PKCS7* p7; X509 *cert; int status, i, ok; rb_scan_args(argc, argv, "21", &ts_req, &store, &intermediates); GetTSResponse(self, resp); GetTSRequest(ts_req, req); x509st = GetX509StorePtr(store); if (!(ctx = TS_REQ_to_TS_VERIFY_CTX(req, NULL))) { ossl_raise(eTimestampError, "Error when creating the verification context."); } if (!NIL_P(intermediates)) { x509inter = ossl_protect_x509_ary2sk(intermediates, &status); if (status) { TS_VERIFY_CTX_free(ctx); rb_jump_tag(status); } } else if (!(x509inter = sk_X509_new_null())) { TS_VERIFY_CTX_free(ctx); ossl_raise(eTimestampError, "sk_X509_new_null"); } if (!(p7 = TS_RESP_get_token(resp))) { TS_VERIFY_CTX_free(ctx); sk_X509_pop_free(x509inter, X509_free); ossl_raise(eTimestampError, "TS_RESP_get_token"); } for (i=0; i < sk_X509_num(p7->d.sign->cert); i++) { cert = sk_X509_value(p7->d.sign->cert, i); if (!sk_X509_push(x509inter, cert)) { sk_X509_pop_free(x509inter, X509_free); TS_VERIFY_CTX_free(ctx); ossl_raise(eTimestampError, "sk_X509_push"); } X509_up_ref(cert); } TS_VERIFY_CTX_set_certs(ctx, x509inter); TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE); TS_VERIFY_CTX_set_store(ctx, x509st); ok = TS_RESP_verify_response(ctx, resp); /* * TS_VERIFY_CTX_set_store() call above does not increment the reference * counter, so it must be unset before TS_VERIFY_CTX_free() is called. */ TS_VERIFY_CTX_set_store(ctx, NULL); TS_VERIFY_CTX_free(ctx); if (!ok) ossl_raise(eTimestampError, "TS_RESP_verify_response"); return self; }