ccrypto-ruby 0.1.0

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.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/Gemfile +12 -0
  4. data/Gemfile.lock +64 -0
  5. data/README.md +149 -0
  6. data/Rakefile +10 -0
  7. data/bin/console +15 -0
  8. data/bin/setup +8 -0
  9. data/ccrypto-ruby.gemspec +45 -0
  10. data/lib/ccrypto/provider.rb +175 -0
  11. data/lib/ccrypto/ruby/data_conversion.rb +68 -0
  12. data/lib/ccrypto/ruby/engines/asn1_engine.rb +110 -0
  13. data/lib/ccrypto/ruby/engines/asn1_object.rb +19 -0
  14. data/lib/ccrypto/ruby/engines/cipher_engine.rb +170 -0
  15. data/lib/ccrypto/ruby/engines/compression_engine.rb +61 -0
  16. data/lib/ccrypto/ruby/engines/data_conversion_engine.rb +9 -0
  17. data/lib/ccrypto/ruby/engines/decompression_engine.rb +70 -0
  18. data/lib/ccrypto/ruby/engines/digest_engine.rb +127 -0
  19. data/lib/ccrypto/ruby/engines/ecc_engine.rb +218 -0
  20. data/lib/ccrypto/ruby/engines/hkdf_engine.rb +54 -0
  21. data/lib/ccrypto/ruby/engines/hmac_engine.rb +53 -0
  22. data/lib/ccrypto/ruby/engines/pbkdf2_engine.rb +69 -0
  23. data/lib/ccrypto/ruby/engines/pkcs7_engine.rb +179 -0
  24. data/lib/ccrypto/ruby/engines/rsa_engine.rb +300 -0
  25. data/lib/ccrypto/ruby/engines/scrypt_engine.rb +34 -0
  26. data/lib/ccrypto/ruby/engines/secret_key_engine.rb +18 -0
  27. data/lib/ccrypto/ruby/engines/secret_sharing_engine.rb +331 -0
  28. data/lib/ccrypto/ruby/engines/secure_random_engine.rb +34 -0
  29. data/lib/ccrypto/ruby/engines/x509_engine.rb +213 -0
  30. data/lib/ccrypto/ruby/ext/secret_key.rb +24 -0
  31. data/lib/ccrypto/ruby/ext/x509_cert.rb +24 -0
  32. data/lib/ccrypto/ruby/keybundle_store/pem_store.rb +73 -0
  33. data/lib/ccrypto/ruby/keybundle_store/pkcs12.rb +111 -0
  34. data/lib/ccrypto/ruby/utils/comparator.rb +15 -0
  35. data/lib/ccrypto/ruby/utils/memory_buffer.rb +63 -0
  36. data/lib/ccrypto/ruby/utils/native_helper.rb +17 -0
  37. data/lib/ccrypto/ruby/version.rb +7 -0
  38. data/lib/ccrypto/ruby.rb +25 -0
  39. metadata +136 -0
