openssl_pkcs8 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,10 +5,20 @@ is part of standard Ruby distributions.
5
5
 
6
6
  Example:
7
7
 
8
- key = OpenSSL::PKey::RSA.new(1024)
8
+ key = OpenSSL::PKey::RSA.new(1024)
9
+
10
+ key.to_pem_pkcs8
11
+ # => "-----BEGIN PRIVATE KEY----- ..."
12
+
13
+ This will export the private key in PKCS8 format, and will export public keys
14
+ in the PUBKEY format used by OpenSSL. Note the absence of "RSA" in both of
15
+ the headers.
9
16
 
10
- key.to_pem_pkcs8
11
- # => "-----BEGIN PRIVATE KEY----- ..."
17
+ == Installation
18
+
19
+ Using the Gem distribution is probably easiest:
20
+
21
+ gem install openssl_pkcs8
12
22
 
13
23
  == Copyright
14
24
 
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,191 @@
1
+ #include "ruby.h"
2
+
3
+ #include <openssl/err.h>
4
+ #include <openssl/ossl_typ.h>
5
+ #include <openssl/engine.h>
6
+ #include <openssl/evp.h>
7
+ #include <openssl/asn1_mac.h>
8
+ #include <openssl/x509v3.h>
9
+ #include <openssl/ssl.h>
10
+ #include <openssl/pkcs12.h>
11
+ #include <openssl/pkcs7.h>
12
+ #include <openssl/hmac.h>
13
+ #include <openssl/rand.h>
14
+ #include <openssl/conf.h>
15
+ #include <openssl/conf_api.h>
16
+
17
+ VALUE mOSSL;
18
+ VALUE mPKey;
19
+ VALUE cRSA;
20
+ VALUE eRSAError;
21
+ VALUE ePKeyError;
22
+ VALUE eOSSLError;
23
+ VALUE cCipher;
24
+
25
+ #define GetPKey(obj, pkey) do {\
26
+ Data_Get_Struct(obj, EVP_PKEY, pkey);\
27
+ if (!pkey) { \
28
+ rb_raise(rb_eRuntimeError, "PKEY wasn't initialized!");\
29
+ } \
30
+ } while (0)
31
+ #define GetPKeyRSA(obj, pkey) do { \
32
+ GetPKey(obj, pkey); \
33
+ if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) { /* PARANOIA? */ \
34
+ ossl_raise(rb_eRuntimeError, "THIS IS NOT A RSA!") ; \
35
+ } \
36
+ } while (0)
37
+ #define OSSL_PKEY_SET_PRIVATE(obj) rb_iv_set((obj), "private", Qtrue)
38
+ #define OSSL_PKEY_SET_PUBLIC(obj) rb_iv_set((obj), "private", Qfalse)
39
+ #define OSSL_PKEY_IS_PRIVATE(obj) (rb_iv_get((obj), "private") == Qtrue)
40
+ #define RSA_HAS_PRIVATE(rsa) ((rsa)->p && (rsa)->q)
41
+ #define GetCipher(obj, ctx) do { \
42
+ Data_Get_Struct(obj, EVP_CIPHER_CTX, ctx); \
43
+ if (!ctx) { \
44
+ ossl_raise(rb_eRuntimeError, "Cipher not inititalized!"); \
45
+ } \
46
+ } while (0)
47
+ #define SafeGetCipher(obj, ctx) do { \
48
+ OSSL_Check_Kind(obj, cCipher); \
49
+ GetCipher(obj, ctx); \
50
+ } while (0)
51
+
52
+ VALUE ossl_membio2str0(BIO *bio)
53
+ {
54
+ VALUE ret;
55
+ BUF_MEM *buf;
56
+
57
+ BIO_get_mem_ptr(bio, &buf);
58
+ ret = rb_str_new(buf->data, buf->length);
59
+
60
+ return ret;
61
+ }
62
+
63
+ VALUE ossl_protect_membio2str(BIO *bio, int *status)
64
+ {
65
+ return rb_protect((VALUE(*)_((VALUE)))ossl_membio2str0, (VALUE)bio, status);
66
+ }
67
+
68
+ VALUE ossl_membio2str(BIO *bio)
69
+ {
70
+ VALUE ret;
71
+ int status = 0;
72
+
73
+ ret = ossl_protect_membio2str(bio, &status);
74
+ BIO_free(bio);
75
+ if(status) rb_jump_tag(status);
76
+
77
+ return ret;
78
+ }
79
+
80
+ const EVP_CIPHER* GetCipherPtr(VALUE obj)
81
+ {
82
+ EVP_CIPHER_CTX* ctx;
83
+
84
+ SafeGetCipher(obj, ctx);
85
+
86
+ return EVP_CIPHER_CTX_cipher(ctx);
87
+ }
88
+
89
+ static VALUE openssl_pkcs8_pem_passwd_cb0(VALUE flag)
90
+ {
91
+ VALUE pass;
92
+
93
+ pass = rb_yield(flag);
94
+ SafeStringValue(pass);
95
+
96
+ return pass;
97
+ }
98
+
99
+ int openssl_pkcs8_pem_passwd_cb(char *buf, int max_len, int flag, void *pwd)
100
+ {
101
+ int len, status = 0;
102
+ VALUE rflag, pass;
103
+
104
+ if (pwd || !rb_block_given_p())
105
+ return PEM_def_callback(buf, max_len, flag, pwd);
106
+
107
+ while (1) {
108
+ /*
109
+ * when the flag is nonzero, this passphrase
110
+ * will be used to perform encryption; otherwise it will
111
+ * be used to perform decryption.
112
+ */
113
+ rflag = flag ? Qtrue : Qfalse;
114
+ pass = rb_protect(openssl_pkcs8_pem_passwd_cb0, rflag, &status);
115
+ if (status) return -1; /* exception was raised. */
116
+ len = (int) RSTRING_LEN(pass);
117
+ if (len < 4) { /* 4 is OpenSSL hardcoded limit */
118
+ rb_warning("password must be longer than 4 bytes");
119
+ continue;
120
+ }
121
+ if (len > max_len) {
122
+ rb_warning("password must be shorter then %d bytes", max_len-1);
123
+ continue;
124
+ }
125
+ memcpy(buf, RSTRING_PTR(pass), len);
126
+ break;
127
+ }
128
+ return len;
129
+ }
130
+
131
+ static VALUE openssl_rsa_to_pem_pkcs8(int argc, VALUE *argv, VALUE self)
132
+ {
133
+ EVP_PKEY *pkey;
134
+ BIO *out;
135
+ const EVP_CIPHER *ciph = NULL;
136
+ char *passwd = NULL;
137
+ VALUE cipher, pass;
138
+
139
+ GetPKeyRSA(self, pkey);
140
+
141
+ rb_scan_args(argc, argv, "02", &cipher, &pass);
142
+
143
+ if (!NIL_P(cipher))
144
+ {
145
+ ciph = GetCipherPtr(cipher);
146
+ if (!NIL_P(pass))
147
+ {
148
+ passwd = StringValuePtr(pass);
149
+ }
150
+ }
151
+
152
+ if (!(out = BIO_new(BIO_s_mem())))
153
+ {
154
+ ossl_raise(eRSAError, NULL);
155
+ }
156
+
157
+ if (RSA_HAS_PRIVATE(pkey->pkey.rsa))
158
+ {
159
+ if (!PEM_write_bio_PKCS8PrivateKey(
160
+ out, pkey, ciph,
161
+ NULL, 0, openssl_pkcs8_pem_passwd_cb, passwd))
162
+ {
163
+ BIO_free(out);
164
+ ossl_raise(eRSAError, NULL);
165
+ }
166
+ }
167
+ else
168
+ {
169
+ if (!PEM_write_bio_PUBKEY(out, pkey))
170
+ {
171
+ BIO_free(out);
172
+ ossl_raise(eRSAError, NULL);
173
+ }
174
+ }
175
+
176
+ return ossl_membio2str(out);
177
+ }
178
+
179
+ void Init_openssl_pkcs8()
180
+ {
181
+ mOSSL = rb_const_get(rb_cObject, rb_intern("OpenSSL"));
182
+ mPKey = rb_const_get(mOSSL, rb_intern("PKey"));
183
+ cRSA = rb_const_get(mPKey, rb_intern("RSA"));
184
+ cCipher = rb_const_get(mOSSL, rb_intern("Cipher"));
185
+
186
+ eOSSLError = rb_const_get(mOSSL,rb_intern("OpenSSLError"));
187
+ ePKeyError = rb_const_get(mPKey, rb_intern("PKeyError"));
188
+ eRSAError = rb_const_get(mPKey, rb_intern("RSAError"));
189
+
190
+ rb_define_method(cRSA, "to_pem_pkcs8", openssl_rsa_to_pem_pkcs8, -1);
191
+ }
@@ -0,0 +1,3 @@
1
+ require 'openssl'
2
+
3
+ require 'openssl_pkcs8/openssl_pkcs8'
Binary file
@@ -0,0 +1,54 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "openssl_pkcs8"
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Scott Tadman"]
12
+ s.date = "2012-01-16"
13
+ s.description = "Adds PKCS8 key format support to OpenSSL::PKey::RSA"
14
+ s.email = "github@tadman.ca"
15
+ s.extensions = ["ext/openssl_pkcs8/extconf.rb"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "ext/openssl_pkcs8/extconf.rb",
28
+ "ext/openssl_pkcs8/openssl_pkcs8.c",
29
+ "ext/openssl_pkcs8/openssl_pkcs8.o",
30
+ "lib/openssl_pkcs8.rb",
31
+ "openssl-pkcs8.o",
32
+ "openssl_pkcs8.gemspec",
33
+ "test/helper.rb",
34
+ "test/test_openssl_pkcs8.rb"
35
+ ]
36
+ s.homepage = "http://github.com/twg/openssl_pkcs8"
37
+ s.licenses = ["MIT"]
38
+ s.require_paths = ["lib"]
39
+ s.rubygems_version = "1.8.11"
40
+ s.summary = "OpenSSL RSA PKCS8 Extension"
41
+
42
+ if s.respond_to? :specification_version then
43
+ s.specification_version = 3
44
+
45
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
47
+ else
48
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
49
+ end
50
+ else
51
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
52
+ end
53
+ end
54
+
@@ -0,0 +1,24 @@
1
+ require 'helper'
2
+
3
+ class TestOpensslPkcs8 < Test::Unit::TestCase
4
+ def test_rsa_key
5
+ key = OpenSSL::PKey::RSA.new(1024)
6
+
7
+ assert key.respond_to?(:to_pem_pkcs8), "Extension method not defined"
8
+
9
+ encoded = key.to_pem_pkcs8
10
+
11
+ puts key.to_pem
12
+ puts encoded
13
+
14
+ assert encoded
15
+
16
+ encoded_public = key.public_key.to_pem_pkcs8
17
+
18
+ puts key.public_key.to_pem
19
+ puts encoded_public
20
+
21
+ assert encoded_public
22
+ assert encoded_public.match(/BEGIN PUBLIC KEY/)
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openssl_pkcs8
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2012-01-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: jeweler
16
- requirement: &2153405400 !ruby/object:Gem::Requirement
16
+ requirement: &2153224500 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 1.6.4
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2153405400
24
+ version_requirements: *2153224500
25
25
  description: Adds PKCS8 key format support to OpenSSL::PKey::RSA
26
26
  email: github@tadman.ca
27
27
  executables: []
@@ -36,8 +36,15 @@ files:
36
36
  - LICENSE.txt
37
37
  - README.rdoc
38
38
  - Rakefile
39
- - test/helper.rb
39
+ - VERSION
40
40
  - ext/openssl_pkcs8/extconf.rb
41
+ - ext/openssl_pkcs8/openssl_pkcs8.c
42
+ - ext/openssl_pkcs8/openssl_pkcs8.o
43
+ - lib/openssl_pkcs8.rb
44
+ - openssl-pkcs8.o
45
+ - openssl_pkcs8.gemspec
46
+ - test/helper.rb
47
+ - test/test_openssl_pkcs8.rb
41
48
  homepage: http://github.com/twg/openssl_pkcs8
42
49
  licenses:
43
50
  - MIT