Ruby  2.0.0p247(2013-06-27revision41674)
ext/openssl/ossl_x509cert.c
Go to the documentation of this file.
00001 /*
00002  * $Id: ossl_x509cert.c 35190 2012-03-31 03:07:53Z emboss $
00003  * 'OpenSSL for Ruby' project
00004  * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
00005  * All rights reserved.
00006  */
00007 /*
00008  * This program is licenced under the same licence as Ruby.
00009  * (See the file 'LICENCE'.)
00010  */
00011 #include "ossl.h"
00012 
00013 #define WrapX509(klass, obj, x509) do { \
00014     if (!(x509)) { \
00015         ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
00016     } \
00017     (obj) = Data_Wrap_Struct((klass), 0, X509_free, (x509)); \
00018 } while (0)
00019 #define GetX509(obj, x509) do { \
00020     Data_Get_Struct((obj), X509, (x509)); \
00021     if (!(x509)) { \
00022         ossl_raise(rb_eRuntimeError, "CERT wasn't initialized!"); \
00023     } \
00024 } while (0)
00025 #define SafeGetX509(obj, x509) do { \
00026     OSSL_Check_Kind((obj), cX509Cert); \
00027     GetX509((obj), (x509)); \
00028 } while (0)
00029 
00030 /*
00031  * Classes
00032  */
00033 VALUE cX509Cert;
00034 VALUE eX509CertError;
00035 
00036 /*
00037  * Public
00038  */
00039 VALUE
00040 ossl_x509_new(X509 *x509)
00041 {
00042     X509 *new;
00043     VALUE obj;
00044 
00045     if (!x509) {
00046         new = X509_new();
00047     } else {
00048         new = X509_dup(x509);
00049     }
00050     if (!new) {
00051         ossl_raise(eX509CertError, NULL);
00052     }
00053     WrapX509(cX509Cert, obj, new);
00054 
00055     return obj;
00056 }
00057 
00058 VALUE
00059 ossl_x509_new_from_file(VALUE filename)
00060 {
00061     X509 *x509;
00062     FILE *fp;
00063     VALUE obj;
00064 
00065     SafeStringValue(filename);
00066     if (!(fp = fopen(RSTRING_PTR(filename), "r"))) {
00067         ossl_raise(eX509CertError, "%s", strerror(errno));
00068     }
00069     rb_fd_fix_cloexec(fileno(fp));
00070     x509 = PEM_read_X509(fp, NULL, NULL, NULL);
00071     /*
00072      * prepare for DER...
00073 #if !defined(OPENSSL_NO_FP_API)
00074     if (!x509) {
00075         (void)ERR_get_error();
00076         rewind(fp);
00077 
00078         x509 = d2i_X509_fp(fp, NULL);
00079     }
00080 #endif
00081     */
00082     fclose(fp);
00083     if (!x509) {
00084         ossl_raise(eX509CertError, NULL);
00085     }
00086     WrapX509(cX509Cert, obj, x509);
00087 
00088     return obj;
00089 }
00090 
00091 X509 *
00092 GetX509CertPtr(VALUE obj)
00093 {
00094     X509 *x509;
00095 
00096     SafeGetX509(obj, x509);
00097 
00098     return x509;
00099 }
00100 
00101 X509 *
00102 DupX509CertPtr(VALUE obj)
00103 {
00104     X509 *x509;
00105 
00106     SafeGetX509(obj, x509);
00107 
00108     CRYPTO_add(&x509->references, 1, CRYPTO_LOCK_X509);
00109 
00110     return x509;
00111 }
00112 
00113 /*
00114  * Private
00115  */
00116 static VALUE
00117 ossl_x509_alloc(VALUE klass)
00118 {
00119     X509 *x509;
00120     VALUE obj;
00121 
00122     x509 = X509_new();
00123     if (!x509) ossl_raise(eX509CertError, NULL);
00124 
00125     WrapX509(klass, obj, x509);
00126 
00127     return obj;
00128 }
00129 
00130 /*
00131  * call-seq:
00132  *    Certificate.new => cert
00133  *    Certificate.new(string) => cert
00134  */
00135 static VALUE
00136 ossl_x509_initialize(int argc, VALUE *argv, VALUE self)
00137 {
00138     BIO *in;
00139     X509 *x509, *x = DATA_PTR(self);
00140     VALUE arg;
00141 
00142     if (rb_scan_args(argc, argv, "01", &arg) == 0) {
00143         /* create just empty X509Cert */
00144         return self;
00145     }
00146     arg = ossl_to_der_if_possible(arg);
00147     in = ossl_obj2bio(arg);
00148     x509 = PEM_read_bio_X509(in, &x, NULL, NULL);
00149     DATA_PTR(self) = x;
00150     if (!x509) {
00151         OSSL_BIO_reset(in);
00152         x509 = d2i_X509_bio(in, &x);
00153         DATA_PTR(self) = x;
00154     }
00155     BIO_free(in);
00156     if (!x509) ossl_raise(eX509CertError, NULL);
00157 
00158     return self;
00159 }
00160 
00161 static VALUE
00162 ossl_x509_copy(VALUE self, VALUE other)
00163 {
00164     X509 *a, *b, *x509;
00165 
00166     rb_check_frozen(self);
00167     if (self == other) return self;
00168 
00169     GetX509(self, a);
00170     SafeGetX509(other, b);
00171 
00172     x509 = X509_dup(b);
00173     if (!x509) ossl_raise(eX509CertError, NULL);
00174 
00175     DATA_PTR(self) = x509;
00176     X509_free(a);
00177 
00178     return self;
00179 }
00180 
00181 /*
00182  * call-seq:
00183  *    cert.to_der => string
00184  */
00185 static VALUE
00186 ossl_x509_to_der(VALUE self)
00187 {
00188     X509 *x509;
00189     VALUE str;
00190     long len;
00191     unsigned char *p;
00192 
00193     GetX509(self, x509);
00194     if ((len = i2d_X509(x509, NULL)) <= 0)
00195         ossl_raise(eX509CertError, NULL);
00196     str = rb_str_new(0, len);
00197     p = (unsigned char *)RSTRING_PTR(str);
00198     if (i2d_X509(x509, &p) <= 0)
00199         ossl_raise(eX509CertError, NULL);
00200     ossl_str_adjust(str, p);
00201 
00202     return str;
00203 }
00204 
00205 /*
00206  * call-seq:
00207  *    cert.to_pem => string
00208  */
00209 static VALUE
00210 ossl_x509_to_pem(VALUE self)
00211 {
00212     X509 *x509;
00213     BIO *out;
00214     VALUE str;
00215 
00216     GetX509(self, x509);
00217     out = BIO_new(BIO_s_mem());
00218     if (!out) ossl_raise(eX509CertError, NULL);
00219 
00220     if (!PEM_write_bio_X509(out, x509)) {
00221         BIO_free(out);
00222         ossl_raise(eX509CertError, NULL);
00223     }
00224     str = ossl_membio2str(out);
00225 
00226     return str;
00227 }
00228 
00229 /*
00230  * call-seq:
00231  *    cert.to_text => string
00232  */
00233 static VALUE
00234 ossl_x509_to_text(VALUE self)
00235 {
00236     X509 *x509;
00237     BIO *out;
00238     VALUE str;
00239 
00240     GetX509(self, x509);
00241 
00242     out = BIO_new(BIO_s_mem());
00243     if (!out) ossl_raise(eX509CertError, NULL);
00244 
00245     if (!X509_print(out, x509)) {
00246         BIO_free(out);
00247         ossl_raise(eX509CertError, NULL);
00248     }
00249     str = ossl_membio2str(out);
00250 
00251     return str;
00252 }
00253 
00254 #if 0
00255 /*
00256  * Makes from X509 X509_REQuest
00257  */
00258 static VALUE
00259 ossl_x509_to_req(VALUE self)
00260 {
00261     X509 *x509;
00262     X509_REQ *req;
00263     VALUE obj;
00264 
00265     GetX509(self, x509);
00266     if (!(req = X509_to_X509_REQ(x509, NULL, EVP_md5()))) {
00267         ossl_raise(eX509CertError, NULL);
00268     }
00269     obj = ossl_x509req_new(req);
00270     X509_REQ_free(req);
00271 
00272     return obj;
00273 }
00274 #endif
00275 
00276 /*
00277  * call-seq:
00278  *    cert.version => integer
00279  */
00280 static VALUE
00281 ossl_x509_get_version(VALUE self)
00282 {
00283     X509 *x509;
00284 
00285     GetX509(self, x509);
00286 
00287     return LONG2NUM(X509_get_version(x509));
00288 }
00289 
00290 /*
00291  * call-seq:
00292  *    cert.version = integer => integer
00293  */
00294 static VALUE
00295 ossl_x509_set_version(VALUE self, VALUE version)
00296 {
00297     X509 *x509;
00298     long ver;
00299 
00300     if ((ver = NUM2LONG(version)) < 0) {
00301         ossl_raise(eX509CertError, "version must be >= 0!");
00302     }
00303     GetX509(self, x509);
00304     if (!X509_set_version(x509, ver)) {
00305         ossl_raise(eX509CertError, NULL);
00306     }
00307 
00308     return version;
00309 }
00310 
00311 /*
00312  * call-seq:
00313  *    cert.serial => integer
00314  */
00315 static VALUE
00316 ossl_x509_get_serial(VALUE self)
00317 {
00318     X509 *x509;
00319 
00320     GetX509(self, x509);
00321 
00322     return asn1integer_to_num(X509_get_serialNumber(x509));
00323 }
00324 
00325 /*
00326  * call-seq:
00327  *    cert.serial = integer => integer
00328  */
00329 static VALUE
00330 ossl_x509_set_serial(VALUE self, VALUE num)
00331 {
00332     X509 *x509;
00333 
00334     GetX509(self, x509);
00335 
00336     x509->cert_info->serialNumber =
00337         num_to_asn1integer(num, X509_get_serialNumber(x509));
00338 
00339     return num;
00340 }
00341 
00342 /*
00343  * call-seq:
00344  *    cert.signature_algorithm => string
00345  */
00346 static VALUE
00347 ossl_x509_get_signature_algorithm(VALUE self)
00348 {
00349     X509 *x509;
00350     BIO *out;
00351     VALUE str;
00352 
00353     GetX509(self, x509);
00354     out = BIO_new(BIO_s_mem());
00355     if (!out) ossl_raise(eX509CertError, NULL);
00356 
00357     if (!i2a_ASN1_OBJECT(out, x509->cert_info->signature->algorithm)) {
00358         BIO_free(out);
00359         ossl_raise(eX509CertError, NULL);
00360     }
00361     str = ossl_membio2str(out);
00362 
00363     return str;
00364 }
00365 
00366 /*
00367  * call-seq:
00368  *    cert.subject => name
00369  */
00370 static VALUE
00371 ossl_x509_get_subject(VALUE self)
00372 {
00373     X509 *x509;
00374     X509_NAME *name;
00375 
00376     GetX509(self, x509);
00377     if (!(name = X509_get_subject_name(x509))) { /* NO DUP - don't free! */
00378         ossl_raise(eX509CertError, NULL);
00379     }
00380 
00381     return ossl_x509name_new(name);
00382 }
00383 
00384 /*
00385  * call-seq:
00386  *    cert.subject = name => name
00387  */
00388 static VALUE
00389 ossl_x509_set_subject(VALUE self, VALUE subject)
00390 {
00391     X509 *x509;
00392 
00393     GetX509(self, x509);
00394     if (!X509_set_subject_name(x509, GetX509NamePtr(subject))) { /* DUPs name */
00395         ossl_raise(eX509CertError, NULL);
00396     }
00397 
00398     return subject;
00399 }
00400 
00401 /*
00402  * call-seq:
00403  *    cert.issuer => name
00404  */
00405 static VALUE
00406 ossl_x509_get_issuer(VALUE self)
00407 {
00408     X509 *x509;
00409     X509_NAME *name;
00410 
00411     GetX509(self, x509);
00412     if(!(name = X509_get_issuer_name(x509))) { /* NO DUP - don't free! */
00413         ossl_raise(eX509CertError, NULL);
00414     }
00415 
00416     return ossl_x509name_new(name);
00417 }
00418 
00419 /*
00420  * call-seq:
00421  *    cert.issuer = name => name
00422  */
00423 static VALUE
00424 ossl_x509_set_issuer(VALUE self, VALUE issuer)
00425 {
00426     X509 *x509;
00427 
00428     GetX509(self, x509);
00429     if (!X509_set_issuer_name(x509, GetX509NamePtr(issuer))) { /* DUPs name */
00430         ossl_raise(eX509CertError, NULL);
00431     }
00432 
00433     return issuer;
00434 }
00435 
00436 /*
00437  * call-seq:
00438  *    cert.not_before => time
00439  */
00440 static VALUE
00441 ossl_x509_get_not_before(VALUE self)
00442 {
00443     X509 *x509;
00444     ASN1_UTCTIME *asn1time;
00445 
00446     GetX509(self, x509);
00447     if (!(asn1time = X509_get_notBefore(x509))) { /* NO DUP - don't free! */
00448         ossl_raise(eX509CertError, NULL);
00449     }
00450 
00451     return asn1time_to_time(asn1time);
00452 }
00453 
00454 /*
00455  * call-seq:
00456  *    cert.not_before = time => time
00457  */
00458 static VALUE
00459 ossl_x509_set_not_before(VALUE self, VALUE time)
00460 {
00461     X509 *x509;
00462     time_t sec;
00463 
00464     sec = time_to_time_t(time);
00465     GetX509(self, x509);
00466     if (!X509_time_adj(X509_get_notBefore(x509), 0, &sec)) {
00467         ossl_raise(eX509CertError, NULL);
00468     }
00469 
00470     return time;
00471 }
00472 
00473 /*
00474  * call-seq:
00475  *    cert.not_after => time
00476  */
00477 static VALUE
00478 ossl_x509_get_not_after(VALUE self)
00479 {
00480     X509 *x509;
00481     ASN1_TIME *asn1time;
00482 
00483     GetX509(self, x509);
00484     if (!(asn1time = X509_get_notAfter(x509))) { /* NO DUP - don't free! */
00485         ossl_raise(eX509CertError, NULL);
00486     }
00487 
00488     return asn1time_to_time(asn1time);
00489 }
00490 
00491 /*
00492  * call-seq:
00493  *    cert.not_after = time => time
00494  */
00495 static VALUE
00496 ossl_x509_set_not_after(VALUE self, VALUE time)
00497 {
00498     X509 *x509;
00499     time_t sec;
00500 
00501     sec = time_to_time_t(time);
00502     GetX509(self, x509);
00503     if (!X509_time_adj(X509_get_notAfter(x509), 0, &sec)) {
00504         ossl_raise(eX509CertError, NULL);
00505     }
00506 
00507     return time;
00508 }
00509 
00510 /*
00511  * call-seq:
00512  *    cert.public_key => key
00513  */
00514 static VALUE
00515 ossl_x509_get_public_key(VALUE self)
00516 {
00517     X509 *x509;
00518     EVP_PKEY *pkey;
00519 
00520     GetX509(self, x509);
00521     if (!(pkey = X509_get_pubkey(x509))) { /* adds an reference */
00522         ossl_raise(eX509CertError, NULL);
00523     }
00524 
00525     return ossl_pkey_new(pkey); /* NO DUP - OK */
00526 }
00527 
00528 /*
00529  * call-seq:
00530  *    cert.public_key = key => key
00531  */
00532 static VALUE
00533 ossl_x509_set_public_key(VALUE self, VALUE key)
00534 {
00535     X509 *x509;
00536 
00537     GetX509(self, x509);
00538     if (!X509_set_pubkey(x509, GetPKeyPtr(key))) { /* DUPs pkey */
00539         ossl_raise(eX509CertError, NULL);
00540     }
00541 
00542     return key;
00543 }
00544 
00545 /*
00546  * call-seq:
00547  *    cert.sign(key, digest) => self
00548  */
00549 static VALUE
00550 ossl_x509_sign(VALUE self, VALUE key, VALUE digest)
00551 {
00552     X509 *x509;
00553     EVP_PKEY *pkey;
00554     const EVP_MD *md;
00555 
00556     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
00557     md = GetDigestPtr(digest);
00558     GetX509(self, x509);
00559     if (!X509_sign(x509, pkey, md)) {
00560         ossl_raise(eX509CertError, NULL);
00561     }
00562 
00563     return self;
00564 }
00565 
00566 /*
00567  * call-seq:
00568  *    cert.verify(key) => true | false
00569  *
00570  * Checks that cert signature is made with PRIVversion of this PUBLIC 'key'
00571  */
00572 static VALUE
00573 ossl_x509_verify(VALUE self, VALUE key)
00574 {
00575     X509 *x509;
00576     EVP_PKEY *pkey;
00577     int i;
00578 
00579     pkey = GetPKeyPtr(key); /* NO NEED TO DUP */
00580     GetX509(self, x509);
00581     if ((i = X509_verify(x509, pkey)) < 0) {
00582         ossl_raise(eX509CertError, NULL);
00583     }
00584     if (i > 0) {
00585         return Qtrue;
00586     }
00587 
00588     return Qfalse;
00589 }
00590 
00591 /*
00592  * call-seq:
00593  *    cert.check_private_key(key)
00594  *
00595  * Checks if 'key' is PRIV key for this cert
00596  */
00597 static VALUE
00598 ossl_x509_check_private_key(VALUE self, VALUE key)
00599 {
00600     X509 *x509;
00601     EVP_PKEY *pkey;
00602 
00603     /* not needed private key, but should be */
00604     pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */
00605     GetX509(self, x509);
00606     if (!X509_check_private_key(x509, pkey)) {
00607         OSSL_Warning("Check private key:%s", OSSL_ErrMsg());
00608         return Qfalse;
00609     }
00610 
00611     return Qtrue;
00612 }
00613 
00614 /*
00615  * call-seq:
00616  *    cert.extensions => [extension...]
00617  */
00618 static VALUE
00619 ossl_x509_get_extensions(VALUE self)
00620 {
00621     X509 *x509;
00622     int count, i;
00623     X509_EXTENSION *ext;
00624     VALUE ary;
00625 
00626     GetX509(self, x509);
00627     count = X509_get_ext_count(x509);
00628     if (count < 0) {
00629         return rb_ary_new();
00630     }
00631     ary = rb_ary_new2(count);
00632     for (i=0; i<count; i++) {
00633         ext = X509_get_ext(x509, i); /* NO DUP - don't free! */
00634         rb_ary_push(ary, ossl_x509ext_new(ext));
00635     }
00636 
00637     return ary;
00638 }
00639 
00640 /*
00641  * call-seq:
00642  *    cert.extensions = [ext...] => [ext...]
00643  */
00644 static VALUE
00645 ossl_x509_set_extensions(VALUE self, VALUE ary)
00646 {
00647     X509 *x509;
00648     X509_EXTENSION *ext;
00649     int i;
00650 
00651     Check_Type(ary, T_ARRAY);
00652     /* All ary's members should be X509Extension */
00653     for (i=0; i<RARRAY_LEN(ary); i++) {
00654         OSSL_Check_Kind(RARRAY_PTR(ary)[i], cX509Ext);
00655     }
00656     GetX509(self, x509);
00657     sk_X509_EXTENSION_pop_free(x509->cert_info->extensions, X509_EXTENSION_free);
00658     x509->cert_info->extensions = NULL;
00659     for (i=0; i<RARRAY_LEN(ary); i++) {
00660         ext = DupX509ExtPtr(RARRAY_PTR(ary)[i]);
00661 
00662         if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
00663             X509_EXTENSION_free(ext);
00664             ossl_raise(eX509CertError, NULL);
00665         }
00666         X509_EXTENSION_free(ext);
00667     }
00668 
00669     return ary;
00670 }
00671 
00672 /*
00673  * call-seq:
00674  *    cert.add_extension(extension) => extension
00675  */
00676 static VALUE
00677 ossl_x509_add_extension(VALUE self, VALUE extension)
00678 {
00679     X509 *x509;
00680     X509_EXTENSION *ext;
00681 
00682     GetX509(self, x509);
00683     ext = DupX509ExtPtr(extension);
00684     if (!X509_add_ext(x509, ext, -1)) { /* DUPs ext - FREE it */
00685         X509_EXTENSION_free(ext);
00686         ossl_raise(eX509CertError, NULL);
00687     }
00688     X509_EXTENSION_free(ext);
00689 
00690     return extension;
00691 }
00692 
00693 static VALUE
00694 ossl_x509_inspect(VALUE self)
00695 {
00696     VALUE str;
00697     const char *cname = rb_class2name(rb_obj_class(self));
00698 
00699     str = rb_str_new2("#<");
00700     rb_str_cat2(str, cname);
00701     rb_str_cat2(str, " ");
00702 
00703     rb_str_cat2(str, "subject=");
00704     rb_str_append(str, rb_inspect(ossl_x509_get_subject(self)));
00705     rb_str_cat2(str, ", ");
00706 
00707     rb_str_cat2(str, "issuer=");
00708     rb_str_append(str, rb_inspect(ossl_x509_get_issuer(self)));
00709     rb_str_cat2(str, ", ");
00710 
00711     rb_str_cat2(str, "serial=");
00712     rb_str_append(str, rb_inspect(ossl_x509_get_serial(self)));
00713     rb_str_cat2(str, ", ");
00714 
00715     rb_str_cat2(str, "not_before=");
00716     rb_str_append(str, rb_inspect(ossl_x509_get_not_before(self)));
00717     rb_str_cat2(str, ", ");
00718 
00719     rb_str_cat2(str, "not_after=");
00720     rb_str_append(str, rb_inspect(ossl_x509_get_not_after(self)));
00721 
00722     str = rb_str_cat2(str, ">");
00723 
00724     return str;
00725 }
00726 
00727 /*
00728  * INIT
00729  */
00730 void
00731 Init_ossl_x509cert()
00732 {
00733 
00734 #if 0
00735     mOSSL = rb_define_module("OpenSSL"); /* let rdoc know about mOSSL */
00736     mX509 = rb_define_module_under(mOSSL, "X509");
00737 #endif
00738 
00739     eX509CertError = rb_define_class_under(mX509, "CertificateError", eOSSLError);
00740 
00741     /* Document-class: OpenSSL::X509::Certificate
00742      *
00743      * Implementation of an X.509 certificate as specified in RFC 5280.
00744      * Provides access to a certificate's attributes and allows certificates
00745      * to be read from a string, but also supports the creation of new
00746      * certificates from scratch.
00747      *
00748      * === Reading a certificate from a file
00749      *
00750      * Certificate is capable of handling DER-encoded certificates and
00751      * certificates encoded in OpenSSL's PEM format.
00752      *
00753      *   raw = File.read "cert.cer" # DER- or PEM-encoded
00754      *   certificate = OpenSSL::X509::Certificate.new raw
00755      *
00756      * === Saving a certificate to a file
00757      *
00758      * A certificate may be encoded in DER format
00759      *
00760      *   cert = ...
00761      *   File.open("cert.cer", "wb") { |f| f.print cert.to_der }
00762      *
00763      * or in PEM format
00764      *
00765      *   cert = ...
00766      *   File.open("cert.pem", "wb") { |f| f.print cert.to_pem }
00767      *
00768      * X.509 certificates are associated with a private/public key pair,
00769      * typically a RSA, DSA or ECC key (see also OpenSSL::PKey::RSA,
00770      * OpenSSL::PKey::DSA and OpenSSL::PKey::EC), the public key itself is
00771      * stored within the certificate and can be accessed in form of an
00772      * OpenSSL::PKey. Certificates are typically used to be able to associate
00773      * some form of identity with a key pair, for example web servers serving
00774      * pages over HTTPs use certificates to authenticate themselves to the user.
00775      *
00776      * The public key infrastructure (PKI) model relies on trusted certificate
00777      * authorities ("root CAs") that issue these certificates, so that end
00778      * users need to base their trust just on a selected few authorities
00779      * that themselves again vouch for subordinate CAs issuing their
00780      * certificates to end users.
00781      *
00782      * The OpenSSL::X509 module provides the tools to set up an independent
00783      * PKI, similar to scenarios where the 'openssl' command line tool is
00784      * used for issuing certificates in a private PKI.
00785      *
00786      * === Creating a root CA certificate and an end-entity certificate
00787      *
00788      * First, we need to create a "self-signed" root certificate. To do so,
00789      * we need to generate a key first. Please note that the choice of "1"
00790      * as a serial number is considered a security flaw for real certificates.
00791      * Secure choices are integers in the two-digit byte range and ideally
00792      * not sequential but secure random numbers, steps omitted here to keep
00793      * the example concise.
00794      *
00795      *   root_key = OpenSSL::PKey::RSA.new 2048 # the CA's public/private key
00796      *   root_ca = OpenSSL::X509::Certificate.new
00797      *   root_ca.version = 2 # cf. RFC 5280 - to make it a "v3" certificate
00798      *   root_ca.serial = 1
00799      *   root_ca.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby CA"
00800      *   root_ca.issuer = root_ca.subject # root CA's are "self-signed"
00801      *   root_ca.public_key = root_key.public_key
00802      *   root_ca.not_before = Time.now
00803      *   root_ca.not_after = root_ca.not_before + 2 * 365 * 24 * 60 * 60 # 2 years validity
00804      *   ef = OpenSSL::X509::ExtensionFactory.new
00805      *   ef.subject_certificate = root_ca
00806      *   ef.issuer_certificate = root_ca
00807      *   root_ca.add_extension(ef.create_extension("basicConstraints","CA:TRUE",true))
00808      *   root_ca.add_extension(ef.create_extension("keyUsage","keyCertSign, cRLSign", true))
00809      *   root_ca.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
00810      *   root_ca.add_extension(ef.create_extension("authorityKeyIdentifier","keyid:always",false))
00811      *   root_ca.sign(root_key, OpenSSL::Digest::SHA256.new)
00812      *
00813      * The next step is to create the end-entity certificate using the root CA
00814      * certificate.
00815      *
00816      *   key = OpenSSL::PKey::RSA.new 2048
00817      *   cert = OpenSSL::X509::Certificate.new
00818      *   cert.version = 2
00819      *   cert.serial = 2
00820      *   cert.subject = OpenSSL::X509::Name.parse "/DC=org/DC=ruby-lang/CN=Ruby certificate"
00821      *   cert.issuer = root_ca.subject # root CA is the issuer
00822      *   cert.public_key = key.public_key
00823      *   cert.not_before = Time.now
00824      *   cert.not_after = cert.not_before + 1 * 365 * 24 * 60 * 60 # 1 years validity
00825      *   ef = OpenSSL::X509::ExtensionFactory.new
00826      *   ef.subject_certificate = cert
00827      *   ef.issuer_certificate = root_ca
00828      *   cert.add_extension(ef.create_extension("keyUsage","digitalSignature", true))
00829      *   cert.add_extension(ef.create_extension("subjectKeyIdentifier","hash",false))
00830      *   cert.sign(root_key, OpenSSL::Digest::SHA256.new)
00831      *
00832      */
00833     cX509Cert = rb_define_class_under(mX509, "Certificate", rb_cObject);
00834 
00835     rb_define_alloc_func(cX509Cert, ossl_x509_alloc);
00836     rb_define_method(cX509Cert, "initialize", ossl_x509_initialize, -1);
00837     rb_define_copy_func(cX509Cert, ossl_x509_copy);
00838 
00839     rb_define_method(cX509Cert, "to_der", ossl_x509_to_der, 0);
00840     rb_define_method(cX509Cert, "to_pem", ossl_x509_to_pem, 0);
00841     rb_define_alias(cX509Cert, "to_s", "to_pem");
00842     rb_define_method(cX509Cert, "to_text", ossl_x509_to_text, 0);
00843     rb_define_method(cX509Cert, "version", ossl_x509_get_version, 0);
00844     rb_define_method(cX509Cert, "version=", ossl_x509_set_version, 1);
00845     rb_define_method(cX509Cert, "signature_algorithm", ossl_x509_get_signature_algorithm, 0);
00846     rb_define_method(cX509Cert, "serial", ossl_x509_get_serial, 0);
00847     rb_define_method(cX509Cert, "serial=", ossl_x509_set_serial, 1);
00848     rb_define_method(cX509Cert, "subject", ossl_x509_get_subject, 0);
00849     rb_define_method(cX509Cert, "subject=", ossl_x509_set_subject, 1);
00850     rb_define_method(cX509Cert, "issuer", ossl_x509_get_issuer, 0);
00851     rb_define_method(cX509Cert, "issuer=", ossl_x509_set_issuer, 1);
00852     rb_define_method(cX509Cert, "not_before", ossl_x509_get_not_before, 0);
00853     rb_define_method(cX509Cert, "not_before=", ossl_x509_set_not_before, 1);
00854     rb_define_method(cX509Cert, "not_after", ossl_x509_get_not_after, 0);
00855     rb_define_method(cX509Cert, "not_after=", ossl_x509_set_not_after, 1);
00856     rb_define_method(cX509Cert, "public_key", ossl_x509_get_public_key, 0);
00857     rb_define_method(cX509Cert, "public_key=", ossl_x509_set_public_key, 1);
00858     rb_define_method(cX509Cert, "sign", ossl_x509_sign, 2);
00859     rb_define_method(cX509Cert, "verify", ossl_x509_verify, 1);
00860     rb_define_method(cX509Cert, "check_private_key", ossl_x509_check_private_key, 1);
00861     rb_define_method(cX509Cert, "extensions", ossl_x509_get_extensions, 0);
00862     rb_define_method(cX509Cert, "extensions=", ossl_x509_set_extensions, 1);
00863     rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1);
00864     rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0);
00865 }
00866 
00867