openssl_pkcs8 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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