module PkernelJce::IdentityFactory
Public Instance Methods
build_from_components(key, cert = nil, chain = [], provider = nil)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 161 def build_from_components(key, cert = nil, chain = [], provider = nil) if key.nil? raise PkernelJce::Error, "Key cannot be nil to build identity" end id = Pkernel::Identity.new( { key: key, certificate: cert, chain: chain } ) if cert.nil? class_eval do include PkernelJce::IdentityManagement end else c = PkernelJce::Certificate.ensure_java_cert(cert) if PkernelJce::Certificate.is_issuer_cert?(c) class_eval do include PkernelJce::IdentityIssuer include PkernelJce::IdentityManagement end else class_eval do include PkernelJce::IdentityManagement end end end id.provider = provider id end
Also aliased as: build
dump(id, opts = {}, &block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 192 def dump(id, opts = {}, &block) if id.nil? raise PkernelJce::Error, "Identity object is nil in write to keystore" end result = { } format = opts[:format] case format when :pkcs8, :pk8, :p8 res = dump_pk8(id, opts, &block) # private key file = opts[:file] if file.nil? or file.empty? result[:bin] = res[:bin] else ff = java.io.File.new(file) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(ff) fos.write res[:bin].to_java.getBytes fos.flush fos.close result[:file] = file end # certificate cfile = opts[:cert_file] if not cfile.nil? ff = java.io.File.new(cfile) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(ff) fos.write res[:cert_bin] fos.flush fos.close result[:cert_file] = cfile else result[:cert_bin] = res[:cert_bin] end # cert chain cafile = opts[:ca_file] if not cafile.nil? ff = java.io.File.new(cafile) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(ff) res[:ca_bin].each do |ca| fos.write ca end fos.flush fos.close result[:ca_file] = cafile else result[:ca_bin] = res[:ca_bin] end result when :pem res = dump_pem(id, opts, &block) # private key file = opts[:file] if file.nil? or file.empty? result[:bin] = res[:bin] else ff = java.io.File.new(file) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(ff) fos.write res[:bin] fos.flush fos.close result[:file] = file end # public key cfile = opts[:pubKey_file] if not cfile.nil? ff = java.io.File.new(cfile) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(ff) fos.write res[:pubKey_bin] fos.flush fos.close result[:pubKey_file] = cfile else result[:pubKey_bin] = res[:pubKey_bin] end # certificate cfile = opts[:cert_file] if not cfile.nil? ff = java.io.File.new(cfile) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(ff) fos.write res[:cert_bin] fos.flush fos.close result[:cert_file] = cfile else result[:cert_bin] = res[:cert_bin] end # cert chain cafile = opts[:ca_file] if not cafile.nil? ff = java.io.File.new(cafile) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(ff) res[:ca_bin].each do |ca| fos.write ca end fos.flush fos.close result[:ca_file] = cafile else result[:ca_bin] = res[:ca_bin] end result else # JCE/JCA keystore rres = dump_keystore(id, opts, &block) result.merge!(rres) file = opts[:file] if file.nil? or file.empty? else ff = java.io.File.new(file) ff.parent_file.mkdirs if not ff.parent_file.exists? fos = java.io.FileOutputStream.new(file) fos.write result[:bin] fos.flush fos.close result[:file] = file end result end end
dump_to_file(id, file, opts = { }, &block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 345 def dump_to_file(id, file, opts = { }, &block) opts = { } if opts.nil? raise PkernelJce::Error, "Option for dump to file must be a hash" if not opts.is_a?(Hash) dump(id, opts.merge({ file: file }), &block) end
dump_to_file_p8(id, idFile, certFile, caFile, password, opts = { }, &block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 351 def dump_to_file_p8(id, idFile, certFile, caFile, password, opts = { }, &block) opts = { } if opts.nil? raise PkernelJce::Error, "Option for dump to file in pkcs8 format must be a hash" if not opts.is_a?(Hash) raise PkernelJce::Error, "Identity file path cannot be empty" if empty?(idFile) raise PkernelJce::Error, "Certificate file path cannot be empty" if empty?(certFile) raise PkernelJce::Error, "CA chain file path cannot be empty" if empty?(caFile) dump(id, opts.merge({ file: idFile, cert_file: certFile, ca_file: caFile, format: :pkcs8 }),&block) end
load(opts = {}, &block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 362 def load(opts = {}, &block) format = opts[:format] case format when :pk8, :p8, :pkcs8 res = load_pk8(opts, &block) when :pem res = load_pem(opts, &block) else res = load_keystore(opts, &block) end if res[:key].nil? raise Pkernel::Error, "Failed to load key from the store." end Pkernel::Identity.new( { privKey: res[:key], certificate: res[:cert], chain: res[:chain] } ) end
Private Instance Methods
dump_keystore(id, opts = { }, &block)
click to toggle source
end load()
# File lib/pkernel_jce/identity.rb, line 383 def dump_keystore(id, opts = { }, &block) result = { } prov = opts[:provider] if prov.nil? prov = PkernelJce::Provider.add_default else prov = PkernelJce::Provider.add_provider(prov) end case opts[:format] when :p12, :pkcs12 stype = "PKCS12" when :jks, :java stype = "jks" when :bks stype = "bks" else PkernelJce::GConf.instance.glog.debug "No keystore type given. Default to pkcs12 keystore" stype = "PKCS12" end if prov.nil? or stype == "jks" PkernelJce::GConf.instance.glog.debug "Loading #{stype} keystore with null provider" ks = java.security.KeyStore.getInstance(stype) else PkernelJce::GConf.instance.glog.debug "Loading #{stype} keystore with provider #{prov.name}" ks = java.security.KeyStore.getInstance(stype,prov) end pass = opts[:password] if pass.nil? or pass.empty? if block pass = block.call(:prompt_pass) end end passLen = opts[:password_length] || 8 # cannot be too small... if (passLen/2) < 8 passLen = 8 else passLen = passLen/2 end if pass.nil? or pass.empty? PkernelJce::GConf.instance.glog.warn "Password is not given to dump identity. Random password of #{passLen*2} characters shall be generated." pass = SecureRandom.hex(passLen) result[:password] = pass end chain = id.chain.map do |c| if c.java_kind_of?(org.bouncycastle.cert.X509CertificateHolder) c.to_java_cert else c end end name = opts[:key_name] || opts[:keyName] || opts[:keyname] || Certificate.get_subject_fields(id.certificate,[:cn])[:cn][0] ks.load(nil,nil) ks.setKeyEntry(name, id.privKey, pass.to_java.toCharArray, chain.to_java(java.security.cert.Certificate)) baos = java.io.ByteArrayOutputStream.new ks.store(baos, pass.to_java.toCharArray) result[:bin] = baos.toByteArray result end
dump_pem(id,opts,&block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 543 def dump_pem(id,opts,&block) result = { } baos = java.io.ByteArrayOutputStream.new pass = opts[:password] if (pass.nil? or pass.empty?) and block pass = block.call(:prompt_pass) end PkernelJce::Provider.add_default writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos)) if pass.nil? or pass.empty? PkernelJce::GConf.instance.glog.debug "Constructing plain PEM..." writer.writeObject(id.privKey) else PkernelJce::GConf.instance.glog.debug "Constructing encrypted PEM..." encryptor = org.bouncycastle.openssl.jcajce.JcePEMEncryptorBuilder.new("AES-256-GCM").build(pass.to_java.toCharArray) writer.writeObject(id.privKey,encryptor) end writer.flush writer.close result[:bin] = baos.toByteArray baos.reset writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos)) writer.writeObject(id.certificate) writer.flush writer.close result[:cert_bin] = baos.toByteArray baos.reset writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos)) writer.writeObject(id.pubKey) writer.flush writer.close result[:pubKey_bin] = baos.toByteArray cc = [] id.chain.each do |c| baos.reset writer = org.bouncycastle.openssl.PEMWriter.new(java.io.OutputStreamWriter.new(baos)) writer.writeObject(c) writer.flush writer.close cc << baos.toByteArray end result[:ca_bin] = cc result end
dump_pk8(id, opts, &block)
click to toggle source
dump_pk8
()
# File lib/pkernel_jce/identity.rb, line 674 def dump_pk8(id, opts, &block) PkernelJce::GConf.instance.glog.debug "Dump to PKCS8 format..." result = { } pass = opts[:password] if (pass.nil? or pass.empty?) and block pass = block.call(:prompt_pass) end prov = opts[:provider] if not prov.nil? prov = PkernelJce::Provider.add_provider(prov) end # private key only # remove file parameter if given # because we want the dump to be available here keyDumpPara = opts.clone keyDumpPara.delete(:file) # KeyPair already using the PKCS8 format for output... might as well just reuse... rres = PkernelJce::KeyPairEngine.dump(id.keypair, keyDumpPara, &block) result[:bin] = rres result[:cert_bin] = PkernelJce::CertificateEngine.dump(id.certificate, { outForm: :pem }) cc = [] id.chain.each do |c| cc << PkernelJce::CertificateEngine.dump(c, { outForm: :pem }) end result[:ca_bin] = cc result end
load_keystore(opts = { }, &block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 456 def load_keystore(opts = { }, &block) result = { } prov = opts[:provider] if not prov.nil? prov = PkernelJce::Provider.add_provider(prov) end format = opts[:format] format = :p12 if format.nil? sFormat = format case format.to_sym when :p12, :pkcs12 PkernelJce::GConf.instance.glog.debug "Loading PKCS12 keystore" pprov = PkernelJce::Provider.add_default ks = java.security.KeyStore.getInstance("PKCS12",pprov) result[:ks_format] = :p12 when :jks PkernelJce::GConf.instance.glog.debug "Loading JKS keystore" ks = java.security.KeyStore.getInstance("JKS") result[:ks_format] = :jks when :pk8, :pkcs8, :p8 else PkernelJce::GConf.instance.glog.debug "Loading '#{format}' keystore" if prov.nil? ks = java.security.KeyStore.getInstance(format.to_s) else ks = java.security.KeyStore.getInstance(format.to_s, prov) end result[:ks_format] = format end pass = opts[:password] if (pass.nil? or pass.empty?) and block pass = block.call(:prompt_pass) end file = opts[:file] bin = opts[:bin] baos = java.io.ByteArrayOutputStream.new if not (file.nil? or file.empty?) fis = java.io.FileInputStream.new(file) ks.load(fis,pass.to_java.toCharArray) fis.close elsif not bin.nil? ks.load(java.io.ByteArrayInputStream.new(bin),pass.to_java.toCharArray) else raise PkernelJce::Error, "No file or bin in keystore format is given to load identity" end keyname = opts[:keyname] || opts[:keyName] || opts[:key_name] if not (keyname.empty? or keyname.nil?) result[:ks_alias] = keyname else aliases = ks.aliases.to_a if aliases.length == 0 raise PkernelJce::Error, "No alias available from the keystore" end if aliases.length > 1 # more the 1 aliases # to ensure the loading is correct, call block or error if block result[:ks_alias] = block.call(:multiple_aliases, aliases) else raise PkernelJce::Error, "Multiple aliases exist in the keystores. Please provide keyname to pick one or provide a block for processing" end else result[:ks_alias] = aliases.first end end result[:key] = ks.getKey(result[:ks_alias],pass.to_java.toCharArray) result[:cert] = ks.getCertificate(result[:ks_alias]) result[:chain] = ks.getCertificateChain(result[:ks_alias]) result end
load_pem(opts, &block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 598 def load_pem(opts, &block) res = { } file = opts[:file] bin = opts[:bin] prov = PkernelJce::Provider.add_default converter = org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new.setProvider prov if not (file.nil? or file.empty?) reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.FileInputStream.new(file))) elsif not (bin.nil? or bin.empty?) reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(IoUtils.ensure_java_bytes(bin)))) else raise PkernelJce::Error, "No file or bin in PEM format is given to load identity" end obj = reader.readObject if obj.java_kind_of? org.bouncycastle.openssl.PEMKeyPair res[:keypair] = converter.getKeyPair(obj) res[:key] = PkernelJce::KeyPair.private_key(res[:keypair]) elsif obj.java_kind_of? org.bouncycastle.openssl.PEMEncryptedKeyPair PkernelJce::GConf.instance.glog.debug "Loading encrypted PEM..." pass = opts[:password] if (pass.nil? or pass.empty?) and block pass = block.call(:prompt_pass) end if pass.nil? or pass.empty? raise PkernelJce::Error, "The given key file to load is password protected but password is not given. Process shall abort." end decryptor = org.bouncycastle.openssl.jcajce.JcePEMDecryptorProviderBuilder.new.setProvider(prov).build(pass.to_java.toCharArray) res[:keypair] = converter.getKeyPair(obj.decryptKeyPair(decryptor)) res[:key] = PkernelJce::KeyPair.private_key(res[:keypair]) elsif obj.java_kind_of? org.bouncycastle.asn1.pkcs.PrivateKeyInfo res[:key] = converter.getPrivateKey obj else raise PkernelJce::Error, "Unknown object for further processing #{obj.class}" end if not (opts[:cert_file].nil? or opts[:cert_file].empty?) reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.FileInputStream.new(opts[:cert_file]))) res[:cert] = reader.readObject elsif not (opts[:cert_bin].nil? or opts[:cert_bin].empty?) reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(IoUtils.ensure_java_bytes(opts[:cert_bin])))) res[:cert] = reader.readObject end if not (opts[:ca_file].nil? or opts[:ca_file].empty?) reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.FileInputStream.new(opts[:ca_file]))) res[:chain] = [] o = reader.readObject while(o != nil) res[:chain] << o o = reader.readObject end elsif not (opts[:ca_bin].nil? or opts[:ca_bin].empty?) reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(IoUtils.ensure_java_bytes(opts[:ca_bin])))) res[:chain] = [] o = reader.readObject while(o != nil) res[:chain] << o o = reader.readObject end end res end
load_pk8(opts, &block)
click to toggle source
# File lib/pkernel_jce/identity.rb, line 714 def load_pk8(opts, &block) res = { } pass = opts[:password] if (pass.nil? or pass.empty?) and block pass = block.call(:prompt_pass) end prov = opts[:provider] if not prov.nil? prov = PkernelJce::Provider.add_provider(prov) end key = PkernelJce::KeyPairEngine.load(opts) res[:key] = key certPara = { } certPara[:file] = opts[:cert_file] if not (opts[:cert_file].nil? or opts[:cert_file].empty?) certPara[:bin] = opts[:cert_bin] if not (opts[:cert_bin].nil? or opts[:cert_file].empty?) res[:cert] = PkernelJce::CertificateEngine.load(certPara) chainPara = { multiple: true } chainPara[:file] = opts[:ca_file] if not (opts[:ca_file].nil? or opts[:ca_file].empty?) chainPara[:bin] = opts[:ca_bin] if not (opts[:ca_bin].nil? or opts[:ca_bin].empty?) res[:chain] = PkernelJce::CertificateEngine.load(chainPara) res end