类 OpenSSL::X509::Store
X509
证书存储用于保存用于验证对等证书的受信任 CA 证书。
创建有用证书存储的最简单方法是
cert_store = OpenSSL::X509::Store.new cert_store.set_default_paths
这将使用您系统的内置证书。
如果您的系统没有默认的证书集,您可以从 Mozilla CA 证书存储中获取由 cURL 维护者提取的一组证书:curl.haxx.se/docs/caextract.html(您可能希望使用 firefox-db2pem.sh 脚本从本地安装中提取证书以避免中间人攻击。)
从上面的链接下载或生成 cacert.pem 后,您可以像这样从 pem 文件创建证书存储
cert_store = OpenSSL::X509::Store.new cert_store.add_file 'cacert.pem'
证书存储可以与 SSLSocket 一起使用,如下所示
ssl_context = OpenSSL::SSL::SSLContext.new ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER ssl_context.cert_store = cert_store tcp_socket = TCPSocket.open 'example.com', 443 ssl_socket = OpenSSL::SSL::SSLSocket.new tcp_socket, ssl_context
属性
由 verify
的最后一次调用构建的证书链。
另请参见 StoreContext#chain
。
由 verify
的最后一次调用设置的错误代码。
另请参见 StoreContext#error
。
由 verify
的最后一次调用设置的错误代码的描述。
用于额外证书验证的回调。它会为链中的每个证书调用,并且可以用于实现自定义证书验证条件。
回调会使用两个值调用,一个布尔值,指示 OpenSSL
的预验证是否成功,以及正在使用的 StoreContext
。
回调可以使用 StoreContext#error=
根据需要更改错误代码。回调必须返回 true 或 false。
注意:回调中引发的任何异常都将被忽略。
另请参见手册页 X509_STORE_CTX_set_verify_cb(3)。
公共类方法
创建一个新的 X509::Store
。
static VALUE ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) { X509_STORE *store; GetX509Store(self, store); if (argc != 0) rb_warn("OpenSSL::X509::Store.new does not take any arguments"); #if !defined(HAVE_OPAQUE_OPENSSL) /* [Bug #405] [Bug #1678] [Bug #3000]; already fixed? */ store->ex_data.sk = NULL; #endif X509_STORE_set_verify_cb(store, x509store_verify_cb); ossl_x509store_set_vfy_cb(self, Qnil); /* last verification status */ rb_iv_set(self, "@error", Qnil); rb_iv_set(self, "@error_string", Qnil); rb_iv_set(self, "@chain", Qnil); rb_iv_set(self, "@time", Qnil); return self; }
公共实例方法
将 OpenSSL::X509::Certificate
cert 添加到证书存储中。
另请参阅手册页 X509_STORE_add_cert(3)。
static VALUE ossl_x509store_add_cert(VALUE self, VALUE arg) { X509_STORE *store; X509 *cert; cert = GetX509CertPtr(arg); /* NO NEED TO DUP */ GetX509Store(self, store); if (X509_STORE_add_cert(store, cert) != 1) ossl_raise(eX509StoreError, "X509_STORE_add_cert"); return self; }
将 OpenSSL::X509::CRL
crl 添加到存储中。
另请参阅手册页 X509_STORE_add_crl(3)。
static VALUE ossl_x509store_add_crl(VALUE self, VALUE arg) { X509_STORE *store; X509_CRL *crl; crl = GetX509CRLPtr(arg); /* NO NEED TO DUP */ GetX509Store(self, store); if (X509_STORE_add_crl(store, crl) != 1) ossl_raise(eX509StoreError, "X509_STORE_add_crl"); return self; }
将 file 中的证书添加到证书存储中。file 是文件的路径,该文件包含以 PEM 格式连接在一起的一个或多个证书。
另请参阅手册页 X509_LOOKUP_file(3)。
static VALUE ossl_x509store_add_file(VALUE self, VALUE file) { X509_STORE *store; X509_LOOKUP *lookup; const char *path; GetX509Store(self, store); path = StringValueCStr(file); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); if (!lookup) ossl_raise(eX509StoreError, "X509_STORE_add_lookup"); if (X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1) ossl_raise(eX509StoreError, "X509_LOOKUP_load_file"); #if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER) /* * X509_load_cert_crl_file() which is called from X509_LOOKUP_load_file() * did not check the return value of X509_STORE_add_{cert,crl}(), leaking * "cert already in hash table" errors on the error queue, if duplicate * certificates are found. This will be fixed by OpenSSL 1.1.1. */ ossl_clear_error(); #endif return self; }
将 path 添加为存储要查找的哈希目录。
另请参阅手册页 X509_LOOKUP_hash_dir(3)。
static VALUE ossl_x509store_add_path(VALUE self, VALUE dir) { X509_STORE *store; X509_LOOKUP *lookup; const char *path; GetX509Store(self, store); path = StringValueCStr(dir); lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir()); if (!lookup) ossl_raise(eX509StoreError, "X509_STORE_add_lookup"); if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1) ossl_raise(eX509StoreError, "X509_LOOKUP_add_dir"); return self; }
设置使用 Store
执行的证书链验证使用的默认标志。
flags 由 OpenSSL::X509
中定义的名称为 V_FLAG_* 的常量组成,或按位或运算在一起。
OpenSSL::X509::StoreContext#flags=
可用于更改单个验证操作的标志。
另请参阅手册页 X509_VERIFY_PARAM_set_flags(3)。
static VALUE ossl_x509store_set_flags(VALUE self, VALUE flags) { X509_STORE *store; long f = NUM2LONG(flags); GetX509Store(self, store); X509_STORE_set_flags(store, f); return flags; }
设置存储的默认验证目的。如果指定,存储上的验证将检查每个证书的扩展名是否与目的相一致。目的由以下常量指定:
-
X509::PURPOSE_SSL_CLIENT
-
X509::PURPOSE_SSL_SERVER
-
X509::PURPOSE_NS_SSL_SERVER
-
X509::PURPOSE_SMIME_SIGN
-
X509::PURPOSE_SMIME_ENCRYPT
-
X509::PURPOSE_CRL_SIGN
-
X509::PURPOSE_ANY
-
X509::PURPOSE_OCSP_HELPER
-
X509::PURPOSE_TIMESTAMP_SIGN
OpenSSL::X509::StoreContext#purpose=
可用于更改单个验证操作的值。
另请参阅手册页 X509_VERIFY_PARAM_set_purpose(3)。
static VALUE ossl_x509store_set_purpose(VALUE self, VALUE purpose) { X509_STORE *store; int p = NUM2INT(purpose); GetX509Store(self, store); X509_STORE_set_purpose(store, p); return purpose; }
配置store 以根据需要从系统默认证书存储中查找 CA 证书。存储位置通常可以通过
-
OpenSSL::X509::DEFAULT_CERT_FILE
-
OpenSSL::X509::DEFAULT_CERT_DIR
另请参阅手册页 X509_STORE_set_default_paths(3)。
static VALUE ossl_x509store_set_default_paths(VALUE self) { X509_STORE *store; GetX509Store(self, store); if (X509_STORE_set_default_paths(store) != 1) ossl_raise(eX509StoreError, "X509_STORE_set_default_paths"); return Qnil; }
设置用于证书验证的存储的时间。默认情况下,如果未指定,则使用当前系统时间。
OpenSSL::X509::StoreContext#time=
可用于更改单个验证操作的值。
另请参阅手册页 X509_VERIFY_PARAM_set_time(3)。
static VALUE ossl_x509store_set_time(VALUE self, VALUE time) { rb_iv_set(self, "@time", time); return time; }
设置证书验证与存储一起使用的默认信任设置。
OpenSSL::X509::StoreContext#trust=
可用于更改单个验证操作的值。
另请参阅手册页 X509_VERIFY_PARAM_set_trust(3)。
static VALUE ossl_x509store_set_trust(VALUE self, VALUE trust) { X509_STORE *store; int t = NUM2INT(trust); GetX509Store(self, store); X509_STORE_set_trust(store, t); return trust; }
对 OpenSSL::X509::Certificate
cert 执行证书验证。
chain 可以是 OpenSSL::X509::Certificate
的数组,用于构建证书链。
如果给定一个块,它将覆盖由 verify_callback=
设置的回调。
完成验证后,可以通过 error
、error_string
检索错误信息,并且可以通过 chain
检索生成的完整证书链。
static VALUE ossl_x509store_verify(int argc, VALUE *argv, VALUE self) { VALUE cert, chain; VALUE ctx, proc, result; rb_scan_args(argc, argv, "11", &cert, &chain); ctx = rb_funcall(cX509StoreContext, rb_intern("new"), 3, self, cert, chain); proc = rb_block_given_p() ? rb_block_proc() : rb_iv_get(self, "@verify_callback"); rb_iv_set(ctx, "@verify_callback", proc); result = rb_funcall(ctx, rb_intern("verify"), 0); rb_iv_set(self, "@error", ossl_x509stctx_get_err(ctx)); rb_iv_set(self, "@error_string", ossl_x509stctx_get_err_string(ctx)); rb_iv_set(self, "@chain", ossl_x509stctx_get_chain(ctx)); return result; }
针对 OpenSSL
验证的通用回调
static VALUE ossl_x509store_set_vfy_cb(VALUE self, VALUE cb) { X509_STORE *store; GetX509Store(self, store); rb_iv_set(self, "@verify_callback", cb); // We don't need to trigger a write barrier because `rb_iv_set` did it. X509_STORE_set_ex_data(store, store_ex_verify_cb_idx, (void *)cb); return cb; }