@@ -0,0 +1,331 @@
1
+
2
+ require 'openssl'
3
+
4
+ module Ccrypto
5
+ module Ruby
6
+
7
+ class SecretSharingEngine
8
+ def initialize(*args, &block)
9
+ @config = args.first
10
+ raise SecretSharingException, "SecretSharingConfig is required" if not @config.is_a?(Ccrypto::SecretSharingConfig)
11
+ raise SecretSharingException, "split_into value must be more than 1" if not @config.split_into.to_i > 1
12
+ raise SecretSharingException, "required_parts value (#{@config.required_parts}) must be less than or equal split_into value (#{@config.split_into})." if not @config.required_parts.to_i < @config.split_into.to_i
13
+ end
14
+
15
+ def split(secVal)
16
+
17
+ case secVal
18
+ when MemoryBuffer
19
+ data = secVal.bytes
20
+ when String
21
+ data = secVal
22
+ when Ccrypto::SecretKey
23
+ data = secVal.to_bin
24
+ else
25
+ raise SecretSharingException, "Unknown how to process split for #{secVal.class}"
26
+ end
27
+
28
+ eng = ShamirSharing.new(@config.required_parts.to_i, data)
29
+ shares = []
30
+ (1..@config.split_into.to_i).each do |i|
31
+ res = eng.compute_share(i)
32
+ res[1] = res[1].map { |v| v.chr }.join
33
+ shares << res
34
+ end
35
+ shares
36
+ end
37
+
38
+ def self.combine(req, parts)
39
+
40
+ parts.each do |k,v|
41
+ parts[k] = v.chars.map(&:ord)
42
+ end
43
+
44
+ ss = ShamirSharing.new(req)
45
+ ss.recover_secretdata(parts.to_a)
46
+ end
47
+ end
48
+
49
+
50
+ #
51
+ # This code is borrowed from PolyPasswordHasher-Ruby project at https://github.com/PolyPasswordHasher/PolyPasswordHasher-Ruby
52
+ #
53
+ class ShamirSharing
54
+ attr_reader :_coefficients
55
+ attr_reader :secretdata
56
+
57
+ def initialize(threshold, secretdata=nil)
58
+ @threshold = threshold
59
+ @secretdata = secretdata
60
+ @_coefficients = []
61
+
62
+ if secretdata
63
+ secretdata.each_char do |secretbyte|
64
+ thesecoefficients = secretbyte+OpenSSL::Random.random_bytes(@threshold-1)
65
+ @_coefficients << thesecoefficients
66
+ end
67
+ end
68
+ end
69
+
70
+ def is_valid_share?(share)
71
+ raise "Share is of incorrect length: #{share.size}" if share.size !=2
72
+ raise "Must initialize coefficient before checking is_valid_share?" unless @_coefficients
73
+ raise "Must initialize coefficient before checking is_valid_share?" if @_coefficients.size != share[1].size
74
+
75
+ x = share[0]
76
+ fx = share[1]
77
+
78
+ correctshare = compute_share(x)
79
+
80
+ correctshare == share
81
+ end
82
+
83
+ def compute_share(x)
84
+ raise "x should be integer" unless x.class == Fixnum
85
+ raise "x must be between 1 and 255" if x <= 0 || x >256
86
+ raise "@_coefficient must be initialized" if @_coefficients.empty?
87
+
88
+ sharebytes = []
89
+
90
+ @_coefficients.each do |thiscoefficient|
91
+ thisshare = _f(x,thiscoefficient)
92
+ sharebytes << thisshare
93
+ end
94
+
95
+ return x, sharebytes
96
+ end
97
+
98
+ def recover_secretdata(shares)
99
+ newshares = []
100
+
101
+ shares.each do |share|
102
+ newshares << share unless newshares.include?(share)
103
+ end
104
+
105
+ shares = newshares
106
+
107
+ if @threshold > shares.size
108
+ raise "Threshold: #{@threshold} is smaller than the number of uniquie shares: #{shares.size}"
109
+ end
110
+
111
+ if @secretdata
112
+ raise "Recovoring secretdata when some is stored. Use check_share instead"
113
+ end
114
+
115
+ xs = []
116
+
117
+ shares.each do |share|
118
+ if xs.include?(share[0])
119
+ raise "Different shares with the same first byte: #{share[0]}"
120
+ end
121
+
122
+ if share[1].size != shares[0][1].size
123
+ raise "Shares have different lengths!"
124
+ end
125
+
126
+ xs << share[0]
127
+ end
128
+
129
+ mycoefficients = []
130
+ mysecretdata = ''
131
+
132
+ shares[0][1].size.times.each do |byte_to_use|
133
+ fxs = []
134
+ shares.each do |share|
135
+ fxs << share[1][byte_to_use]
136
+ end
137
+
138
+ resulting_poly = _full_lagrange(xs,fxs)
139
+
140
+ if resulting_poly[0..@threshold-1] + [0]*(shares.size - @threshold) != resulting_poly
141
+ raise "Share do not match. Cannot decode"
142
+ end
143
+
144
+ mycoefficients << resulting_poly.map{|p| p.chr}.join
145
+
146
+ mysecretdata += resulting_poly[0].chr
147
+ end
148
+
149
+ @_coefficients = mycoefficients
150
+ @secretdata = mysecretdata
151
+ end
152
+
153
+ private
154
+ def _f(x, coefs_bytes)
155
+ raise "invalid share index value. cannot be 0" if x == 0
156
+
157
+ accumulator = 0
158
+
159
+ x_i = 1
160
+
161
+ coefs_bytes.each_byte do |c|
162
+ accumulator = _gf256_add(accumulator, _gf256_mul(c, x_i))
163
+ x_i = _gf256_mul(x_i, x)
164
+ end
165
+
166
+ return accumulator
167
+ end
168
+
169
+ def _multiply_polynomials(a,b)
170
+ resultterms = []
171
+
172
+ termpadding = []
173
+
174
+ b.each do |bterm|
175
+ thisvalue = termpadding.clone
176
+
177
+ a.each do |aterm|
178
+ val = _gf256_mul(aterm, bterm)
179
+ thisvalue << _gf256_mul(aterm, bterm)
180
+ end
181
+
182
+ resultterms = _add_polynomials(resultterms, thisvalue)
183
+
184
+ termpadding << 0
185
+ end
186
+
187
+ return resultterms
188
+ end
189
+
190
+ def _add_polynomials(a,b)
191
+ if a.size < b.size
192
+ a = a + [0]*(b.size - a.size)
193
+ elsif a.size > b.size
194
+ b = b + [0]*(a.size - b.size)
195
+ end
196
+
197
+ result = []
198
+
199
+ a.size.times do |pos|
200
+ result << _gf256_add(a[pos], b[pos])
201
+ end
202
+
203
+ return result
204
+ end
205
+
206
+ def _full_lagrange(xs, fxs)
207
+ returnedcoefficients = []
208
+
209
+ fxs.size.times do |i|
210
+ this_polynomial = [1]
211
+
212
+ fxs.size.times do |j|
213
+ next if i == j
214
+
215
+ denominator = _gf256_sub(xs[i], xs[j])
216
+
217
+ this_term = [_gf256_div(xs[j], denominator), _gf256_div(1, denominator)]
218
+
219
+ this_polynomial = _multiply_polynomials(this_polynomial, this_term)
220
+ end
221
+
222
+ this_polynomial = _multiply_polynomials(this_polynomial, [fxs[i]]) if fxs[i]
223
+
224
+ returnedcoefficients = _add_polynomials(returnedcoefficients, this_polynomial)
225
+ end
226
+
227
+ return returnedcoefficients
228
+
229
+ end
230
+
231
+ GF256_EXP = [
232
+ 0x01, 0x03, 0x05, 0x0f, 0x11, 0x33, 0x55, 0xff,
233
+ 0x1a, 0x2e, 0x72, 0x96, 0xa1, 0xf8, 0x13, 0x35,
234
+ 0x5f, 0xe1, 0x38, 0x48, 0xd8, 0x73, 0x95, 0xa4,
235
+ 0xf7, 0x02, 0x06, 0x0a, 0x1e, 0x22, 0x66, 0xaa,
236
+ 0xe5, 0x34, 0x5c, 0xe4, 0x37, 0x59, 0xeb, 0x26,
237
+ 0x6a, 0xbe, 0xd9, 0x70, 0x90, 0xab, 0xe6, 0x31,
238
+ 0x53, 0xf5, 0x04, 0x0c, 0x14, 0x3c, 0x44, 0xcc,
239
+ 0x4f, 0xd1, 0x68, 0xb8, 0xd3, 0x6e, 0xb2, 0xcd,
240
+ 0x4c, 0xd4, 0x67, 0xa9, 0xe0, 0x3b, 0x4d, 0xd7,
241
+ 0x62, 0xa6, 0xf1, 0x08, 0x18, 0x28, 0x78, 0x88,
242
+ 0x83, 0x9e, 0xb9, 0xd0, 0x6b, 0xbd, 0xdc, 0x7f,
243
+ 0x81, 0x98, 0xb3, 0xce, 0x49, 0xdb, 0x76, 0x9a,
244
+ 0xb5, 0xc4, 0x57, 0xf9, 0x10, 0x30, 0x50, 0xf0,
245
+ 0x0b, 0x1d, 0x27, 0x69, 0xbb, 0xd6, 0x61, 0xa3,
246
+ 0xfe, 0x19, 0x2b, 0x7d, 0x87, 0x92, 0xad, 0xec,
247
+ 0x2f, 0x71, 0x93, 0xae, 0xe9, 0x20, 0x60, 0xa0,
248
+ 0xfb, 0x16, 0x3a, 0x4e, 0xd2, 0x6d, 0xb7, 0xc2,
249
+ 0x5d, 0xe7, 0x32, 0x56, 0xfa, 0x15, 0x3f, 0x41,
250
+ 0xc3, 0x5e, 0xe2, 0x3d, 0x47, 0xc9, 0x40, 0xc0,
251
+ 0x5b, 0xed, 0x2c, 0x74, 0x9c, 0xbf, 0xda, 0x75,
252
+ 0x9f, 0xba, 0xd5, 0x64, 0xac, 0xef, 0x2a, 0x7e,
253
+ 0x82, 0x9d, 0xbc, 0xdf, 0x7a, 0x8e, 0x89, 0x80,
254
+ 0x9b, 0xb6, 0xc1, 0x58, 0xe8, 0x23, 0x65, 0xaf,
255
+ 0xea, 0x25, 0x6f, 0xb1, 0xc8, 0x43, 0xc5, 0x54,
256
+ 0xfc, 0x1f, 0x21, 0x63, 0xa5, 0xf4, 0x07, 0x09,
257
+ 0x1b, 0x2d, 0x77, 0x99, 0xb0, 0xcb, 0x46, 0xca,
258
+ 0x45, 0xcf, 0x4a, 0xde, 0x79, 0x8b, 0x86, 0x91,
259
+ 0xa8, 0xe3, 0x3e, 0x42, 0xc6, 0x51, 0xf3, 0x0e,
260
+ 0x12, 0x36, 0x5a, 0xee, 0x29, 0x7b, 0x8d, 0x8c,
261
+ 0x8f, 0x8a, 0x85, 0x94, 0xa7, 0xf2, 0x0d, 0x17,
262
+ 0x39, 0x4b, 0xdd, 0x7c, 0x84, 0x97, 0xa2, 0xfd,
263
+ 0x1c, 0x24, 0x6c, 0xb4, 0xc7, 0x52, 0xf6, 0x01]
264
+
265
+ GF256_LOG = [
266
+ 0x00, 0x00, 0x19, 0x01, 0x32, 0x02, 0x1a, 0xc6,
267
+ 0x4b, 0xc7, 0x1b, 0x68, 0x33, 0xee, 0xdf, 0x03,
268
+ 0x64, 0x04, 0xe0, 0x0e, 0x34, 0x8d, 0x81, 0xef,
269
+ 0x4c, 0x71, 0x08, 0xc8, 0xf8, 0x69, 0x1c, 0xc1,
270
+ 0x7d, 0xc2, 0x1d, 0xb5, 0xf9, 0xb9, 0x27, 0x6a,
271
+ 0x4d, 0xe4, 0xa6, 0x72, 0x9a, 0xc9, 0x09, 0x78,
272
+ 0x65, 0x2f, 0x8a, 0x05, 0x21, 0x0f, 0xe1, 0x24,
273
+ 0x12, 0xf0, 0x82, 0x45, 0x35, 0x93, 0xda, 0x8e,
274
+ 0x96, 0x8f, 0xdb, 0xbd, 0x36, 0xd0, 0xce, 0x94,
275
+ 0x13, 0x5c, 0xd2, 0xf1, 0x40, 0x46, 0x83, 0x38,
276
+ 0x66, 0xdd, 0xfd, 0x30, 0xbf, 0x06, 0x8b, 0x62,
277
+ 0xb3, 0x25, 0xe2, 0x98, 0x22, 0x88, 0x91, 0x10,
278
+ 0x7e, 0x6e, 0x48, 0xc3, 0xa3, 0xb6, 0x1e, 0x42,
279
+ 0x3a, 0x6b, 0x28, 0x54, 0xfa, 0x85, 0x3d, 0xba,
280
+ 0x2b, 0x79, 0x0a, 0x15, 0x9b, 0x9f, 0x5e, 0xca,
281
+ 0x4e, 0xd4, 0xac, 0xe5, 0xf3, 0x73, 0xa7, 0x57,
282
+ 0xaf, 0x58, 0xa8, 0x50, 0xf4, 0xea, 0xd6, 0x74,
283
+ 0x4f, 0xae, 0xe9, 0xd5, 0xe7, 0xe6, 0xad, 0xe8,
284
+ 0x2c, 0xd7, 0x75, 0x7a, 0xeb, 0x16, 0x0b, 0xf5,
285
+ 0x59, 0xcb, 0x5f, 0xb0, 0x9c, 0xa9, 0x51, 0xa0,
286
+ 0x7f, 0x0c, 0xf6, 0x6f, 0x17, 0xc4, 0x49, 0xec,
287
+ 0xd8, 0x43, 0x1f, 0x2d, 0xa4, 0x76, 0x7b, 0xb7,
288
+ 0xcc, 0xbb, 0x3e, 0x5a, 0xfb, 0x60, 0xb1, 0x86,
289
+ 0x3b, 0x52, 0xa1, 0x6c, 0xaa, 0x55, 0x29, 0x9d,
290
+ 0x97, 0xb2, 0x87, 0x90, 0x61, 0xbe, 0xdc, 0xfc,
291
+ 0xbc, 0x95, 0xcf, 0xcd, 0x37, 0x3f, 0x5b, 0xd1,
292
+ 0x53, 0x39, 0x84, 0x3c, 0x41, 0xa2, 0x6d, 0x47,
293
+ 0x14, 0x2a, 0x9e, 0x5d, 0x56, 0xf2, 0xd3, 0xab,
294
+ 0x44, 0x11, 0x92, 0xd9, 0x23, 0x20, 0x2e, 0x89,
295
+ 0xb4, 0x7c, 0xb8, 0x26, 0x77, 0x99, 0xe3, 0xa5,
296
+ 0x67, 0x4a, 0xed, 0xde, 0xc5, 0x31, 0xfe, 0x18,
297
+ 0x0d, 0x63, 0x8c, 0x80, 0xc0, 0xf7, 0x70, 0x07]
298
+
299
+
300
+ def _gf256_add(a, b)
301
+ val = a ^ b
302
+ val
303
+ end
304
+
305
+ def _gf256_sub(a,b)
306
+ _gf256_add(a,b)
307
+ end
308
+
309
+ def _gf256_mul(a,b)
310
+ a = a.to_i
311
+ b = b.to_i
312
+ if a == 0 || b == 0
313
+ return 0
314
+ else
315
+ GF256_EXP[(GF256_LOG[a] + GF256_LOG[b]) % 255]
316
+ end
317
+ end
318
+
319
+ def _gf256_div(a,b)
320
+ if a == 0
321
+ return 0
322
+ elsif b == 0
323
+ raise ZeroDivisionError
324
+ else
325
+ GF256_EXP[(GF256_LOG[a] - GF256_LOG[b]) % 255]
326
+ end
327
+ end
328
+ end # class ShamirSharing
329
+
330
+ end
331
+ end
@@ -0,0 +1,34 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Ruby
5
+ class SecureRandomEngine
6
+
7
+ def self.random_bytes(size)
8
+ SecureRandom.random_bytes(size)
9
+ end
10
+
11
+ def self.random_hex(size)
12
+ SecureRandom.hex(size)
13
+ end
14
+
15
+ def self.random_b64(size)
16
+ SecureRandom.base64(size)
17
+ end
18
+
19
+ def self.random_uuid
20
+ SecureRandom.uuid
21
+ end
22
+
23
+ def self.random_alphanum(size)
24
+ SecureRandom.alphanumeric(size)
25
+ end
26
+
27
+ def self.random_number(val = nil)
28
+ SecureRandom.rand(val)
29
+ end
30
+ self.singleton_class.alias_method :rand, :random_number
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,213 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Ruby
5
+ class X509Engine
6
+ include TR::CondUtils
7
+
8
+ include TeLogger::TeLogHelper
9
+ teLogger_tag :x509Eng
10
+
11
+ def initialize(cert_profile)
12
+ @certProfile = cert_profile
13
+ end
14
+
15
+ def generate(issuerKey, &block)
16
+
17
+ cp = @certProfile
18
+ cert = OpenSSL::X509::Certificate.new
19
+ cert.version = 2
20
+ cert.serial = OpenSSL::BN.new(cp.serial, 16)
21
+ cert.subject = to_cert_subject
22
+
23
+ ext = OpenSSL::X509::ExtensionFactory.new
24
+ ext.subject_certificate = cert
25
+
26
+ iss = cp.issuer_cert
27
+
28
+ iss = iss.nativeX509 if iss.is_a?(Ccrypto::X509Cert)
29
+
30
+ if not_empty?(iss)
31
+ raise X509EngineException, "Issuer certificate must be X509 Certificate object" if not iss.is_a?(OpenSSL::X509::Certificate)
32
+ cert.issuer = iss.subject
33
+ ext.issuer_certificate = iss
34
+
35
+ cp.match_issuer_not_before(iss.not_before)
36
+ cp.match_issuer_not_after(iss.not_after)
37
+
38
+ else
39
+ cert.issuer = cert.subject
40
+ ext.issuer_certificate = cert
41
+ end
42
+
43
+ cert.not_before = cp.not_before
44
+ cert.not_after = cp.not_after
45
+
46
+ case cp.public_key
47
+ when Ccrypto::PublicKey
48
+ pubKey = cp.public_key.native_pubKey
49
+ else
50
+ raise X509EngineException, "Public key type '#{cp.public_key.class}' is not supported"
51
+ end
52
+
53
+ if pubKey.is_a?(OpenSSL::PKey::EC::Point)
54
+ # ECC patch
55
+ pub = OpenSSL::PKey::EC.new(pubKey.group)
56
+ pub.public_key = pubKey
57
+ cert.public_key = pub
58
+ else
59
+ cert.public_key = pubKey
60
+ end
61
+
62
+ cert.add_extension(ext.create_extension("basicConstraints","CA:TRUE",true)) if cp.gen_issuer_cert?
63
+ cert.add_extension(ext.create_extension("subjectKeyIdentifier","hash")) if cp.gen_subj_key_id?
64
+ cert.add_extension(ext.create_extension("authorityKeyIdentifier","keyid:always,issuer:always")) if cp.gen_auth_key_id?
65
+
66
+ #cert.add_extension(ext.create_extension("keyUsage",to_keyusage,true))
67
+ cp.key_usage.selected.each do |ku,critical|
68
+ teLogger.debug "Setting KeyUsage : #{ku} (#{critical})"
69
+ case ku
70
+ when :crlSign
71
+ cert.add_extension(ext.create_extension("keyUsage","cRLSign",critical))
72
+ else
73
+ cert.add_extension(ext.create_extension("keyUsage",ku.to_s,critical))
74
+ end
75
+ end
76
+
77
+
78
+ #extKeyUsage = to_extkeyusage
79
+ extKeyUsage = []
80
+ cp.ext_key_usage.selected.each do |ku,critical|
81
+ case ku
82
+ when :allPurpose
83
+ #kur << :anyExtendedKeyUsage
84
+ cert.add_extension(ext.create_extension("extendedKeyUsage","anyExtendedKeyUsage",critical))
85
+ when :timestamping
86
+ #kur << :timeStamping
87
+ cert.add_extension(ext.create_extension("extendedKeyUsage","timeStamping",critical))
88
+ when :ocspSigning
89
+ #kur << :oCSPSigning
90
+ cert.add_extension(ext.create_extension("extendedKeyUsage","oCSPSigning",critical))
91
+ when :ipSecIKE
92
+ #kur << :ipsecIKE
93
+ cert.add_extension(ext.create_extension("extendedKeyUsage","ipsecIKE",critical))
94
+ when :msCtlsign
95
+ #kur << :msCTLSign
96
+ cert.add_extension(ext.create_extension("extendedKeyUsage","msCTLSign",critical))
97
+ when :msEFS
98
+ #kur << :msEfs
99
+ cert.add_extension(ext.create_extension("extendedKeyUsage","msEfs",critical))
100
+ else
101
+ #kur << ku
102
+ cert.add_extension(ext.create_extension("extendedKeyUsage",ku.to_s,critical))
103
+ end
104
+ end
105
+
106
+ cp.domain_key_usage.each do |dku, critical|
107
+ cert.add_extension(ext.create_extension("extendedKeyUsage",dku.to_s,critical))
108
+ end
109
+
110
+ cert.add_extension(ext.create_extension("subjectAltName","email:#{cp.email.join(",email:")}",false)) if not_empty?(cp.email)
111
+ cert.add_extension(ext.create_extension("subjectAltName","DNS:#{cp.dns_name.join(",DNS:")}",false)) if not_empty?(cp.dns_name)
112
+ cert.add_extension(ext.create_extension("subjectAltName","IP:#{cp.ip_addr.join(",IP:")}",false)) if not_empty?(cp.ip_addr)
113
+ cert.add_extension(ext.create_extension("subjectAltName","URI:#{cp.uri.join(",URI:")}",false)) if not_empty?(cp.uri)
114
+
115
+ # try to sync the structure with Java BC output
116
+ # whereby single name = multiple URI however failed
117
+ # If single format is required need more R&D
118
+ #
119
+ #crlDistPoint = []
120
+ #if not_empty?(cp.crl_dist_point)
121
+ # cnt = 1
122
+ # cp.crl_dist_point.each do |cdp|
123
+ # crlDistPoint << "URI.#{cnt}:#{cdp}"
124
+ # cnt += 1
125
+ # end
126
+ #end
127
+ #p crlDistPoint.join(",")
128
+ #cert.add_extension(ext.create_extension("crlDistributionPoints","URI:#{crlDistPoint.join(",")}",false)) if not_empty?(crlDistPoint)
129
+ #
130
+ cert.add_extension(ext.create_extension("crlDistributionPoints","URI:#{cp.crl_dist_point.join(",URI:")}",false)) if not_empty?(cp.crl_dist_point)
131
+
132
+ aia = []
133
+ aia << "OCSP;URI:#{cp.ocsp_url.join(",OCSP;URI:")}" if not_empty?(cp.ocsp_url)
134
+ aia << "caIssuers;URI:#{cp.issuer_url.join(",caIssuers;URI:")}" if not_empty?(cp.issuer_url)
135
+ cert.add_extension(ext.create_extension("authorityInfoAccess",aia.join(","),false)) if not_empty?(aia)
136
+
137
+
138
+ case issuerKey
139
+ when Ccrypto::KeyBundle
140
+ privKey = issuerKey.private_key.native_privKey
141
+ when Ccrypto::PrivateKey
142
+ privKey = issuerKey.native_privKey
143
+ else
144
+ raise X509EngineException, "Unsupported issuer key #{issuerKey}"
145
+ end
146
+
147
+ res = cert.sign(privKey, DigestEngine.instance(cp.hashAlgo).native_instance)
148
+
149
+ Ccrypto::X509Cert.new(res)
150
+
151
+ end
152
+
153
+ private
154
+ def to_cert_subject
155
+ res = []
156
+ res << ["CN", @certProfile.owner_name]
157
+ res << ["O", @certProfile.org] if not_empty?(@certProfile.org)
158
+ @certProfile.org_unit.each do |ou|
159
+ res << ["OU", ou]
160
+ end
161
+
162
+ e = @certProfile.email.first
163
+ if not_empty?(e)
164
+ res << ["emailAddress", e]
165
+ end
166
+
167
+ OpenSSL::X509::Name.new(res)
168
+ end
169
+
170
+ #def to_keyusage
171
+ # kur = []
172
+ # @certProfile.key_usage.selected.each do |ku,critical|
173
+ # case ku
174
+ # when :crlSign
175
+ # cert.add_extension(ext.create_extension("keyUsage",:cRLSign,critical))
176
+ # #kur << :cRLSign
177
+ # else
178
+ # #kur << ku
179
+ # cert.add_extension(ext.create_extension("keyUsage",ku,critical))
180
+ # end
181
+ # end
182
+
183
+ # #kur.join(",")
184
+ #end
185
+
186
+ #def to_extkeyusage
187
+ # kur = []
188
+ # @certProfile.ext_key_usage.selected.keys.each do |ku|
189
+ # case ku
190
+ # when :allPurpose
191
+ # kur << :anyExtendedKeyUsage
192
+ # when :timestamping
193
+ # kur << :timeStamping
194
+ # when :ocspSigning
195
+ # kur << :oCSPSigning
196
+ # when :ipSecIKE
197
+ # kur << :ipsecIKE
198
+ # when :msCtlsign
199
+ # kur << :msCTLSign
200
+ # when :msEFS
201
+ # kur << :msEfs
202
+ # else
203
+ # kur << ku
204
+ # end
205
+ # end
206
+
207
+ # #kur.join(",")
208
+ # kur
209
+ #end
210
+
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,24 @@
1
+
2
+
3
+ module Ccrypto
4
+ class SecretKey
5
+
6
+ def to_bin
7
+ case @key
8
+ when String
9
+ @key
10
+ else
11
+ @key.key
12
+ end
13
+ end
14
+
15
+ def length
16
+ to_bin.length
17
+ end
18
+
19
+ def equals?(key)
20
+ to_bin == key
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+
2
+
3
+ module Ccrypto
4
+ class X509Cert
5
+ include TR::CondUtils
6
+
7
+ def equal?(cert)
8
+ if is_empty?(cert)
9
+ if is_empty?(@nativeX509)
10
+ true
11
+ else
12
+ false
13
+ end
14
+ else
15
+ @nativeX509.to_der == cert.to_der
16
+ end
17
+ end
18
+
19
+ def method_missing(mtd, *args, &block)
20
+ @nativeX509.send(mtd, *args, &block)
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,73 @@
1
+
2
+
3
+ module Ccrypto
4
+ module Ruby
5
+ module PEMStore
6
+ include TR::CondUtils
7
+ include DataConversion
8
+
9
+ class PEMStoreException < KeyBundleStorageException; end
10
+
11
+ module ClassMethods
12
+ def is_pem?(input)
13
+ if is_empty?(input)
14
+ false
15
+ else
16
+ begin
17
+ (input =~ /BEGIN/) != nil
18
+ rescue ArgumentError => ex
19
+ if ex.message =~ /invalid byte sequence/
20
+ false
21
+ else
22
+ raise KeypairEngineException, ex
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def from_pem(input, &block)
29
+
30
+ begin
31
+ # try with no password first to check if the keystore is really encrypted
32
+ # If not the library will prompt at command prompt which might halt the flow of program
33
+ pKey = OpenSSL::PKey.read(input,"")
34
+ ECCKeyBundle.new(pKey)
35
+ rescue OpenSSL::PKey::PKeyError => ex
36
+ raise PEMStoreException, "block is required" if not block
37
+ pass = block.call(:pem_pass)
38
+ begin
39
+ pKey = OpenSSL::PKey.read(input, pass)
40
+ ECCKeyBundle.new(pKey)
41
+ rescue OpenSSL::PKey::PKeyError => exx
42
+ raise PEMStoreException, exx
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ def self.included(klass)
49
+ klass.extend(ClassMethods)
50
+ end
51
+
52
+ def to_pem(&block)
53
+ raise PEMStoreException, "Block is required" if not block
54
+ kcipher = block.call(:pem_cipher)
55
+ kpass = block.call(:pem_pass)
56
+
57
+ kcipher = "AES-256-GCM" if is_empty?(kcipher)
58
+
59
+ keypair = block.call(:keypair)
60
+ raise PEMStoreException, "Keypair is required" if is_empty?(keypair)
61
+
62
+ if not_empty?(kpass)
63
+ kCipher = OpenSSL::Cipher.new(kcipher)
64
+ keypair.export(kCipher, kpass)
65
+ else
66
+ keypair.export
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
73
+ end