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