jruby-openssl 0.11.0-java → 0.12.1-java
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.
- checksums.yaml +4 -4
- data/History.md +20 -0
- data/Mavenfile +21 -26
- data/README.md +3 -0
- data/Rakefile +21 -35
- data/lib/jopenssl/load.rb +0 -14
- data/lib/jopenssl/version.rb +1 -1
- data/lib/jopenssl.jar +0 -0
- data/lib/openssl/bn.rb +40 -9
- data/lib/openssl/buffering.rb +478 -9
- data/lib/openssl/cipher.rb +67 -9
- data/lib/openssl/config.rb +496 -12
- data/lib/openssl/digest.rb +73 -9
- data/lib/openssl/hmac.rb +13 -0
- data/lib/openssl/marshal.rb +30 -0
- data/lib/openssl/pkcs5.rb +3 -3
- data/lib/openssl/pkey.rb +42 -5
- data/lib/openssl/ssl.rb +543 -9
- data/lib/openssl/x509.rb +369 -9
- data/lib/openssl.rb +43 -1
- data/pom.xml +35 -127
- metadata +8 -42
- data/lib/jopenssl19/openssl/bn.rb +0 -29
- data/lib/jopenssl19/openssl/buffering.rb +0 -449
- data/lib/jopenssl19/openssl/cipher.rb +0 -28
- data/lib/jopenssl19/openssl/config.rb +0 -472
- data/lib/jopenssl19/openssl/digest.rb +0 -32
- data/lib/jopenssl19/openssl/ssl-internal.rb +0 -223
- data/lib/jopenssl19/openssl/ssl.rb +0 -2
- data/lib/jopenssl19/openssl/x509-internal.rb +0 -115
- data/lib/jopenssl19/openssl/x509.rb +0 -2
- data/lib/jopenssl19/openssl.rb +0 -22
- data/lib/jopenssl21/openssl/bn.rb +0 -28
- data/lib/jopenssl21/openssl/buffering.rb +0 -1
- data/lib/jopenssl21/openssl/cipher.rb +0 -1
- data/lib/jopenssl21/openssl/config.rb +0 -1
- data/lib/jopenssl21/openssl/digest.rb +0 -1
- data/lib/jopenssl21/openssl/ssl.rb +0 -1
- data/lib/jopenssl21/openssl/x509.rb +0 -119
- data/lib/jopenssl21/openssl.rb +0 -22
- data/lib/jopenssl22/openssl/bn.rb +0 -39
- data/lib/jopenssl22/openssl/buffering.rb +0 -456
- data/lib/jopenssl22/openssl/cipher.rb +0 -28
- data/lib/jopenssl22/openssl/config.rb +0 -313
- data/lib/jopenssl22/openssl/digest.rb +0 -54
- data/lib/jopenssl22/openssl/ssl.rb +0 -330
- data/lib/jopenssl22/openssl/x509.rb +0 -139
- data/lib/jopenssl22/openssl.rb +0 -22
- data/lib/jopenssl23/openssl/bn.rb +0 -38
- data/lib/jopenssl23/openssl/buffering.rb +0 -455
- data/lib/jopenssl23/openssl/cipher.rb +0 -25
- data/lib/jopenssl23/openssl/config.rb +0 -474
- data/lib/jopenssl23/openssl/digest.rb +0 -43
- data/lib/jopenssl23/openssl/pkey.rb +0 -25
- data/lib/jopenssl23/openssl/ssl.rb +0 -508
- data/lib/jopenssl23/openssl/x509.rb +0 -208
- data/lib/jopenssl23/openssl.rb +0 -19
- data/lib/openssl/ssl-internal.rb +0 -5
- data/lib/openssl/x509-internal.rb +0 -5
data/lib/openssl/x509.rb
CHANGED
@@ -1,9 +1,369 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
#--
|
3
|
+
# = Ruby-space definitions that completes C-space funcs for X509 and subclasses
|
4
|
+
#
|
5
|
+
# = Info
|
6
|
+
# 'OpenSSL for Ruby 2' project
|
7
|
+
# Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# = Licence
|
11
|
+
# This program is licensed under the same licence as Ruby.
|
12
|
+
# (See the file 'LICENCE'.)
|
13
|
+
#++
|
14
|
+
|
15
|
+
require_relative 'marshal'
|
16
|
+
|
17
|
+
module OpenSSL
|
18
|
+
module X509
|
19
|
+
# class ExtensionFactory
|
20
|
+
# def create_extension(*arg)
|
21
|
+
# if arg.size > 1
|
22
|
+
# create_ext(*arg)
|
23
|
+
# else
|
24
|
+
# send("create_ext_from_"+arg[0].class.name.downcase, arg[0])
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# def create_ext_from_array(ary)
|
29
|
+
# raise ExtensionError, "unexpected array form" if ary.size > 3
|
30
|
+
# create_ext(ary[0], ary[1], ary[2])
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# def create_ext_from_string(str) # "oid = critical, value"
|
34
|
+
# oid, value = str.split(/=/, 2)
|
35
|
+
# oid.strip!
|
36
|
+
# value.strip!
|
37
|
+
# create_ext(oid, value)
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# def create_ext_from_hash(hash)
|
41
|
+
# create_ext(hash["oid"], hash["value"], hash["critical"])
|
42
|
+
# end
|
43
|
+
# end
|
44
|
+
|
45
|
+
class Extension
|
46
|
+
include OpenSSL::Marshal
|
47
|
+
|
48
|
+
def ==(other)
|
49
|
+
return false unless Extension === other
|
50
|
+
to_der == other.to_der
|
51
|
+
end
|
52
|
+
|
53
|
+
# def to_s # "oid = critical, value"
|
54
|
+
# str = self.oid
|
55
|
+
# str << " = "
|
56
|
+
# str << "critical, " if self.critical?
|
57
|
+
# str << self.value.gsub(/\n/, ", ")
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
# def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false}
|
61
|
+
# {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?}
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# def to_a
|
65
|
+
# [ self.oid, self.value, self.critical? ]
|
66
|
+
# end
|
67
|
+
|
68
|
+
module Helpers
|
69
|
+
def find_extension(oid)
|
70
|
+
extensions.find { |e| e.oid == oid }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module SubjectKeyIdentifier
|
75
|
+
include Helpers
|
76
|
+
|
77
|
+
# Get the subject's key identifier from the subjectKeyIdentifier
|
78
|
+
# exteension, as described in RFC5280 Section 4.2.1.2.
|
79
|
+
#
|
80
|
+
# Returns the binary String key identifier or nil or raises
|
81
|
+
# ASN1::ASN1Error.
|
82
|
+
def subject_key_identifier
|
83
|
+
ext = find_extension("subjectKeyIdentifier")
|
84
|
+
return nil if ext.nil?
|
85
|
+
|
86
|
+
ski_asn1 = ASN1.decode(ext.value_der)
|
87
|
+
if ext.critical? || ski_asn1.tag_class != :UNIVERSAL || ski_asn1.tag != ASN1::OCTET_STRING
|
88
|
+
raise ASN1::ASN1Error, "invalid extension"
|
89
|
+
end
|
90
|
+
|
91
|
+
ski_asn1.value
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
module AuthorityKeyIdentifier
|
96
|
+
include Helpers
|
97
|
+
|
98
|
+
# Get the issuing certificate's key identifier from the
|
99
|
+
# authorityKeyIdentifier extension, as described in RFC5280
|
100
|
+
# Section 4.2.1.1
|
101
|
+
#
|
102
|
+
# Returns the binary String keyIdentifier or nil or raises
|
103
|
+
# ASN1::ASN1Error.
|
104
|
+
def authority_key_identifier
|
105
|
+
ext = find_extension("authorityKeyIdentifier")
|
106
|
+
return nil if ext.nil?
|
107
|
+
|
108
|
+
aki_asn1 = ASN1.decode(ext.value_der)
|
109
|
+
if ext.critical? || aki_asn1.tag_class != :UNIVERSAL || aki_asn1.tag != ASN1::SEQUENCE
|
110
|
+
raise ASN1::ASN1Error, "invalid extension"
|
111
|
+
end
|
112
|
+
|
113
|
+
key_id = aki_asn1.value.find do |v|
|
114
|
+
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
|
115
|
+
end
|
116
|
+
|
117
|
+
key_id.nil? ? nil : key_id.value
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
module CRLDistributionPoints
|
122
|
+
include Helpers
|
123
|
+
|
124
|
+
# Get the distributionPoint fullName URI from the certificate's CRL
|
125
|
+
# distribution points extension, as described in RFC5280 Section
|
126
|
+
# 4.2.1.13
|
127
|
+
#
|
128
|
+
# Returns an array of strings or nil or raises ASN1::ASN1Error.
|
129
|
+
def crl_uris
|
130
|
+
ext = find_extension("crlDistributionPoints")
|
131
|
+
return nil if ext.nil?
|
132
|
+
|
133
|
+
cdp_asn1 = ASN1.decode(ext.value_der)
|
134
|
+
if cdp_asn1.tag_class != :UNIVERSAL || cdp_asn1.tag != ASN1::SEQUENCE
|
135
|
+
raise ASN1::ASN1Error, "invalid extension"
|
136
|
+
end
|
137
|
+
|
138
|
+
crl_uris = cdp_asn1.map do |crl_distribution_point|
|
139
|
+
distribution_point = crl_distribution_point.value.find do |v|
|
140
|
+
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
|
141
|
+
end
|
142
|
+
full_name = distribution_point&.value&.find do |v|
|
143
|
+
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0
|
144
|
+
end
|
145
|
+
full_name&.value&.find do |v|
|
146
|
+
v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
crl_uris&.map(&:value)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
module AuthorityInfoAccess
|
155
|
+
include Helpers
|
156
|
+
|
157
|
+
# Get the information and services for the issuer from the certificate's
|
158
|
+
# authority information access extension exteension, as described in RFC5280
|
159
|
+
# Section 4.2.2.1.
|
160
|
+
#
|
161
|
+
# Returns an array of strings or nil or raises ASN1::ASN1Error.
|
162
|
+
def ca_issuer_uris
|
163
|
+
aia_asn1 = parse_aia_asn1
|
164
|
+
return nil if aia_asn1.nil?
|
165
|
+
|
166
|
+
ca_issuer = aia_asn1.value.select do |authority_info_access|
|
167
|
+
authority_info_access.value.first.value == "caIssuers"
|
168
|
+
end
|
169
|
+
|
170
|
+
ca_issuer&.map(&:value)&.map(&:last)&.map(&:value)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get the URIs for OCSP from the certificate's authority information access
|
174
|
+
# extension exteension, as described in RFC5280 Section 4.2.2.1.
|
175
|
+
#
|
176
|
+
# Returns an array of strings or nil or raises ASN1::ASN1Error.
|
177
|
+
def ocsp_uris
|
178
|
+
aia_asn1 = parse_aia_asn1
|
179
|
+
return nil if aia_asn1.nil?
|
180
|
+
|
181
|
+
ocsp = aia_asn1.value.select do |authority_info_access|
|
182
|
+
authority_info_access.value.first.value == "OCSP"
|
183
|
+
end
|
184
|
+
|
185
|
+
ocsp&.map(&:value)&.map(&:last)&.map(&:value)
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
def parse_aia_asn1
|
191
|
+
ext = find_extension("authorityInfoAccess")
|
192
|
+
return nil if ext.nil?
|
193
|
+
|
194
|
+
aia_asn1 = ASN1.decode(ext.value_der)
|
195
|
+
if ext.critical? || aia_asn1.tag_class != :UNIVERSAL || aia_asn1.tag != ASN1::SEQUENCE
|
196
|
+
raise ASN1::ASN1Error, "invalid extension"
|
197
|
+
end
|
198
|
+
|
199
|
+
aia_asn1
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
class Name
|
205
|
+
include OpenSSL::Marshal
|
206
|
+
|
207
|
+
module RFC2253DN
|
208
|
+
Special = ',=+<>#;'
|
209
|
+
HexChar = /[0-9a-fA-F]/
|
210
|
+
HexPair = /#{HexChar}#{HexChar}/
|
211
|
+
HexString = /#{HexPair}+/
|
212
|
+
Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/
|
213
|
+
StringChar = /[^\\"#{Special}]/
|
214
|
+
QuoteChar = /[^\\"]/
|
215
|
+
AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/
|
216
|
+
AttributeValue = /
|
217
|
+
(?!["#])((?:#{StringChar}|#{Pair})*)|
|
218
|
+
\#(#{HexString})|
|
219
|
+
"((?:#{QuoteChar}|#{Pair})*)"
|
220
|
+
/x
|
221
|
+
TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/
|
222
|
+
|
223
|
+
module_function
|
224
|
+
|
225
|
+
def expand_pair(str)
|
226
|
+
return nil unless str
|
227
|
+
return str.gsub(Pair){
|
228
|
+
pair = $&
|
229
|
+
case pair.size
|
230
|
+
when 2 then pair[1,1]
|
231
|
+
when 3 then Integer("0x#{pair[1,2]}").chr
|
232
|
+
else raise OpenSSL::X509::NameError, "invalid pair: #{str}"
|
233
|
+
end
|
234
|
+
}
|
235
|
+
end
|
236
|
+
|
237
|
+
def expand_hexstring(str)
|
238
|
+
return nil unless str
|
239
|
+
der = str.gsub(HexPair){$&.to_i(16).chr }
|
240
|
+
a1 = OpenSSL::ASN1.decode(der)
|
241
|
+
return a1.value, a1.tag
|
242
|
+
end
|
243
|
+
|
244
|
+
def expand_value(str1, str2, str3)
|
245
|
+
value = expand_pair(str1)
|
246
|
+
value, tag = expand_hexstring(str2) unless value
|
247
|
+
value = expand_pair(str3) unless value
|
248
|
+
return value, tag
|
249
|
+
end
|
250
|
+
|
251
|
+
def scan(dn)
|
252
|
+
str = dn
|
253
|
+
ary = []
|
254
|
+
while true
|
255
|
+
if md = TypeAndValue.match(str)
|
256
|
+
remain = md.post_match
|
257
|
+
type = md[1]
|
258
|
+
value, tag = expand_value(md[2], md[3], md[4]) rescue nil
|
259
|
+
if value
|
260
|
+
type_and_value = [type, value]
|
261
|
+
type_and_value.push(tag) if tag
|
262
|
+
ary.unshift(type_and_value)
|
263
|
+
if remain.length > 2 && remain[0] == ?,
|
264
|
+
str = remain[1..-1]
|
265
|
+
next
|
266
|
+
elsif remain.length > 2 && remain[0] == ?+
|
267
|
+
raise OpenSSL::X509::NameError,
|
268
|
+
"multi-valued RDN is not supported: #{dn}"
|
269
|
+
elsif remain.empty?
|
270
|
+
break
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|
274
|
+
msg_dn = dn[0, dn.length - str.length] + " =>" + str
|
275
|
+
raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}"
|
276
|
+
end
|
277
|
+
return ary
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
class << self
|
282
|
+
def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE)
|
283
|
+
ary = OpenSSL::X509::Name::RFC2253DN.scan(str)
|
284
|
+
self.new(ary, template)
|
285
|
+
end
|
286
|
+
|
287
|
+
def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE)
|
288
|
+
if str.start_with?("/")
|
289
|
+
# /A=B/C=D format
|
290
|
+
ary = str[1..-1].split("/").map { |i| i.split("=", 2) }
|
291
|
+
else
|
292
|
+
# Comma-separated
|
293
|
+
ary = str.split(",").map { |i| i.strip.split("=", 2) }
|
294
|
+
end
|
295
|
+
self.new(ary, template)
|
296
|
+
end
|
297
|
+
|
298
|
+
alias parse parse_openssl
|
299
|
+
end
|
300
|
+
|
301
|
+
def pretty_print(q)
|
302
|
+
q.object_group(self) {
|
303
|
+
q.text ' '
|
304
|
+
q.text to_s(OpenSSL::X509::Name::RFC2253)
|
305
|
+
}
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
class Attribute
|
310
|
+
include OpenSSL::Marshal
|
311
|
+
|
312
|
+
def ==(other)
|
313
|
+
return false unless Attribute === other
|
314
|
+
to_der == other.to_der
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
class StoreContext
|
319
|
+
def cleanup
|
320
|
+
warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
class Certificate
|
325
|
+
include OpenSSL::Marshal
|
326
|
+
include Extension::SubjectKeyIdentifier
|
327
|
+
include Extension::AuthorityKeyIdentifier
|
328
|
+
include Extension::CRLDistributionPoints
|
329
|
+
include Extension::AuthorityInfoAccess
|
330
|
+
|
331
|
+
def pretty_print(q)
|
332
|
+
q.object_group(self) {
|
333
|
+
q.breakable
|
334
|
+
q.text 'subject='; q.pp self.subject; q.text ','; q.breakable
|
335
|
+
q.text 'issuer='; q.pp self.issuer; q.text ','; q.breakable
|
336
|
+
q.text 'serial='; q.pp self.serial; q.text ','; q.breakable
|
337
|
+
q.text 'not_before='; q.pp self.not_before; q.text ','; q.breakable
|
338
|
+
q.text 'not_after='; q.pp self.not_after
|
339
|
+
}
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
class CRL
|
344
|
+
include OpenSSL::Marshal
|
345
|
+
include Extension::AuthorityKeyIdentifier
|
346
|
+
|
347
|
+
def ==(other)
|
348
|
+
return false unless CRL === other
|
349
|
+
to_der == other.to_der
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
class Revoked
|
354
|
+
def ==(other)
|
355
|
+
return false unless Revoked === other
|
356
|
+
to_der == other.to_der
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
class Request
|
361
|
+
include OpenSSL::Marshal
|
362
|
+
|
363
|
+
def ==(other)
|
364
|
+
return false unless Request === other
|
365
|
+
to_der == other.to_der
|
366
|
+
end
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
data/lib/openssl.rb
CHANGED
@@ -1 +1,43 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'jopenssl/load'
|
4
|
+
|
5
|
+
module OpenSSL
|
6
|
+
autoload :Config, 'openssl/config' unless const_defined?(:Config, false)
|
7
|
+
autoload :PKCS12, 'openssl/pkcs12'
|
8
|
+
end
|
9
|
+
|
10
|
+
=begin
|
11
|
+
= Info
|
12
|
+
'OpenSSL for Ruby 2' project
|
13
|
+
Copyright (C) 2002 Michal Rokos <m.rokos@sh.cvut.cz>
|
14
|
+
All rights reserved.
|
15
|
+
|
16
|
+
= Licence
|
17
|
+
This program is licensed under the same licence as Ruby.
|
18
|
+
(See the file 'LICENCE'.)
|
19
|
+
=end
|
20
|
+
|
21
|
+
require_relative 'openssl/bn'
|
22
|
+
require_relative 'openssl/pkey'
|
23
|
+
require_relative 'openssl/cipher'
|
24
|
+
#require_relative 'openssl/config' if OpenSSL.const_defined?(:Config, false)
|
25
|
+
require_relative 'openssl/digest'
|
26
|
+
require_relative 'openssl/hmac'
|
27
|
+
require_relative 'openssl/x509'
|
28
|
+
require_relative 'openssl/ssl'
|
29
|
+
require_relative 'openssl/pkcs5'
|
30
|
+
|
31
|
+
module OpenSSL
|
32
|
+
# call-seq:
|
33
|
+
# OpenSSL.secure_compare(string, string) -> boolean
|
34
|
+
#
|
35
|
+
# Constant time memory comparison. Inputs are hashed using SHA-256 to mask
|
36
|
+
# the length of the secret. Returns +true+ if the strings are identical,
|
37
|
+
# +false+ otherwise.
|
38
|
+
def self.secure_compare(a, b)
|
39
|
+
hashed_a = OpenSSL::Digest.digest('SHA256', a)
|
40
|
+
hashed_b = OpenSSL::Digest.digest('SHA256', b)
|
41
|
+
OpenSSL.fixed_length_secure_compare(hashed_a, hashed_b) && a == b
|
42
|
+
end
|
43
|
+
end
|