require 'pkernel' require 'pkernel_jce' require_relative 'error' require_relative 'io_utils' require_relative 'provider' require_relative 'global' module GcryptoJce module KeyPairCrypto def sign(opts = { }) raise GcryptoJce::Error, "Insufficient parameters for signature generation" if opts.nil? or opts.empty? id = opts[:identity] if id.nil? raise GcryptoJce::Error, "Identity to sign the data is not available" end prov = GcryptoJce::Provider.handle_options(opts, nil) is = IoUtils.load_input(opts) if prov.nil? GcryptoJce::GConf.instance.glog.debug "Provider is nil" sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(id.privKey)) else GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'" sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(id.privKey), prov) end GcryptoJce::GConf.instance.glog.debug "Private key is #{id.privKey.class}" sign.initSign(id.privKey) begin IoUtils.read_chunk(is) do |buf, from, len| sign.update(buf, from, len) end rescue Exception => ex GcryptoJce::GConf.instance.glog.error ex.message GcryptoJce::GConf.instance.glog.error ex.backtrace.join("\n") ensure begin is.close rescue Exception end end sign.sign end # # end method sign() # def KeyPairCrypto.derive_signing_algo(kp, hash = "SHA256") PkernelJce::KeyPair.derive_signing_algo(kp,hash) end def verify(opts = { }) if opts.nil? or opts.empty? raise GcryptoJce::Error, "Insufficient parameters for signature verification" end file = opts[:sign_file] bin = opts[:sign_bin] if not (file.nil? or file.empty?) signBin = IoUtils.file_to_memory_byte_array(file) elsif not bin.nil? signBin = IoUtils.ensure_java_bytes(bin) else raise GcryptoJce::Error, "Neither signature in file or memory buffer given for signatur verification" end is = IoUtils.load_input(opts) prov = GcryptoJce::Provider.handle_options(opts, nil) cert = opts[:certificate] pubKey = opts[:pubKey] if not cert.nil? if prov.nil? GcryptoJce::GConf.instance.glog.debug "Provider is nil" sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(cert)) else GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'" sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(cert), prov) end sign.initVerify(cert) elsif not pubKey.nil? if prov.nil? GcryptoJce::GConf.instance.glog.debug "Provider is nil" sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(pubKey)) else GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'" sign = java.security.Signature.getInstance(KeyPairCrypto.derive_signing_algo(pubKey), prov) end sign.initVerify(pubKey) else raise GcryptoJce::Error, "No public key or certificate during signature verification" end begin IoUtils.read_chunk(is) do |buf, from, len| sign.update(buf, from, len) end rescue Exception => ex GcryptoJce::GConf.instance.glog.error ex.message GcryptoJce::GConf.instance.glog.error ex.backtrace.join("\n") ensure begin is.close rescue Exception end end sign.verify(signBin) end # # end method verify() # def encrypt(opts = { }) file = opts[:file] bin = opts[:bin] # assumption: # Data size is small (~kb) # Because for RSA the max data = public key size if not (file.nil? or file.empty?) data = IoUtils.file_to_memory_byte_array(file) elsif not bin.nil? data = IoUtils.ensure_java_bytes(bin) else raise GcryptoJce::Error, "No input given for keypair encryption" end recp = opts[:recipient] if recp.nil? raise GcryptoJce::Error, "No recipient given for keypair encryption" end if Pkernel::Certificate.is_cert_object?(recp) pubKey = Pkernel::Certificate.public_key(recp) elsif Pkernel::KeyPair.is_public_key?(recp) pubKey = recp else raise GcryptoJce::Error, "Given recipient is neither certificate nor public key." end prov = GcryptoJce::Provider.handle_options(opts, nil) cipherSpec = opts[:cipher_spec] || "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" type = Pkernel::KeyPair.pub_key_type(pubKey) case type when Pkernel::KeyPair::RSA_KEY_NAME if prov.nil? GcryptoJce::GConf.instance.glog.debug "Provider is nil" if cipherSpec =~ /PKCS5Padding/ GcryptoJce::GConf.instance.glog.warn "PKCS#1 1.5 may be vulnerable to Bleichenbacher's CCA attack" end GcryptoJce::GConf.instance.glog.debug "Using cipher spec '#{cipherSpec}'" cipher = javax.crypto.Cipher.getInstance(cipherSpec) else GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'" cipher = javax.crypto.Cipher.getInstance(cipherSpec, prov) end else raise GcryptoJce::Error, "Unsupported key type '#{pubKey}' for keypair data encryption operation" end cipher.init(javax.crypto.Cipher::ENCRYPT_MODE, pubKey) outStream = opts[:outStream] if not outStream.nil? outStream.write(cipher.update(data)) outStream.write(cipher.doFinal) outStream.flush else baos = java.io.ByteArrayOutputStream.new baos.write(cipher.update(data)) baos.write(cipher.doFinal) baos.toByteArray end end # # end encrypt() # def decrypt(opts = { }) file = opts[:enc_file] bin = opts[:enc_bin] # assumption: # Data size is small (~kb) # Because for RSA the max data = public key size if not (file.nil? or file.empty?) data = IoUtils.file_to_memory_byte_array(file) elsif not bin.nil? data = IoUtils.ensure_java_bytes(bin) else raise GcryptoJce::Error, "No input given for decrypt" end id = opts[:identity] if id.nil? raise GcryptoJce::Error, "No identity given for decrypt" end if id.privKey.nil? raise GcryptoJce::Error, "Private key is nil for data decryption" end prov = GcryptoJce::Provider.handle_options(opts, nil) cipherSpec = opts[:cipher_spec] || "RSA/ECB/OAEPWithSHA-256AndMGF1Padding" type = Pkernel::KeyPair.key_type(id.privKey) case type when Pkernel::KeyPair::RSA_KEY_NAME if prov.nil? GcryptoJce::GConf.instance.glog.debug "Provider is nil" if cipherSpec =~ /PKCS5Padding/ GcryptoJce::GConf.instance.glog.warn "PKCS#1 1.5 may be vulnerable to Bleichenbacher's CCA attack" end GcryptoJce::GConf.instance.glog.debug "Using cipher spec '#{cipherSpec}'" cipher = javax.crypto.Cipher.getInstance(cipherSpec) else GcryptoJce::GConf.instance.glog.debug "Provider is '#{prov.name}'" cipher = javax.crypto.Cipher.getInstance(cipherSpec, prov) end else raise GcryptoJce::Error, "Unsupported key type '#{id.privKey}' for data decryption operation" end cipher.init(javax.crypto.Cipher::DECRYPT_MODE, id.privKey) outStream = opts[:outStream] if not outStream.nil? outStream.write(cipher.update(data)) outStream.write(cipher.doFinal) outStream.flush else baos = java.io.ByteArrayOutputStream.new baos.write(cipher.update(data)) baos.write(cipher.doFinal) baos.toByteArray end end # # end decrypt() # end # end KeyPairCrypto # class KeyPairCryptoEngine extend KeyPairCrypto end end # end gcrypto