openssl 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openssl might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/BSDL +22 -0
- data/CONTRIBUTING.md +130 -0
- data/History.md +118 -0
- data/LICENSE.txt +56 -0
- data/README.md +70 -0
- data/ext/openssl/deprecation.rb +26 -0
- data/ext/openssl/extconf.rb +158 -0
- data/ext/openssl/openssl_missing.c +173 -0
- data/ext/openssl/openssl_missing.h +244 -0
- data/ext/openssl/ossl.c +1201 -0
- data/ext/openssl/ossl.h +222 -0
- data/ext/openssl/ossl_asn1.c +1992 -0
- data/ext/openssl/ossl_asn1.h +66 -0
- data/ext/openssl/ossl_bio.c +87 -0
- data/ext/openssl/ossl_bio.h +19 -0
- data/ext/openssl/ossl_bn.c +1153 -0
- data/ext/openssl/ossl_bn.h +23 -0
- data/ext/openssl/ossl_cipher.c +1085 -0
- data/ext/openssl/ossl_cipher.h +20 -0
- data/ext/openssl/ossl_config.c +89 -0
- data/ext/openssl/ossl_config.h +19 -0
- data/ext/openssl/ossl_digest.c +453 -0
- data/ext/openssl/ossl_digest.h +20 -0
- data/ext/openssl/ossl_engine.c +580 -0
- data/ext/openssl/ossl_engine.h +19 -0
- data/ext/openssl/ossl_hmac.c +398 -0
- data/ext/openssl/ossl_hmac.h +18 -0
- data/ext/openssl/ossl_ns_spki.c +406 -0
- data/ext/openssl/ossl_ns_spki.h +19 -0
- data/ext/openssl/ossl_ocsp.c +2013 -0
- data/ext/openssl/ossl_ocsp.h +23 -0
- data/ext/openssl/ossl_pkcs12.c +259 -0
- data/ext/openssl/ossl_pkcs12.h +13 -0
- data/ext/openssl/ossl_pkcs5.c +180 -0
- data/ext/openssl/ossl_pkcs5.h +6 -0
- data/ext/openssl/ossl_pkcs7.c +1125 -0
- data/ext/openssl/ossl_pkcs7.h +20 -0
- data/ext/openssl/ossl_pkey.c +435 -0
- data/ext/openssl/ossl_pkey.h +245 -0
- data/ext/openssl/ossl_pkey_dh.c +650 -0
- data/ext/openssl/ossl_pkey_dsa.c +672 -0
- data/ext/openssl/ossl_pkey_ec.c +1899 -0
- data/ext/openssl/ossl_pkey_rsa.c +768 -0
- data/ext/openssl/ossl_rand.c +238 -0
- data/ext/openssl/ossl_rand.h +18 -0
- data/ext/openssl/ossl_ssl.c +2679 -0
- data/ext/openssl/ossl_ssl.h +41 -0
- data/ext/openssl/ossl_ssl_session.c +352 -0
- data/ext/openssl/ossl_version.h +15 -0
- data/ext/openssl/ossl_x509.c +186 -0
- data/ext/openssl/ossl_x509.h +119 -0
- data/ext/openssl/ossl_x509attr.c +328 -0
- data/ext/openssl/ossl_x509cert.c +860 -0
- data/ext/openssl/ossl_x509crl.c +565 -0
- data/ext/openssl/ossl_x509ext.c +480 -0
- data/ext/openssl/ossl_x509name.c +547 -0
- data/ext/openssl/ossl_x509req.c +492 -0
- data/ext/openssl/ossl_x509revoked.c +279 -0
- data/ext/openssl/ossl_x509store.c +846 -0
- data/ext/openssl/ruby_missing.h +32 -0
- data/lib/openssl.rb +21 -0
- data/lib/openssl/bn.rb +39 -0
- data/lib/openssl/buffering.rb +451 -0
- data/lib/openssl/cipher.rb +67 -0
- data/lib/openssl/config.rb +473 -0
- data/lib/openssl/digest.rb +78 -0
- data/lib/openssl/pkey.rb +44 -0
- data/lib/openssl/ssl.rb +416 -0
- data/lib/openssl/x509.rb +176 -0
- metadata +178 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2003 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* Copyright (C) 2003 GOTOU Yuuzou <gotoyuzo@notwork.org>
|
5
|
+
* All rights reserved.
|
6
|
+
*/
|
7
|
+
/*
|
8
|
+
* This program is licensed under the same licence as Ruby.
|
9
|
+
* (See the file 'LICENCE'.)
|
10
|
+
*/
|
11
|
+
#if !defined(_OSSL_OCSP_H_)
|
12
|
+
#define _OSSL_OCSP_H_
|
13
|
+
|
14
|
+
#if !defined(OPENSSL_NO_OCSP)
|
15
|
+
extern VALUE mOCSP;
|
16
|
+
extern VALUE cOPCSReq;
|
17
|
+
extern VALUE cOPCSRes;
|
18
|
+
extern VALUE cOPCSBasicRes;
|
19
|
+
#endif
|
20
|
+
|
21
|
+
void Init_ossl_ocsp(void);
|
22
|
+
|
23
|
+
#endif /* _OSSL_OCSP_H_ */
|
@@ -0,0 +1,259 @@
|
|
1
|
+
/*
|
2
|
+
* This program is licensed under the same licence as Ruby.
|
3
|
+
* (See the file 'LICENCE'.)
|
4
|
+
*/
|
5
|
+
#include "ossl.h"
|
6
|
+
|
7
|
+
#define NewPKCS12(klass) \
|
8
|
+
TypedData_Wrap_Struct((klass), &ossl_pkcs12_type, 0)
|
9
|
+
|
10
|
+
#define SetPKCS12(obj, p12) do { \
|
11
|
+
if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
|
12
|
+
RTYPEDDATA_DATA(obj) = (p12); \
|
13
|
+
} while (0)
|
14
|
+
|
15
|
+
#define GetPKCS12(obj, p12) do { \
|
16
|
+
TypedData_Get_Struct((obj), PKCS12, &ossl_pkcs12_type, (p12)); \
|
17
|
+
if(!(p12)) ossl_raise(rb_eRuntimeError, "PKCS12 wasn't initialized."); \
|
18
|
+
} while (0)
|
19
|
+
|
20
|
+
#define SafeGetPKCS12(obj, p12) do { \
|
21
|
+
OSSL_Check_Kind((obj), cPKCS12); \
|
22
|
+
GetPKCS12((obj), (p12)); \
|
23
|
+
} while (0)
|
24
|
+
|
25
|
+
#define ossl_pkcs12_set_key(o,v) rb_iv_set((o), "@key", (v))
|
26
|
+
#define ossl_pkcs12_set_cert(o,v) rb_iv_set((o), "@certificate", (v))
|
27
|
+
#define ossl_pkcs12_set_ca_certs(o,v) rb_iv_set((o), "@ca_certs", (v))
|
28
|
+
#define ossl_pkcs12_get_key(o) rb_iv_get((o), "@key")
|
29
|
+
#define ossl_pkcs12_get_cert(o) rb_iv_get((o), "@certificate")
|
30
|
+
#define ossl_pkcs12_get_ca_certs(o) rb_iv_get((o), "@ca_certs")
|
31
|
+
|
32
|
+
/*
|
33
|
+
* Classes
|
34
|
+
*/
|
35
|
+
VALUE cPKCS12;
|
36
|
+
VALUE ePKCS12Error;
|
37
|
+
|
38
|
+
/*
|
39
|
+
* Private
|
40
|
+
*/
|
41
|
+
static void
|
42
|
+
ossl_pkcs12_free(void *ptr)
|
43
|
+
{
|
44
|
+
PKCS12_free(ptr);
|
45
|
+
}
|
46
|
+
|
47
|
+
static const rb_data_type_t ossl_pkcs12_type = {
|
48
|
+
"OpenSSL/PKCS12",
|
49
|
+
{
|
50
|
+
0, ossl_pkcs12_free,
|
51
|
+
},
|
52
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
53
|
+
};
|
54
|
+
|
55
|
+
static VALUE
|
56
|
+
ossl_pkcs12_s_allocate(VALUE klass)
|
57
|
+
{
|
58
|
+
PKCS12 *p12;
|
59
|
+
VALUE obj;
|
60
|
+
|
61
|
+
obj = NewPKCS12(klass);
|
62
|
+
if(!(p12 = PKCS12_new())) ossl_raise(ePKCS12Error, NULL);
|
63
|
+
SetPKCS12(obj, p12);
|
64
|
+
|
65
|
+
return obj;
|
66
|
+
}
|
67
|
+
|
68
|
+
static VALUE
|
69
|
+
ossl_pkcs12_initialize_copy(VALUE self, VALUE other)
|
70
|
+
{
|
71
|
+
PKCS12 *p12, *p12_old, *p12_new;
|
72
|
+
|
73
|
+
rb_check_frozen(self);
|
74
|
+
GetPKCS12(self, p12_old);
|
75
|
+
SafeGetPKCS12(other, p12);
|
76
|
+
|
77
|
+
p12_new = ASN1_dup((i2d_of_void *)i2d_PKCS12, (d2i_of_void *)d2i_PKCS12, (char *)p12);
|
78
|
+
if (!p12_new)
|
79
|
+
ossl_raise(ePKCS12Error, "ASN1_dup");
|
80
|
+
|
81
|
+
SetPKCS12(self, p12_new);
|
82
|
+
PKCS12_free(p12_old);
|
83
|
+
|
84
|
+
return self;
|
85
|
+
}
|
86
|
+
|
87
|
+
/*
|
88
|
+
* call-seq:
|
89
|
+
* PKCS12.create(pass, name, key, cert [, ca, [, key_pbe [, cert_pbe [, key_iter [, mac_iter [, keytype]]]]]])
|
90
|
+
*
|
91
|
+
* === Parameters
|
92
|
+
* * +pass+ - string
|
93
|
+
* * +name+ - A string describing the key.
|
94
|
+
* * +key+ - Any PKey.
|
95
|
+
* * +cert+ - A X509::Certificate.
|
96
|
+
* * The public_key portion of the certificate must contain a valid public key.
|
97
|
+
* * The not_before and not_after fields must be filled in.
|
98
|
+
* * +ca+ - An optional array of X509::Certificate's.
|
99
|
+
* * +key_pbe+ - string
|
100
|
+
* * +cert_pbe+ - string
|
101
|
+
* * +key_iter+ - integer
|
102
|
+
* * +mac_iter+ - integer
|
103
|
+
* * +keytype+ - An integer representing an MSIE specific extension.
|
104
|
+
*
|
105
|
+
* Any optional arguments may be supplied as nil to preserve the OpenSSL defaults.
|
106
|
+
*
|
107
|
+
* See the OpenSSL documentation for PKCS12_create().
|
108
|
+
*/
|
109
|
+
static VALUE
|
110
|
+
ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self)
|
111
|
+
{
|
112
|
+
VALUE pass, name, pkey, cert, ca, key_nid, cert_nid, key_iter, mac_iter, keytype;
|
113
|
+
VALUE obj;
|
114
|
+
char *passphrase, *friendlyname;
|
115
|
+
EVP_PKEY *key;
|
116
|
+
X509 *x509;
|
117
|
+
STACK_OF(X509) *x509s;
|
118
|
+
int nkey = 0, ncert = 0, kiter = 0, miter = 0, ktype = 0;
|
119
|
+
PKCS12 *p12;
|
120
|
+
|
121
|
+
rb_scan_args(argc, argv, "46", &pass, &name, &pkey, &cert, &ca, &key_nid, &cert_nid, &key_iter, &mac_iter, &keytype);
|
122
|
+
passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
|
123
|
+
friendlyname = NIL_P(name) ? NULL : StringValueCStr(name);
|
124
|
+
key = GetPKeyPtr(pkey);
|
125
|
+
x509 = GetX509CertPtr(cert);
|
126
|
+
/* TODO: make a VALUE to nid function */
|
127
|
+
if (!NIL_P(key_nid)) {
|
128
|
+
if ((nkey = OBJ_txt2nid(StringValueCStr(key_nid))) == NID_undef)
|
129
|
+
ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, key_nid);
|
130
|
+
}
|
131
|
+
if (!NIL_P(cert_nid)) {
|
132
|
+
if ((ncert = OBJ_txt2nid(StringValueCStr(cert_nid))) == NID_undef)
|
133
|
+
ossl_raise(rb_eArgError, "Unknown PBE algorithm %"PRIsVALUE, cert_nid);
|
134
|
+
}
|
135
|
+
if (!NIL_P(key_iter))
|
136
|
+
kiter = NUM2INT(key_iter);
|
137
|
+
if (!NIL_P(mac_iter))
|
138
|
+
miter = NUM2INT(mac_iter);
|
139
|
+
if (!NIL_P(keytype))
|
140
|
+
ktype = NUM2INT(keytype);
|
141
|
+
|
142
|
+
obj = NewPKCS12(cPKCS12);
|
143
|
+
x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca);
|
144
|
+
p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s,
|
145
|
+
nkey, ncert, kiter, miter, ktype);
|
146
|
+
sk_X509_pop_free(x509s, X509_free);
|
147
|
+
if(!p12) ossl_raise(ePKCS12Error, NULL);
|
148
|
+
SetPKCS12(obj, p12);
|
149
|
+
|
150
|
+
ossl_pkcs12_set_key(obj, pkey);
|
151
|
+
ossl_pkcs12_set_cert(obj, cert);
|
152
|
+
ossl_pkcs12_set_ca_certs(obj, ca);
|
153
|
+
|
154
|
+
return obj;
|
155
|
+
}
|
156
|
+
|
157
|
+
/*
|
158
|
+
* call-seq:
|
159
|
+
* PKCS12.new -> pkcs12
|
160
|
+
* PKCS12.new(str) -> pkcs12
|
161
|
+
* PKCS12.new(str, pass) -> pkcs12
|
162
|
+
*
|
163
|
+
* === Parameters
|
164
|
+
* * +str+ - Must be a DER encoded PKCS12 string.
|
165
|
+
* * +pass+ - string
|
166
|
+
*/
|
167
|
+
static VALUE
|
168
|
+
ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self)
|
169
|
+
{
|
170
|
+
BIO *in;
|
171
|
+
VALUE arg, pass, pkey, cert, ca;
|
172
|
+
char *passphrase;
|
173
|
+
EVP_PKEY *key;
|
174
|
+
X509 *x509;
|
175
|
+
STACK_OF(X509) *x509s = NULL;
|
176
|
+
int st = 0;
|
177
|
+
PKCS12 *pkcs = DATA_PTR(self);
|
178
|
+
|
179
|
+
if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self;
|
180
|
+
passphrase = NIL_P(pass) ? NULL : StringValueCStr(pass);
|
181
|
+
in = ossl_obj2bio(arg);
|
182
|
+
d2i_PKCS12_bio(in, &pkcs);
|
183
|
+
DATA_PTR(self) = pkcs;
|
184
|
+
BIO_free(in);
|
185
|
+
|
186
|
+
pkey = cert = ca = Qnil;
|
187
|
+
/* OpenSSL's bug; PKCS12_parse() puts errors even if it succeeds.
|
188
|
+
* Fixed in OpenSSL 1.0.0t, 1.0.1p, 1.0.2d */
|
189
|
+
ERR_set_mark();
|
190
|
+
if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s))
|
191
|
+
ossl_raise(ePKCS12Error, "PKCS12_parse");
|
192
|
+
ERR_pop_to_mark();
|
193
|
+
pkey = rb_protect((VALUE (*)(VALUE))ossl_pkey_new, (VALUE)key,
|
194
|
+
&st); /* NO DUP */
|
195
|
+
if(st) goto err;
|
196
|
+
cert = rb_protect((VALUE (*)(VALUE))ossl_x509_new, (VALUE)x509, &st);
|
197
|
+
if(st) goto err;
|
198
|
+
if(x509s){
|
199
|
+
ca =
|
200
|
+
rb_protect((VALUE (*)(VALUE))ossl_x509_sk2ary, (VALUE)x509s, &st);
|
201
|
+
if(st) goto err;
|
202
|
+
}
|
203
|
+
|
204
|
+
err:
|
205
|
+
X509_free(x509);
|
206
|
+
sk_X509_pop_free(x509s, X509_free);
|
207
|
+
ossl_pkcs12_set_key(self, pkey);
|
208
|
+
ossl_pkcs12_set_cert(self, cert);
|
209
|
+
ossl_pkcs12_set_ca_certs(self, ca);
|
210
|
+
if(st) rb_jump_tag(st);
|
211
|
+
|
212
|
+
return self;
|
213
|
+
}
|
214
|
+
|
215
|
+
static VALUE
|
216
|
+
ossl_pkcs12_to_der(VALUE self)
|
217
|
+
{
|
218
|
+
PKCS12 *p12;
|
219
|
+
VALUE str;
|
220
|
+
long len;
|
221
|
+
unsigned char *p;
|
222
|
+
|
223
|
+
GetPKCS12(self, p12);
|
224
|
+
if((len = i2d_PKCS12(p12, NULL)) <= 0)
|
225
|
+
ossl_raise(ePKCS12Error, NULL);
|
226
|
+
str = rb_str_new(0, len);
|
227
|
+
p = (unsigned char *)RSTRING_PTR(str);
|
228
|
+
if(i2d_PKCS12(p12, &p) <= 0)
|
229
|
+
ossl_raise(ePKCS12Error, NULL);
|
230
|
+
ossl_str_adjust(str, p);
|
231
|
+
|
232
|
+
return str;
|
233
|
+
}
|
234
|
+
|
235
|
+
void
|
236
|
+
Init_ossl_pkcs12(void)
|
237
|
+
{
|
238
|
+
#if 0
|
239
|
+
mOSSL = rb_define_module("OpenSSL");
|
240
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
241
|
+
#endif
|
242
|
+
|
243
|
+
/*
|
244
|
+
* Defines a file format commonly used to store private keys with
|
245
|
+
* accompanying public key certificates, protected with a password-based
|
246
|
+
* symmetric key.
|
247
|
+
*/
|
248
|
+
cPKCS12 = rb_define_class_under(mOSSL, "PKCS12", rb_cObject);
|
249
|
+
ePKCS12Error = rb_define_class_under(cPKCS12, "PKCS12Error", eOSSLError);
|
250
|
+
rb_define_singleton_method(cPKCS12, "create", ossl_pkcs12_s_create, -1);
|
251
|
+
|
252
|
+
rb_define_alloc_func(cPKCS12, ossl_pkcs12_s_allocate);
|
253
|
+
rb_define_copy_func(cPKCS12, ossl_pkcs12_initialize_copy);
|
254
|
+
rb_attr(cPKCS12, rb_intern("key"), 1, 0, Qfalse);
|
255
|
+
rb_attr(cPKCS12, rb_intern("certificate"), 1, 0, Qfalse);
|
256
|
+
rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse);
|
257
|
+
rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1);
|
258
|
+
rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0);
|
259
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This program is licensed under the same licence as Ruby.
|
3
|
+
* (See the file 'LICENCE'.)
|
4
|
+
*/
|
5
|
+
#if !defined(_OSSL_PKCS12_H_)
|
6
|
+
#define _OSSL_PKCS12_H_
|
7
|
+
|
8
|
+
extern VALUE cPKCS12;
|
9
|
+
extern VALUE ePKCS12Error;
|
10
|
+
|
11
|
+
void Init_ossl_pkcs12(void);
|
12
|
+
|
13
|
+
#endif /* _OSSL_PKCS12_H_ */
|
@@ -0,0 +1,180 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net>
|
3
|
+
*/
|
4
|
+
#include "ossl.h"
|
5
|
+
|
6
|
+
VALUE mPKCS5;
|
7
|
+
VALUE ePKCS5;
|
8
|
+
|
9
|
+
#ifdef HAVE_PKCS5_PBKDF2_HMAC
|
10
|
+
/*
|
11
|
+
* call-seq:
|
12
|
+
* PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string
|
13
|
+
*
|
14
|
+
* === Parameters
|
15
|
+
* * +pass+ - string
|
16
|
+
* * +salt+ - string - should be at least 8 bytes long.
|
17
|
+
* * +iter+ - integer - should be greater than 1000. 20000 is better.
|
18
|
+
* * +keylen+ - integer
|
19
|
+
* * +digest+ - a string or OpenSSL::Digest object.
|
20
|
+
*
|
21
|
+
* Available in OpenSSL >= 1.0.0.
|
22
|
+
*
|
23
|
+
* Digests other than SHA1 may not be supported by other cryptography libraries.
|
24
|
+
*/
|
25
|
+
static VALUE
|
26
|
+
ossl_pkcs5_pbkdf2_hmac(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen, VALUE digest)
|
27
|
+
{
|
28
|
+
VALUE str;
|
29
|
+
const EVP_MD *md;
|
30
|
+
int len = NUM2INT(keylen);
|
31
|
+
|
32
|
+
StringValue(pass);
|
33
|
+
StringValue(salt);
|
34
|
+
md = GetDigestPtr(digest);
|
35
|
+
|
36
|
+
str = rb_str_new(0, len);
|
37
|
+
|
38
|
+
if (PKCS5_PBKDF2_HMAC(RSTRING_PTR(pass), RSTRING_LENINT(pass),
|
39
|
+
(unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt),
|
40
|
+
NUM2INT(iter), md, len,
|
41
|
+
(unsigned char *)RSTRING_PTR(str)) != 1)
|
42
|
+
ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC");
|
43
|
+
|
44
|
+
return str;
|
45
|
+
}
|
46
|
+
#else
|
47
|
+
#define ossl_pkcs5_pbkdf2_hmac rb_f_notimplement
|
48
|
+
#endif
|
49
|
+
|
50
|
+
|
51
|
+
/*
|
52
|
+
* call-seq:
|
53
|
+
* PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
|
54
|
+
*
|
55
|
+
* === Parameters
|
56
|
+
* * +pass+ - string
|
57
|
+
* * +salt+ - string - should be at least 8 bytes long.
|
58
|
+
* * +iter+ - integer - should be greater than 1000. 20000 is better.
|
59
|
+
* * +keylen+ - integer
|
60
|
+
*
|
61
|
+
* This method is available in almost any version of OpenSSL.
|
62
|
+
*
|
63
|
+
* Conforms to RFC 2898.
|
64
|
+
*/
|
65
|
+
static VALUE
|
66
|
+
ossl_pkcs5_pbkdf2_hmac_sha1(VALUE self, VALUE pass, VALUE salt, VALUE iter, VALUE keylen)
|
67
|
+
{
|
68
|
+
VALUE str;
|
69
|
+
int len = NUM2INT(keylen);
|
70
|
+
|
71
|
+
StringValue(pass);
|
72
|
+
StringValue(salt);
|
73
|
+
|
74
|
+
str = rb_str_new(0, len);
|
75
|
+
|
76
|
+
if (PKCS5_PBKDF2_HMAC_SHA1(RSTRING_PTR(pass), RSTRING_LENINT(pass),
|
77
|
+
(const unsigned char *)RSTRING_PTR(salt), RSTRING_LENINT(salt), NUM2INT(iter),
|
78
|
+
len, (unsigned char *)RSTRING_PTR(str)) != 1)
|
79
|
+
ossl_raise(ePKCS5, "PKCS5_PBKDF2_HMAC_SHA1");
|
80
|
+
|
81
|
+
return str;
|
82
|
+
}
|
83
|
+
|
84
|
+
void
|
85
|
+
Init_ossl_pkcs5(void)
|
86
|
+
{
|
87
|
+
#if 0
|
88
|
+
mOSSL = rb_define_module("OpenSSL");
|
89
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
90
|
+
#endif
|
91
|
+
|
92
|
+
/* Document-class: OpenSSL::PKCS5
|
93
|
+
*
|
94
|
+
* Provides password-based encryption functionality based on PKCS#5.
|
95
|
+
* Typically used for securely deriving arbitrary length symmetric keys
|
96
|
+
* to be used with an OpenSSL::Cipher from passwords. Another use case
|
97
|
+
* is for storing passwords: Due to the ability to tweak the effort of
|
98
|
+
* computation by increasing the iteration count, computation can be
|
99
|
+
* slowed down artificially in order to render possible attacks infeasible.
|
100
|
+
*
|
101
|
+
* PKCS5 offers support for PBKDF2 with an OpenSSL::Digest::SHA1-based
|
102
|
+
* HMAC, or an arbitrary Digest if the underlying version of OpenSSL
|
103
|
+
* already supports it (>= 1.0.0).
|
104
|
+
*
|
105
|
+
* === Parameters
|
106
|
+
* ==== Password
|
107
|
+
* Typically an arbitrary String that represents the password to be used
|
108
|
+
* for deriving a key.
|
109
|
+
* ==== Salt
|
110
|
+
* Prevents attacks based on dictionaries of common passwords. It is a
|
111
|
+
* public value that can be safely stored along with the password (e.g.
|
112
|
+
* if PBKDF2 is used for password storage). For maximum security, a fresh,
|
113
|
+
* random salt should be generated for each stored password. According
|
114
|
+
* to PKCS#5, a salt should be at least 8 bytes long.
|
115
|
+
* ==== Iteration Count
|
116
|
+
* Allows to tweak the length that the actual computation will take. The
|
117
|
+
* larger the iteration count, the longer it will take.
|
118
|
+
* ==== Key Length
|
119
|
+
* Specifies the length in bytes of the output that will be generated.
|
120
|
+
* Typically, the key length should be larger than or equal to the output
|
121
|
+
* length of the underlying digest function, otherwise an attacker could
|
122
|
+
* simply try to brute-force the key. According to PKCS#5, security is
|
123
|
+
* limited by the output length of the underlying digest function, i.e.
|
124
|
+
* security is not improved if a key length strictly larger than the
|
125
|
+
* digest output length is chosen. Therefore, when using PKCS5 for
|
126
|
+
* password storage, it suffices to store values equal to the digest
|
127
|
+
* output length, nothing is gained by storing larger values.
|
128
|
+
*
|
129
|
+
* == Examples
|
130
|
+
* === Generating a 128 bit key for a Cipher (e.g. AES)
|
131
|
+
* pass = "secret"
|
132
|
+
* salt = OpenSSL::Random.random_bytes(16)
|
133
|
+
* iter = 20000
|
134
|
+
* key_len = 16
|
135
|
+
* key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len)
|
136
|
+
*
|
137
|
+
* === Storing Passwords
|
138
|
+
* pass = "secret"
|
139
|
+
* salt = OpenSSL::Random.random_bytes(16) #store this with the generated value
|
140
|
+
* iter = 20000
|
141
|
+
* digest = OpenSSL::Digest::SHA256.new
|
142
|
+
* len = digest.digest_length
|
143
|
+
* #the final value to be stored
|
144
|
+
* value = OpenSSL::PKCS5.pbkdf2_hmac(pass, salt, iter, len, digest)
|
145
|
+
*
|
146
|
+
* === Important Note on Checking Passwords
|
147
|
+
* When comparing passwords provided by the user with previously stored
|
148
|
+
* values, a common mistake made is comparing the two values using "==".
|
149
|
+
* Typically, "==" short-circuits on evaluation, and is therefore
|
150
|
+
* vulnerable to timing attacks. The proper way is to use a method that
|
151
|
+
* always takes the same amount of time when comparing two values, thus
|
152
|
+
* not leaking any information to potential attackers. To compare two
|
153
|
+
* values, the following could be used:
|
154
|
+
* def eql_time_cmp(a, b)
|
155
|
+
* unless a.length == b.length
|
156
|
+
* return false
|
157
|
+
* end
|
158
|
+
* cmp = b.bytes.to_a
|
159
|
+
* result = 0
|
160
|
+
* a.bytes.each_with_index {|c,i|
|
161
|
+
* result |= c ^ cmp[i]
|
162
|
+
* }
|
163
|
+
* result == 0
|
164
|
+
* end
|
165
|
+
* Please note that the premature return in case of differing lengths
|
166
|
+
* typically does not leak valuable information - when using PKCS#5, the
|
167
|
+
* length of the values to be compared is of fixed size.
|
168
|
+
*/
|
169
|
+
|
170
|
+
mPKCS5 = rb_define_module_under(mOSSL, "PKCS5");
|
171
|
+
/* Document-class: OpenSSL::PKCS5::PKCS5Error
|
172
|
+
*
|
173
|
+
* Generic Exception class that is raised if an error occurs during a
|
174
|
+
* computation.
|
175
|
+
*/
|
176
|
+
ePKCS5 = rb_define_class_under(mPKCS5, "PKCS5Error", eOSSLError);
|
177
|
+
|
178
|
+
rb_define_module_function(mPKCS5, "pbkdf2_hmac", ossl_pkcs5_pbkdf2_hmac, 5);
|
179
|
+
rb_define_module_function(mPKCS5, "pbkdf2_hmac_sha1", ossl_pkcs5_pbkdf2_hmac_sha1, 4);
|
180
|
+
}
|