class OpenSSL::Timestamp::Factory
Wird verwendet, um eine Response von Grund auf neu zu generieren.
Bitte beachten Sie, dass die Implementierung immer das in der Anfrage angegebene Policy-Objekt-Identifier anwendet und dieses gegenüber dem in der Factory spezifizierten Standard-Policy-Identifier bevorzugt. Infolgedessen wird default_policy_id nur angewendet, wenn keine Request#policy_id angegeben wurde. Dies bedeutet jedoch auch, dass man den Policy-Identifier in der Anfrage manuell überprüfen muss, bevor die Response erstellt wird, z. B. um zu prüfen, ob er mit einem bestimmten Satz akzeptabler Policies übereinstimmt.
Es besteht auch die Möglichkeit, neben dem Zeitstempelzertifikat zusätzliche Zertifikate (Instanzen von OpenSSL::X509::Certificate) hinzuzufügen, die im resultierenden Zeitstempel-Token enthalten sein werden, wenn Request#cert_requested? true ist. Idealerweise sollten auch alle Zwischenzertifikate enthalten sein (das Stammzertifikat kann weggelassen werden – um es zu vertrauen, muss eine prüfende Partei es ohnehin besitzen). Dies vereinfacht die Validierung des Zeitstempels, da diese Zwischenzertifikate "bereits vorhanden" sind und nicht als externe Parameter an Response#verify übergeben werden müssen, wodurch die für die Verifizierung benötigten externen Ressourcen minimiert werden.
Beispiel: Einbeziehung von (nicht vertrauenswürdigen) Zwischenzertifikaten
Angenommen, wir haben eine Zeitstempelanfrage erhalten, bei der Request#policy_id auf nil und Request#cert_requested? auf true gesetzt wurde. Die Rohdaten der Anfrage sind in einer Variablen namens req_raw gespeichert. Wir möchten dennoch die notwendigen Zwischenzertifikate (in inter1.cer und inter2.cer) integrieren, um die Validierung der resultierenden Response zu vereinfachen. ts.p12 ist eine PKCS#12-kompatible Datei, die den privaten Schlüssel und das Zeitstempelzertifikat enthält.
req = OpenSSL::Timestamp::Request.new(raw_bytes) p12 = OpenSSL::PKCS12.new(File.binread('ts.p12'), 'pwd') inter1 = OpenSSL::X509::Certificate.new(File.binread('inter1.cer')) inter2 = OpenSSL::X509::Certificate.new(File.binread('inter2.cer')) fac = OpenSSL::Timestamp::Factory.new fac.gen_time = Time.now fac.serial_number = 1 fac.allowed_digests = ["sha256", "sha384", "sha512"] #needed because the Request contained no policy identifier fac.default_policy_id = '1.2.3.4.5' fac.additional_certificates = [ inter1, inter2 ] timestamp = fac.create_timestamp(p12.key, p12.certificate, req)
Attribute
Zusätzliche Zertifikate, abgesehen vom Zeitstempelzertifikat (z. B. Zwischenzertifikate), die der Response hinzugefügt werden sollen. Muss ein Array von OpenSSL::X509::Certificate oder nil sein.
Die Liste der Digest-Algorithmen, für die die Factory Zeitstempel erstellen darf. Bekanntlich anfällige oder schwache Algorithmen sollten nach Möglichkeit nicht zugelassen werden. Muss ein Array von String oder Instanzen von OpenSSL::Digest sein.
Ein String, der den Standard-Policy-Objekt-Identifier darstellt, oder nil.
Request#policy_id wird immer gegenüber diesem bevorzugt, wenn er in der Request vorhanden ist. Nur wenn Request#policy_id nil ist, wird default_policy verwendet. Wenn keiner von beiden vorhanden ist, wird beim Versuch, eine Response zu erstellen, ein TimestampError ausgelöst.
Die Seriennummer, die für die Erstellung des Zeitstempels verwendet werden soll. Muss für die Erstellung des Zeitstempels vorhanden sein. Muss eine Instanz von OpenSSL::BN oder Integer sein.
Öffentliche Instanzmethoden
Source
static VALUE
ossl_tsfac_create_ts(VALUE self, VALUE key, VALUE certificate, VALUE request)
{
VALUE serial_number, def_policy_id, gen_time, additional_certs,
allowed_digests, allowed_digests_tmp = Qnil;
VALUE str;
STACK_OF(X509) *inter_certs;
VALUE tsresp, ret = Qnil;
EVP_PKEY *sign_key;
X509 *tsa_cert;
TS_REQ *req;
TS_RESP *response = NULL;
TS_RESP_CTX *ctx = NULL;
BIO *req_bio;
ASN1_INTEGER *asn1_serial = NULL;
ASN1_OBJECT *def_policy_id_obj = NULL;
long lgen_time;
const char * err_msg = NULL;
int status = 0;
tsresp = NewTSResponse(cTimestampResponse);
tsa_cert = GetX509CertPtr(certificate);
sign_key = GetPrivPKeyPtr(key);
GetTSRequest(request, req);
gen_time = ossl_tsfac_get_gen_time(self);
if (!rb_obj_is_instance_of(gen_time, rb_cTime)) {
err_msg = "@gen_time must be a Time.";
goto end;
}
lgen_time = NUM2LONG(rb_funcall(gen_time, rb_intern("to_i"), 0));
serial_number = ossl_tsfac_get_serial_number(self);
if (NIL_P(serial_number)) {
err_msg = "@serial_number must be set.";
goto end;
}
asn1_serial = num_to_asn1integer(serial_number, NULL);
def_policy_id = ossl_tsfac_get_default_policy_id(self);
if (NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
err_msg = "No policy id in the request and no default policy set";
goto end;
}
if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req)) {
def_policy_id_obj = (ASN1_OBJECT*)rb_protect(obj_to_asn1obj_i, (VALUE)def_policy_id, &status);
if (status)
goto end;
}
if (!(ctx = TS_RESP_CTX_new())) {
err_msg = "Memory allocation failed.";
goto end;
}
TS_RESP_CTX_set_serial_cb(ctx, ossl_tsfac_serial_cb, &asn1_serial);
if (!TS_RESP_CTX_set_signer_cert(ctx, tsa_cert)) {
err_msg = "Certificate does not contain the timestamping extension";
goto end;
}
additional_certs = ossl_tsfac_get_additional_certs(self);
if (rb_obj_is_kind_of(additional_certs, rb_cArray)) {
inter_certs = ossl_protect_x509_ary2sk(additional_certs, &status);
if (status)
goto end;
/* this dups the sk_X509 and ups each cert's ref count */
TS_RESP_CTX_set_certs(ctx, inter_certs);
sk_X509_pop_free(inter_certs, X509_free);
}
TS_RESP_CTX_set_signer_key(ctx, sign_key);
if (!NIL_P(def_policy_id) && !TS_REQ_get_policy_id(req))
TS_RESP_CTX_set_def_policy(ctx, def_policy_id_obj);
if (TS_REQ_get_policy_id(req))
TS_RESP_CTX_set_def_policy(ctx, TS_REQ_get_policy_id(req));
TS_RESP_CTX_set_time_cb(ctx, ossl_tsfac_time_cb, &lgen_time);
allowed_digests = ossl_tsfac_get_allowed_digests(self);
if (rb_obj_is_kind_of(allowed_digests, rb_cArray)) {
allowed_digests_tmp = rb_ary_new_capa(RARRAY_LEN(allowed_digests));
for (long i = 0; i < RARRAY_LEN(allowed_digests); i++) {
VALUE args[] = {
allowed_digests_tmp,
rb_ary_entry(allowed_digests, i),
};
const EVP_MD *md = (const EVP_MD *)rb_protect(ossl_evp_md_fetch_i,
(VALUE)args, &status);
if (status)
goto end;
if (!TS_RESP_CTX_add_md(ctx, md))
goto end;
}
}
str = rb_protect(ossl_to_der, request, &status);
if (status)
goto end;
req_bio = (BIO*)rb_protect(ossl_obj2bio_i, (VALUE)&str, &status);
if (status)
goto end;
response = TS_RESP_create_response(ctx, req_bio);
BIO_free(req_bio);
RB_GC_GUARD(allowed_digests_tmp);
if (!response) {
err_msg = "Error during response generation";
goto end;
}
/* bad responses aren't exceptional, but openssl still sets error
* information. */
ossl_clear_error();
SetTSResponse(tsresp, response);
ret = tsresp;
end:
ASN1_INTEGER_free(asn1_serial);
ASN1_OBJECT_free(def_policy_id_obj);
TS_RESP_CTX_free(ctx);
if (err_msg)
rb_exc_raise(ossl_make_error(eTimestampError, rb_str_new_cstr(err_msg)));
if (status)
rb_jump_tag(status);
return ret;
}
Erstellt eine Response mit Hilfe eines OpenSSL::PKey, eines OpenSSL::X509::Certificate und einer Request.
Obligatorische Parameter für die Erstellung des Zeitstempels, die in der Request gesetzt werden müssen
Obligatorische Parameter, die in der Factory gesetzt werden müssen
Zusätzlich muss entweder Request#policy_id oder Factory#default_policy_id gesetzt sein.
Löst einen TimestampError aus, wenn die Erstellung fehlschlägt, obwohl erfolgreich erstellte Fehlerantworten zurückgegeben werden können.