Ruby
2.1.3p242(2014-09-19revision47630)
Main Page
Modules
Data Structures
Files
File List
Globals
ext
openssl
ossl_pkcs5.c
Go to the documentation of this file.
1
/*
2
* $Id$
3
* Copyright (C) 2007 Technorama Ltd. <oss-ruby@technorama.net>
4
*/
5
#include "
ossl.h
"
6
7
VALUE
mPKCS5
;
8
VALUE
ePKCS5
;
9
10
#ifdef HAVE_PKCS5_PBKDF2_HMAC
11
/*
12
* call-seq:
13
* PKCS5.pbkdf2_hmac(pass, salt, iter, keylen, digest) => string
14
*
15
* === Parameters
16
* * +pass+ - string
17
* * +salt+ - string - should be at least 8 bytes long.
18
* * +iter+ - integer - should be greater than 1000. 20000 is better.
19
* * +keylen+ - integer
20
* * +digest+ - a string or OpenSSL::Digest object.
21
*
22
* Available in OpenSSL 0.9.4.
23
*
24
* Digests other than SHA1 may not be supported by other cryptography libraries.
25
*/
26
static
VALUE
27
ossl_pkcs5_pbkdf2_hmac
(
VALUE
self
,
VALUE
pass,
VALUE
salt,
VALUE
iter,
VALUE
keylen,
VALUE
digest)
28
{
29
VALUE
str;
30
const
EVP_MD *md;
31
int
len =
NUM2INT
(keylen);
32
33
StringValue
(pass);
34
StringValue
(salt);
35
md =
GetDigestPtr
(digest);
36
37
str =
rb_str_new
(0, len);
38
39
if
(PKCS5_PBKDF2_HMAC(
RSTRING_PTR
(pass),
RSTRING_LENINT
(pass),
40
(
unsigned
char
*)
RSTRING_PTR
(salt),
RSTRING_LENINT
(salt),
41
NUM2INT
(iter), md, len,
42
(
unsigned
char
*)
RSTRING_PTR
(str)) != 1)
43
ossl_raise
(
ePKCS5
,
"PKCS5_PBKDF2_HMAC"
);
44
45
return
str;
46
}
47
#else
48
#define ossl_pkcs5_pbkdf2_hmac rb_f_notimplement
49
#endif
50
51
52
#ifdef HAVE_PKCS5_PBKDF2_HMAC_SHA1
53
/*
54
* call-seq:
55
* PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, keylen) => string
56
*
57
* === Parameters
58
* * +pass+ - string
59
* * +salt+ - string - should be at least 8 bytes long.
60
* * +iter+ - integer - should be greater than 1000. 20000 is better.
61
* * +keylen+ - integer
62
*
63
* This method is available in almost any version of OpenSSL.
64
*
65
* Conforms to rfc2898.
66
*/
67
static
VALUE
68
ossl_pkcs5_pbkdf2_hmac_sha1
(
VALUE
self
,
VALUE
pass,
VALUE
salt,
VALUE
iter,
VALUE
keylen)
69
{
70
VALUE
str;
71
int
len =
NUM2INT
(keylen);
72
73
StringValue
(pass);
74
StringValue
(salt);
75
76
str =
rb_str_new
(0, len);
77
78
if
(PKCS5_PBKDF2_HMAC_SHA1(
RSTRING_PTR
(pass),
RSTRING_LENINT
(pass),
79
(
const
unsigned
char
*)
RSTRING_PTR
(salt),
RSTRING_LENINT
(salt),
NUM2INT
(iter),
80
len, (
unsigned
char
*)
RSTRING_PTR
(str)) != 1)
81
ossl_raise
(
ePKCS5
,
"PKCS5_PBKDF2_HMAC_SHA1"
);
82
83
return
str;
84
}
85
#else
86
#define ossl_pkcs5_pbkdf2_hmac_sha1 rb_f_notimplement
87
#endif
88
89
void
90
Init_ossl_pkcs5
()
91
{
92
/*
93
* Password-based Encryption
94
*
95
*/
96
97
#if 0
98
mOSSL
=
rb_define_module
(
"OpenSSL"
);
/* let rdoc know about mOSSL */
99
#endif
100
101
/* Document-class: OpenSSL::PKCS5
102
*
103
* Provides password-based encryption functionality based on PKCS#5.
104
* Typically used for securely deriving arbitrary length symmetric keys
105
* to be used with an OpenSSL::Cipher from passwords. Another use case
106
* is for storing passwords: Due to the ability to tweak the effort of
107
* computation by increasing the iteration count, computation can be
108
* slowed down artificially in order to render possible attacks infeasible.
109
*
110
* PKCS5 offers support for PBKDF2 with an OpenSSL::Digest::SHA1-based
111
* HMAC, or an arbitrary Digest if the underlying version of OpenSSL
112
* already supports it (>= 0.9.4).
113
*
114
* === Parameters
115
* ==== Password
116
* Typically an arbitrary String that represents the password to be used
117
* for deriving a key.
118
* ==== Salt
119
* Prevents attacks based on dictionaries of common passwords. It is a
120
* public value that can be safely stored along with the password (e.g.
121
* if PBKDF2 is used for password storage). For maximum security, a fresh,
122
* random salt should be generated for each stored password. According
123
* to PKCS#5, a salt should be at least 8 bytes long.
124
* ==== Iteration Count
125
* Allows to tweak the length that the actual computation will take. The
126
* larger the iteration count, the longer it will take.
127
* ==== Key Length
128
* Specifies the length in bytes of the output that will be generated.
129
* Typically, the key length should be larger than or equal to the output
130
* length of the underlying digest function, otherwise an attacker could
131
* simply try to brute-force the key. According to PKCS#5, security is
132
* limited by the output length of the underlying digest function, i.e.
133
* security is not improved if a key length strictly larger than the
134
* digest output length is chosen. Therefore, when using PKCS5 for
135
* password storage, it suffices to store values equal to the digest
136
* output length, nothing is gained by storing larger values.
137
*
138
* == Examples
139
* === Generating a 128 bit key for a Cipher (e.g. AES)
140
* pass = "secret"
141
* salt = OpenSSL::Random.random_bytes(16)
142
* iter = 20000
143
* key_len = 16
144
* key = OpenSSL::PKCS5.pbkdf2_hmac_sha1(pass, salt, iter, key_len)
145
*
146
* === Storing Passwords
147
* pass = "secret"
148
* salt = OpenSSL::Random.random_bytes(16) #store this with the generated value
149
* iter = 20000
150
* digest = OpenSSL::Digest::SHA256.new
151
* len = digest.digest_length
152
* #the final value to be stored
153
* value = OpenSSL::PKCS5.pbkdf2_hmac(pass, salt, iter, len, digest)
154
*
155
* === Important Note on Checking Passwords
156
* When comparing passwords provided by the user with previously stored
157
* values, a common mistake made is comparing the two values using "==".
158
* Typically, "==" short-circuits on evaluation, and is therefore
159
* vulnerable to timing attacks. The proper way is to use a method that
160
* always takes the same amount of time when comparing two values, thus
161
* not leaking any information to potential attackers. To compare two
162
* values, the following could be used:
163
* def eql_time_cmp(a, b)
164
* unless a.length == b.length
165
* return false
166
* end
167
* cmp = b.bytes.to_a
168
* result = 0
169
* a.bytes.each_with_index {|c,i|
170
* result |= c ^ cmp[i]
171
* }
172
* result == 0
173
* end
174
* Please note that the premature return in case of differing lengths
175
* typically does not leak valuable information - when using PKCS#5, the
176
* length of the values to be compared is of fixed size.
177
*/
178
179
mPKCS5
=
rb_define_module_under
(
mOSSL
,
"PKCS5"
);
180
/* Document-class: OpenSSL::PKCS5::PKCS5Error
181
*
182
* Generic Exception class that is raised if an error occurs during a
183
* computation.
184
*/
185
ePKCS5
=
rb_define_class_under
(
mPKCS5
,
"PKCS5Error"
,
eOSSLError
);
186
187
rb_define_module_function
(
mPKCS5
,
"pbkdf2_hmac"
,
ossl_pkcs5_pbkdf2_hmac
, 5);
188
rb_define_module_function
(
mPKCS5
,
"pbkdf2_hmac_sha1"
,
ossl_pkcs5_pbkdf2_hmac_sha1
, 4);
189
}
190
Generated on Mon Sep 22 2014 11:05:25 for Ruby by
1.8.2