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,20 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#if !defined(_OSSL_CIPHER_H_)
|
11
|
+
#define _OSSL_CIPHER_H_
|
12
|
+
|
13
|
+
extern VALUE cCipher;
|
14
|
+
extern VALUE eCipherError;
|
15
|
+
|
16
|
+
const EVP_CIPHER *GetCipherPtr(VALUE);
|
17
|
+
VALUE ossl_cipher_new(const EVP_CIPHER *);
|
18
|
+
void Init_ossl_cipher(void);
|
19
|
+
|
20
|
+
#endif /* _OSSL_CIPHER_H_ */
|
@@ -0,0 +1,89 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#include "ossl.h"
|
11
|
+
|
12
|
+
|
13
|
+
/*
|
14
|
+
* Classes
|
15
|
+
*/
|
16
|
+
VALUE cConfig;
|
17
|
+
/* Document-class: OpenSSL::ConfigError
|
18
|
+
*
|
19
|
+
* General error for openssl library configuration files. Including formatting,
|
20
|
+
* parsing errors, etc.
|
21
|
+
*/
|
22
|
+
VALUE eConfigError;
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Public
|
26
|
+
*/
|
27
|
+
|
28
|
+
/*
|
29
|
+
* DupConfigPtr is a public C-level function for getting OpenSSL CONF struct
|
30
|
+
* from an OpenSSL::Config(eConfig) instance. We decided to implement
|
31
|
+
* OpenSSL::Config in Ruby level but we need to pass native CONF struct for
|
32
|
+
* some OpenSSL features such as X509V3_EXT_*.
|
33
|
+
*/
|
34
|
+
CONF *
|
35
|
+
DupConfigPtr(VALUE obj)
|
36
|
+
{
|
37
|
+
CONF *conf;
|
38
|
+
VALUE str;
|
39
|
+
BIO *bio;
|
40
|
+
long eline = -1;
|
41
|
+
|
42
|
+
OSSL_Check_Kind(obj, cConfig);
|
43
|
+
str = rb_funcall(obj, rb_intern("to_s"), 0);
|
44
|
+
bio = ossl_obj2bio(str);
|
45
|
+
conf = NCONF_new(NULL);
|
46
|
+
if(!conf){
|
47
|
+
BIO_free(bio);
|
48
|
+
ossl_raise(eConfigError, NULL);
|
49
|
+
}
|
50
|
+
if(!NCONF_load_bio(conf, bio, &eline)){
|
51
|
+
BIO_free(bio);
|
52
|
+
NCONF_free(conf);
|
53
|
+
if (eline <= 0)
|
54
|
+
ossl_raise(eConfigError, "wrong config format");
|
55
|
+
else
|
56
|
+
ossl_raise(eConfigError, "error in line %d", eline);
|
57
|
+
}
|
58
|
+
BIO_free(bio);
|
59
|
+
|
60
|
+
return conf;
|
61
|
+
}
|
62
|
+
|
63
|
+
/* Document-const: DEFAULT_CONFIG_FILE
|
64
|
+
*
|
65
|
+
* The default system configuration file for openssl
|
66
|
+
*/
|
67
|
+
|
68
|
+
/*
|
69
|
+
* INIT
|
70
|
+
*/
|
71
|
+
void
|
72
|
+
Init_ossl_config(void)
|
73
|
+
{
|
74
|
+
char *default_config_file;
|
75
|
+
|
76
|
+
#if 0
|
77
|
+
mOSSL = rb_define_module("OpenSSL");
|
78
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
79
|
+
#endif
|
80
|
+
|
81
|
+
eConfigError = rb_define_class_under(mOSSL, "ConfigError", eOSSLError);
|
82
|
+
cConfig = rb_define_class_under(mOSSL, "Config", rb_cObject);
|
83
|
+
|
84
|
+
default_config_file = CONF_get1_default_config_file();
|
85
|
+
rb_define_const(cConfig, "DEFAULT_CONFIG_FILE",
|
86
|
+
rb_str_new2(default_config_file));
|
87
|
+
OPENSSL_free(default_config_file);
|
88
|
+
/* methods are defined by openssl/config.rb */
|
89
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#if !defined(_OSSL_CONFIG_H_)
|
11
|
+
#define _OSSL_CONFIG_H_
|
12
|
+
|
13
|
+
extern VALUE cConfig;
|
14
|
+
extern VALUE eConfigError;
|
15
|
+
|
16
|
+
CONF* DupConfigPtr(VALUE obj);
|
17
|
+
void Init_ossl_config(void);
|
18
|
+
|
19
|
+
#endif /* _OSSL_CONFIG_H_ */
|
@@ -0,0 +1,453 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#include "ossl.h"
|
11
|
+
|
12
|
+
#define GetDigest(obj, ctx) do { \
|
13
|
+
TypedData_Get_Struct((obj), EVP_MD_CTX, &ossl_digest_type, (ctx)); \
|
14
|
+
if (!(ctx)) { \
|
15
|
+
ossl_raise(rb_eRuntimeError, "Digest CTX wasn't initialized!"); \
|
16
|
+
} \
|
17
|
+
} while (0)
|
18
|
+
#define SafeGetDigest(obj, ctx) do { \
|
19
|
+
OSSL_Check_Kind((obj), cDigest); \
|
20
|
+
GetDigest((obj), (ctx)); \
|
21
|
+
} while (0)
|
22
|
+
|
23
|
+
/*
|
24
|
+
* Classes
|
25
|
+
*/
|
26
|
+
VALUE cDigest;
|
27
|
+
VALUE eDigestError;
|
28
|
+
|
29
|
+
static VALUE ossl_digest_alloc(VALUE klass);
|
30
|
+
|
31
|
+
static void
|
32
|
+
ossl_digest_free(void *ctx)
|
33
|
+
{
|
34
|
+
EVP_MD_CTX_destroy(ctx);
|
35
|
+
}
|
36
|
+
|
37
|
+
static const rb_data_type_t ossl_digest_type = {
|
38
|
+
"OpenSSL/Digest",
|
39
|
+
{
|
40
|
+
0, ossl_digest_free,
|
41
|
+
},
|
42
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
43
|
+
};
|
44
|
+
|
45
|
+
/*
|
46
|
+
* Public
|
47
|
+
*/
|
48
|
+
const EVP_MD *
|
49
|
+
GetDigestPtr(VALUE obj)
|
50
|
+
{
|
51
|
+
const EVP_MD *md;
|
52
|
+
ASN1_OBJECT *oid = NULL;
|
53
|
+
|
54
|
+
if (RB_TYPE_P(obj, T_STRING)) {
|
55
|
+
const char *name = StringValueCStr(obj);
|
56
|
+
|
57
|
+
md = EVP_get_digestbyname(name);
|
58
|
+
if (!md) {
|
59
|
+
oid = OBJ_txt2obj(name, 0);
|
60
|
+
md = EVP_get_digestbyobj(oid);
|
61
|
+
ASN1_OBJECT_free(oid);
|
62
|
+
}
|
63
|
+
if(!md)
|
64
|
+
ossl_raise(rb_eRuntimeError, "Unsupported digest algorithm (%"PRIsVALUE").", obj);
|
65
|
+
} else {
|
66
|
+
EVP_MD_CTX *ctx;
|
67
|
+
|
68
|
+
SafeGetDigest(obj, ctx);
|
69
|
+
|
70
|
+
md = EVP_MD_CTX_md(ctx);
|
71
|
+
}
|
72
|
+
|
73
|
+
return md;
|
74
|
+
}
|
75
|
+
|
76
|
+
VALUE
|
77
|
+
ossl_digest_new(const EVP_MD *md)
|
78
|
+
{
|
79
|
+
VALUE ret;
|
80
|
+
EVP_MD_CTX *ctx;
|
81
|
+
|
82
|
+
ret = ossl_digest_alloc(cDigest);
|
83
|
+
GetDigest(ret, ctx);
|
84
|
+
if (EVP_DigestInit_ex(ctx, md, NULL) != 1) {
|
85
|
+
ossl_raise(eDigestError, "Digest initialization failed.");
|
86
|
+
}
|
87
|
+
|
88
|
+
return ret;
|
89
|
+
}
|
90
|
+
|
91
|
+
/*
|
92
|
+
* Private
|
93
|
+
*/
|
94
|
+
static VALUE
|
95
|
+
ossl_digest_alloc(VALUE klass)
|
96
|
+
{
|
97
|
+
VALUE obj = TypedData_Wrap_Struct(klass, &ossl_digest_type, 0);
|
98
|
+
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
|
99
|
+
if (ctx == NULL)
|
100
|
+
ossl_raise(rb_eRuntimeError, "EVP_MD_CTX_create() failed");
|
101
|
+
RTYPEDDATA_DATA(obj) = ctx;
|
102
|
+
|
103
|
+
return obj;
|
104
|
+
}
|
105
|
+
|
106
|
+
VALUE ossl_digest_update(VALUE, VALUE);
|
107
|
+
|
108
|
+
/*
|
109
|
+
* call-seq:
|
110
|
+
* Digest.new(string [, data]) -> Digest
|
111
|
+
*
|
112
|
+
* Creates a Digest instance based on +string+, which is either the ln
|
113
|
+
* (long name) or sn (short name) of a supported digest algorithm.
|
114
|
+
*
|
115
|
+
* If +data+ (a +String+) is given, it is used as the initial input to the
|
116
|
+
* Digest instance, i.e.
|
117
|
+
*
|
118
|
+
* digest = OpenSSL::Digest.new('sha256', 'digestdata')
|
119
|
+
*
|
120
|
+
* is equal to
|
121
|
+
*
|
122
|
+
* digest = OpenSSL::Digest.new('sha256')
|
123
|
+
* digest.update('digestdata')
|
124
|
+
*/
|
125
|
+
static VALUE
|
126
|
+
ossl_digest_initialize(int argc, VALUE *argv, VALUE self)
|
127
|
+
{
|
128
|
+
EVP_MD_CTX *ctx;
|
129
|
+
const EVP_MD *md;
|
130
|
+
VALUE type, data;
|
131
|
+
|
132
|
+
rb_scan_args(argc, argv, "11", &type, &data);
|
133
|
+
md = GetDigestPtr(type);
|
134
|
+
if (!NIL_P(data)) StringValue(data);
|
135
|
+
|
136
|
+
GetDigest(self, ctx);
|
137
|
+
if (EVP_DigestInit_ex(ctx, md, NULL) != 1) {
|
138
|
+
ossl_raise(eDigestError, "Digest initialization failed.");
|
139
|
+
}
|
140
|
+
|
141
|
+
if (!NIL_P(data)) return ossl_digest_update(self, data);
|
142
|
+
return self;
|
143
|
+
}
|
144
|
+
|
145
|
+
static VALUE
|
146
|
+
ossl_digest_copy(VALUE self, VALUE other)
|
147
|
+
{
|
148
|
+
EVP_MD_CTX *ctx1, *ctx2;
|
149
|
+
|
150
|
+
rb_check_frozen(self);
|
151
|
+
if (self == other) return self;
|
152
|
+
|
153
|
+
GetDigest(self, ctx1);
|
154
|
+
SafeGetDigest(other, ctx2);
|
155
|
+
|
156
|
+
if (!EVP_MD_CTX_copy(ctx1, ctx2)) {
|
157
|
+
ossl_raise(eDigestError, NULL);
|
158
|
+
}
|
159
|
+
return self;
|
160
|
+
}
|
161
|
+
|
162
|
+
/*
|
163
|
+
* call-seq:
|
164
|
+
* digest.reset -> self
|
165
|
+
*
|
166
|
+
* Resets the Digest in the sense that any Digest#update that has been
|
167
|
+
* performed is abandoned and the Digest is set to its initial state again.
|
168
|
+
*
|
169
|
+
*/
|
170
|
+
static VALUE
|
171
|
+
ossl_digest_reset(VALUE self)
|
172
|
+
{
|
173
|
+
EVP_MD_CTX *ctx;
|
174
|
+
|
175
|
+
GetDigest(self, ctx);
|
176
|
+
if (EVP_DigestInit_ex(ctx, EVP_MD_CTX_md(ctx), NULL) != 1) {
|
177
|
+
ossl_raise(eDigestError, "Digest initialization failed.");
|
178
|
+
}
|
179
|
+
|
180
|
+
return self;
|
181
|
+
}
|
182
|
+
|
183
|
+
/*
|
184
|
+
* call-seq:
|
185
|
+
* digest.update(string) -> aString
|
186
|
+
*
|
187
|
+
* Not every message digest can be computed in one single pass. If a message
|
188
|
+
* digest is to be computed from several subsequent sources, then each may
|
189
|
+
* be passed individually to the Digest instance.
|
190
|
+
*
|
191
|
+
* === Example
|
192
|
+
* digest = OpenSSL::Digest::SHA256.new
|
193
|
+
* digest.update('First input')
|
194
|
+
* digest << 'Second input' # equivalent to digest.update('Second input')
|
195
|
+
* result = digest.digest
|
196
|
+
*
|
197
|
+
*/
|
198
|
+
VALUE
|
199
|
+
ossl_digest_update(VALUE self, VALUE data)
|
200
|
+
{
|
201
|
+
EVP_MD_CTX *ctx;
|
202
|
+
|
203
|
+
StringValue(data);
|
204
|
+
GetDigest(self, ctx);
|
205
|
+
|
206
|
+
if (!EVP_DigestUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)))
|
207
|
+
ossl_raise(eDigestError, "EVP_DigestUpdate");
|
208
|
+
|
209
|
+
return self;
|
210
|
+
}
|
211
|
+
|
212
|
+
/*
|
213
|
+
* call-seq:
|
214
|
+
* digest.finish -> aString
|
215
|
+
*
|
216
|
+
*/
|
217
|
+
static VALUE
|
218
|
+
ossl_digest_finish(int argc, VALUE *argv, VALUE self)
|
219
|
+
{
|
220
|
+
EVP_MD_CTX *ctx;
|
221
|
+
VALUE str;
|
222
|
+
int out_len;
|
223
|
+
|
224
|
+
GetDigest(self, ctx);
|
225
|
+
rb_scan_args(argc, argv, "01", &str);
|
226
|
+
out_len = EVP_MD_CTX_size(ctx);
|
227
|
+
|
228
|
+
if (NIL_P(str)) {
|
229
|
+
str = rb_str_new(NULL, out_len);
|
230
|
+
} else {
|
231
|
+
StringValue(str);
|
232
|
+
rb_str_resize(str, out_len);
|
233
|
+
}
|
234
|
+
|
235
|
+
if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL))
|
236
|
+
ossl_raise(eDigestError, "EVP_DigestFinal_ex");
|
237
|
+
|
238
|
+
return str;
|
239
|
+
}
|
240
|
+
|
241
|
+
/*
|
242
|
+
* call-seq:
|
243
|
+
* digest.name -> string
|
244
|
+
*
|
245
|
+
* Returns the sn of this Digest algorithm.
|
246
|
+
*
|
247
|
+
* === Example
|
248
|
+
* digest = OpenSSL::Digest::SHA512.new
|
249
|
+
* puts digest.name # => SHA512
|
250
|
+
*
|
251
|
+
*/
|
252
|
+
static VALUE
|
253
|
+
ossl_digest_name(VALUE self)
|
254
|
+
{
|
255
|
+
EVP_MD_CTX *ctx;
|
256
|
+
|
257
|
+
GetDigest(self, ctx);
|
258
|
+
|
259
|
+
return rb_str_new2(EVP_MD_name(EVP_MD_CTX_md(ctx)));
|
260
|
+
}
|
261
|
+
|
262
|
+
/*
|
263
|
+
* call-seq:
|
264
|
+
* digest.digest_length -> integer
|
265
|
+
*
|
266
|
+
* Returns the output size of the digest, i.e. the length in bytes of the
|
267
|
+
* final message digest result.
|
268
|
+
*
|
269
|
+
* === Example
|
270
|
+
* digest = OpenSSL::Digest::SHA1.new
|
271
|
+
* puts digest.digest_length # => 20
|
272
|
+
*
|
273
|
+
*/
|
274
|
+
static VALUE
|
275
|
+
ossl_digest_size(VALUE self)
|
276
|
+
{
|
277
|
+
EVP_MD_CTX *ctx;
|
278
|
+
|
279
|
+
GetDigest(self, ctx);
|
280
|
+
|
281
|
+
return INT2NUM(EVP_MD_CTX_size(ctx));
|
282
|
+
}
|
283
|
+
|
284
|
+
/*
|
285
|
+
* call-seq:
|
286
|
+
* digest.block_length -> integer
|
287
|
+
*
|
288
|
+
* Returns the block length of the digest algorithm, i.e. the length in bytes
|
289
|
+
* of an individual block. Most modern algorithms partition a message to be
|
290
|
+
* digested into a sequence of fix-sized blocks that are processed
|
291
|
+
* consecutively.
|
292
|
+
*
|
293
|
+
* === Example
|
294
|
+
* digest = OpenSSL::Digest::SHA1.new
|
295
|
+
* puts digest.block_length # => 64
|
296
|
+
*/
|
297
|
+
static VALUE
|
298
|
+
ossl_digest_block_length(VALUE self)
|
299
|
+
{
|
300
|
+
EVP_MD_CTX *ctx;
|
301
|
+
|
302
|
+
GetDigest(self, ctx);
|
303
|
+
|
304
|
+
return INT2NUM(EVP_MD_CTX_block_size(ctx));
|
305
|
+
}
|
306
|
+
|
307
|
+
/*
|
308
|
+
* INIT
|
309
|
+
*/
|
310
|
+
void
|
311
|
+
Init_ossl_digest(void)
|
312
|
+
{
|
313
|
+
rb_require("digest");
|
314
|
+
|
315
|
+
#if 0
|
316
|
+
mOSSL = rb_define_module("OpenSSL");
|
317
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
318
|
+
#endif
|
319
|
+
|
320
|
+
/* Document-class: OpenSSL::Digest
|
321
|
+
*
|
322
|
+
* OpenSSL::Digest allows you to compute message digests (sometimes
|
323
|
+
* interchangeably called "hashes") of arbitrary data that are
|
324
|
+
* cryptographically secure, i.e. a Digest implements a secure one-way
|
325
|
+
* function.
|
326
|
+
*
|
327
|
+
* One-way functions offer some useful properties. E.g. given two
|
328
|
+
* distinct inputs the probability that both yield the same output
|
329
|
+
* is highly unlikely. Combined with the fact that every message digest
|
330
|
+
* algorithm has a fixed-length output of just a few bytes, digests are
|
331
|
+
* often used to create unique identifiers for arbitrary data. A common
|
332
|
+
* example is the creation of a unique id for binary documents that are
|
333
|
+
* stored in a database.
|
334
|
+
*
|
335
|
+
* Another useful characteristic of one-way functions (and thus the name)
|
336
|
+
* is that given a digest there is no indication about the original
|
337
|
+
* data that produced it, i.e. the only way to identify the original input
|
338
|
+
* is to "brute-force" through every possible combination of inputs.
|
339
|
+
*
|
340
|
+
* These characteristics make one-way functions also ideal companions
|
341
|
+
* for public key signature algorithms: instead of signing an entire
|
342
|
+
* document, first a hash of the document is produced with a considerably
|
343
|
+
* faster message digest algorithm and only the few bytes of its output
|
344
|
+
* need to be signed using the slower public key algorithm. To validate
|
345
|
+
* the integrity of a signed document, it suffices to re-compute the hash
|
346
|
+
* and verify that it is equal to that in the signature.
|
347
|
+
*
|
348
|
+
* Among the supported message digest algorithms are:
|
349
|
+
* * SHA, SHA1, SHA224, SHA256, SHA384 and SHA512
|
350
|
+
* * MD2, MD4, MDC2 and MD5
|
351
|
+
* * RIPEMD160
|
352
|
+
* * DSS, DSS1 (Pseudo algorithms to be used for DSA signatures. DSS is
|
353
|
+
* equal to SHA and DSS1 is equal to SHA1)
|
354
|
+
*
|
355
|
+
* For each of these algorithms, there is a sub-class of Digest that
|
356
|
+
* can be instantiated as simply as e.g.
|
357
|
+
*
|
358
|
+
* digest = OpenSSL::Digest::SHA1.new
|
359
|
+
*
|
360
|
+
* === Mapping between Digest class and sn/ln
|
361
|
+
*
|
362
|
+
* The sn (short names) and ln (long names) are defined in
|
363
|
+
* <openssl/object.h> and <openssl/obj_mac.h>. They are textual
|
364
|
+
* representations of ASN.1 OBJECT IDENTIFIERs. Each supported digest
|
365
|
+
* algorithm has an OBJECT IDENTIFIER associated to it and those again
|
366
|
+
* have short/long names assigned to them.
|
367
|
+
* E.g. the OBJECT IDENTIFIER for SHA-1 is 1.3.14.3.2.26 and its
|
368
|
+
* sn is "SHA1" and its ln is "sha1".
|
369
|
+
* ==== MD2
|
370
|
+
* * sn: MD2
|
371
|
+
* * ln: md2
|
372
|
+
* ==== MD4
|
373
|
+
* * sn: MD4
|
374
|
+
* * ln: md4
|
375
|
+
* ==== MD5
|
376
|
+
* * sn: MD5
|
377
|
+
* * ln: md5
|
378
|
+
* ==== SHA
|
379
|
+
* * sn: SHA
|
380
|
+
* * ln: SHA
|
381
|
+
* ==== SHA-1
|
382
|
+
* * sn: SHA1
|
383
|
+
* * ln: sha1
|
384
|
+
* ==== SHA-224
|
385
|
+
* * sn: SHA224
|
386
|
+
* * ln: sha224
|
387
|
+
* ==== SHA-256
|
388
|
+
* * sn: SHA256
|
389
|
+
* * ln: sha256
|
390
|
+
* ==== SHA-384
|
391
|
+
* * sn: SHA384
|
392
|
+
* * ln: sha384
|
393
|
+
* ==== SHA-512
|
394
|
+
* * sn: SHA512
|
395
|
+
* * ln: sha512
|
396
|
+
*
|
397
|
+
* "Breaking" a message digest algorithm means defying its one-way
|
398
|
+
* function characteristics, i.e. producing a collision or finding a way
|
399
|
+
* to get to the original data by means that are more efficient than
|
400
|
+
* brute-forcing etc. Most of the supported digest algorithms can be
|
401
|
+
* considered broken in this sense, even the very popular MD5 and SHA1
|
402
|
+
* algorithms. Should security be your highest concern, then you should
|
403
|
+
* probably rely on SHA224, SHA256, SHA384 or SHA512.
|
404
|
+
*
|
405
|
+
* === Hashing a file
|
406
|
+
*
|
407
|
+
* data = File.read('document')
|
408
|
+
* sha256 = OpenSSL::Digest::SHA256.new
|
409
|
+
* digest = sha256.digest(data)
|
410
|
+
*
|
411
|
+
* === Hashing several pieces of data at once
|
412
|
+
*
|
413
|
+
* data1 = File.read('file1')
|
414
|
+
* data2 = File.read('file2')
|
415
|
+
* data3 = File.read('file3')
|
416
|
+
* sha256 = OpenSSL::Digest::SHA256.new
|
417
|
+
* sha256 << data1
|
418
|
+
* sha256 << data2
|
419
|
+
* sha256 << data3
|
420
|
+
* digest = sha256.digest
|
421
|
+
*
|
422
|
+
* === Reuse a Digest instance
|
423
|
+
*
|
424
|
+
* data1 = File.read('file1')
|
425
|
+
* sha256 = OpenSSL::Digest::SHA256.new
|
426
|
+
* digest1 = sha256.digest(data1)
|
427
|
+
*
|
428
|
+
* data2 = File.read('file2')
|
429
|
+
* sha256.reset
|
430
|
+
* digest2 = sha256.digest(data2)
|
431
|
+
*
|
432
|
+
*/
|
433
|
+
cDigest = rb_define_class_under(mOSSL, "Digest", rb_path2class("Digest::Class"));
|
434
|
+
/* Document-class: OpenSSL::Digest::DigestError
|
435
|
+
*
|
436
|
+
* Generic Exception class that is raised if an error occurs during a
|
437
|
+
* Digest operation.
|
438
|
+
*/
|
439
|
+
eDigestError = rb_define_class_under(cDigest, "DigestError", eOSSLError);
|
440
|
+
|
441
|
+
rb_define_alloc_func(cDigest, ossl_digest_alloc);
|
442
|
+
|
443
|
+
rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1);
|
444
|
+
rb_define_copy_func(cDigest, ossl_digest_copy);
|
445
|
+
rb_define_method(cDigest, "reset", ossl_digest_reset, 0);
|
446
|
+
rb_define_method(cDigest, "update", ossl_digest_update, 1);
|
447
|
+
rb_define_alias(cDigest, "<<", "update");
|
448
|
+
rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1);
|
449
|
+
rb_define_method(cDigest, "digest_length", ossl_digest_size, 0);
|
450
|
+
rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0);
|
451
|
+
|
452
|
+
rb_define_method(cDigest, "name", ossl_digest_name, 0);
|
453
|
+
}
|