module PkernelJce::KeyPair

Public Class Methods

derive_signing_algo(kp, hashAlgo = "SHA256") click to toggle source
# File lib/pkernel_jce/keypair.rb, line 320
def KeyPair.derive_signing_algo(kp, hashAlgo = "SHA256")
  raise PkernelJce::Error, "Hashing algo should not be nil while deriving signing algo" if hashAlgo.nil?
 
  PkernelJce::GConf.instance.glog.debug "Derive signing algo for key '#{kp.class}'"

  if KeyPair.is_keypair?(kp)
    type = PkernelJce::KeyPair.key_type(KeyPair.private_key(kp))
  elsif KeyPair.is_public_key?(kp)
    type = PkernelJce::KeyPair.pub_key_type(kp)
  elsif Certificate.is_cert_object?(kp)
    type = PkernelJce::KeyPair.pub_key_type(Certificate.public_key(kp))
  elsif KeyPair.is_private_key?(kp)
    type = PkernelJce::KeyPair.key_type(kp)
  else
    raise PkernelJce::Error, "Unknown key type to derive signing key algo from"
  end

  #type = PkernelJce::KeyPair.key_type(kp)
  case type
  when Pkernel::KeyPair::RSA_KEY_NAME
    "#{hashAlgo}with#{type.upcase}"
  when Pkernel::KeyPair::DSA_KEY_NAME
    "#{hashAlgo}with#{type.upcase}"
  when Pkernel::KeyPair::EC_KEY_NAME
    "#{hashAlgo}with#{type.upcase}DSA"
  else
    raise PkernelJce::Error, "Unsupported type to derive signing algo '#{type}'"
  end 
end
ensure_java_keypair(kp) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 189
def KeyPair.ensure_java_keypair(kp)
  raise PkernelJce::Error, "Keypair to check for Java keypair type is nil" if kp.nil?
end
is_keypair?(key) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 206
def KeyPair.is_keypair?(key)
  if key.nil?
    false
  else
    case key
    when java.security.KeyPair
      true
    else
      false
    end
  end
end
is_private_key?(key) click to toggle source

end get_key_type

# File lib/pkernel_jce/keypair.rb, line 153
def KeyPair.is_private_key?(key)
  if key.nil?
    false
  else
    case key
    when java.security.interfaces.RSAPrivateCrtKey, Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey, Java::OrgBouncycastleCryptoParams::RSAPrivateCrtKeyParameters,  Java::OrgBouncycastleCryptoParams::DSAPrivateKeyParameters, Java::OrgBouncycastleCryptoParams::ECPrivateKeyParameters, Java::SunSecurityEc::ECPrivateKeyImpl, org.bouncycastle.crypto.AsymmetricCipherKeyPair, java.security.KeyPair
      true
    else
      false
    end
  end
end
is_public_key?(key) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 193
def KeyPair.is_public_key?(key)
  if key.nil?
    false
  else
    case key
    when java.security.interfaces.RSAPublicKey, Java::OrgBouncycastleJcajceProviderAsymmetricDsa::BCDSAPublicKey,Java::sun.security.provider.DSAPublicKey, Java::OrgBouncycastleJcajceProviderAsymmetricEc::BCECPublicKey
      true
    else
      false
    end
  end
end
is_public_key_equals?(pub1, pub2) click to toggle source

Compare 2 public keys

# File lib/pkernel_jce/keypair.rb, line 291
def KeyPair.is_public_key_equals?(pub1, pub2)
  if not (pub1.nil? and pub2.nil?)
    pubkey1 = KeyPair.public_key(pub1)
    pubkey2 = KeyPair.public_key(pub2)

    pubkey1.equals(pubkey2)

  else
    false
  end
end
key_size(kp) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 350
def KeyPair.key_size(kp)
  if KeyPair.is_keypair?(kp)
    type = PkernelJce::KeyPair.key_type(KeyPair.private_key(kp))
  elsif KeyPair.is_public_key?(kp)
    type = PkernelJce::KeyPair.pub_key_type(kp)
  elsif Certificate.is_cert_object?(kp)
    type = PkernelJce::KeyPair.pub_key_type(Certificate.public_key(kp))
  elsif KeyPair.is_private_key?(kp)
    type = PkernelJce::KeyPair.key_type(kp)
  else
    raise PkernelJce::Error, "Unknown key type to derive signing key algo from"
  end

  case type
  when Pkernel::KeyPair::RSA_KEY_NAME
    if PkernelJce::KeyPair::is_keypair?(kp)
      rsaKey = PkernelJce::KeyPair.private_key(kp)
    elsif PkernelJce::KeyPair::is_private_key?(kp)
      rsaKey = PkernelJce::KeyPair.private_key(kp)
    elsif PkernelJce::KeyPair::is_public_key?(kp)
      rsaKey = PkernelJce::KeyPair::public_key(kp)
    end

    rsaKey.modulus.bit_length

  when Pkernel::KeyPair::DSA_KEY_NAME
    if PkernelJce::KeyPair::is_keypair?(kp)
      dsaKey = PkernelJce::KeyPair.private_key(kp)
    elsif PkernelJce::KeyPair::is_private_key?(kp)
      dsaKey = PkernelJce::KeyPair.private_key(kp)
    elsif PkernelJce::KeyPair::is_public_key?(kp)
      dsaKey = PkernelJce::KeyPair::public_key(kp)
    end
   
    dsaKey.params.p.bit_length 

  when Pkernel::KeyPair::EC_KEY_NAME

  end
end
key_type(key) click to toggle source

end generate

# File lib/pkernel_jce/keypair.rb, line 122
def KeyPair.key_type(key)

  case key
  when java.security.KeyPair, org.bouncycastle.crypto.AsymmetricCipherKeyPair
    privKey = key.getPrivate
  else
    # given is private key
    if KeyPair.is_private_key?(key)
      privKey = key
    else
      raise PkernelJce::Error, "key_type API only check for keypair and private key. For public key type shall  call pub_key_type() API. Given key is #{key}"
    end
  end
 
  case privKey
  when java.security.interfaces.RSAPrivateCrtKey, Java::OrgBouncycastleCryptoParams::RSAPrivateCrtKeyParameters
    Pkernel::KeyPair::RSA_KEY_NAME
  when Java::sun.security.provider.DSAPrivateKey, org.bouncycastle.jcajce.provider.asymmetric.dsa.BCDSAPrivateKey, Java::OrgBouncycastleCryptoParams::DSAPrivateKeyParameters
    Pkernel::KeyPair::DSA_KEY_NAME
  when org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey, Java::OrgBouncycastleCryptoParams::ECPrivateKeyParameters, Java::SunSecurityEc::ECPrivateKeyImpl
    Pkernel::KeyPair::EC_KEY_NAME
  when org.bouncycastle.crypto.params.DHPrivateKeyParameters
    Pkernel::KeyPair::DH_KEY_NAME
  else
    raise PkernelJce::Error, "Unknown priv key type '#{privKey.class}'"
  end
end
private_key(kp) click to toggle source

harmonize the private key acquiring There are BC and Java, keypair and private key

# File lib/pkernel_jce/keypair.rb, line 305
def KeyPair.private_key(kp)
  if kp.nil?
    raise PkernelJce::Error, "Cannot derive private key from nil private key"
  else
    case kp
    when java.security.KeyPair
      kp.private
    when java.security.PrivateKey
      kp
    else
      raise PkernelJce::Error, "Unsupported key type '#{kp}' to derive private key from."
    end
  end
end
pub_key_type(key) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 166
def KeyPair.pub_key_type(key)
  if key.java_kind_of?(java.security.KeyPair)
    pubKey = key.public
  elsif PkernelJce::Certificate.is_cert_object?(key)
    pubKey = PkernelJce::Certificate.public_key(key)
  else
    pubKey = key
  end

  case pubKey
  when java.security.interfaces.RSAPublicKey
    Pkernel::KeyPair::RSA_KEY_NAME
  when Java::sun.security.provider.DSAPublicKey, Java::OrgBouncycastleJcajceProviderAsymmetricDsa::BCDSAPublicKey
    Pkernel::KeyPair::DSA_KEY_NAME
  when Java::OrgBouncycastleJcajceProviderAsymmetricEc::BCECPublicKey, Java::SunSecurityEc::ECPublicKeyImpl
    Pkernel::KeyPair::EC_KEY_NAME  
  when org.bouncycastle.crypto.params.DHPublicKeyParameters
    Pkernel::KeyPair::DH_KEY_NAME  
  else
    raise PkernelJce::Error, "Unknown pub key type '#{pubKey.class}'"
  end
end
public_key(priv, opts = { }) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 219
def KeyPair.public_key(priv, opts = { })
  if priv.nil?
    raise PkernelJce::Error, "Cannot derive public key from nil key"
  else
    if priv.java_kind_of?(java.security.KeyPair)
      priv.getPublic
    elsif priv.java_kind_of?(java.security.PrivateKey)
      type = key_type(priv)
      case type
      when Pkernel::KeyPair::RSA_KEY_NAME
        java.security.KeyFactory.getInstance("RSA").generatePublic(java.security.spec.RSAPublicKeySpec.new(priv.modulus, priv.public_exponent))
      when Pkernel::KeyPair::DSA_KEY_NAME
        y = priv.params.g.to_java.modPow(priv.x, priv.params.p)
        spec = java.security.spec.DSAPublicKeySpec.new(y, priv.params.p, priv.params.q, priv.params.g)
        prov = PkernelJce::Provider.add_default
        java.security.KeyFactory.getInstance("DSA",prov).generatePublic(spec)
      when Pkernel::KeyPair::EC_KEY_NAME
        case priv
          # No way to recover public key using SUN provider yet
        #when Java::SunSecurityEc::ECPrivateKeyImpl
          # this uses BC also so add provider first
          #pProv = PkernelJce::Provider.add_default
          #curveName = priv.params.name.split(" ")[0]

          #ecSpec = org.bouncycastle.jcajce.provider.asymmetric.util.EC5Util.convertSpec(priv.params,false)
          #q = ecSpec.g.to_java.multiply(priv.s)
          #bcW = ecSpec.curve.decodePoint(q.getEncoded(false))
          ##w = org.bouncycastle.math.ec.ECPoint.new(bcW.getAffineXCoord.toBigInteger, bcW.getAffineYCoord.toBigInteger)
          #w = java.security.spec.ECPoint.new(bcW.getAffineXCoord.toBigInteger, bcW.getAffineYCoord.toBigInteger)
          #curveParam = org.bouncycastle.jce.ECNamedCurveTable.getParameterSpec(curveName)
          ##keySpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(w,curveParam)
          #keySpec = java.security.spec.ECPublicKeySpec.new(w,curveParam)

          ##java.security.KeyFactory.getInstance("EC",pProv).generatePublic(keySpec)

        when Java::OrgBouncycastleCryptoParams::ECPrivateKeyParameters, org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
          d = priv.d
          q = priv.parameters.g.to_java.multiply(d)
          pubSpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(q, priv.parameters)
          prov = PkernelJce::Provider.add_default
          java.security.KeyFactory.getInstance("EC",prov).generatePublic(pubSpec)
        else
          raise PkernelJce::Error, "Haven't figure out how to convert #{priv.class} into public key yet..."
        end
        #p priv
        #p priv.methods.sort
        #d = priv.d;
        #q = priv.parameters.g.to_java.multiply(d);
        #pubSpec = org.bouncycastle.jce.spec.ECPublicKeySpec.new(q, priv.parameters);
        #prov = PkernelJce::Provider.add_default
        #java.security.KeyFactory.getInstance("EC",prov).generatePublic(pubSpec)
      else
      end
    elsif priv.java_kind_of?(java.security.PublicKey)
      priv
    elsif priv.java_kind_of?(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo)
      org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new.getPublicKey(priv)
    elsif priv.java_kind_of?(org.bouncycastle.cert.X509CertificateHolder)
      org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new.getPublicKey(priv.subject_public_key_info)
    elsif priv.java_kind_of?(java.security.cert.Certificate)
      priv.public_key 
    else
      raise PkernelJce::Error, "Unsupported key type '#{priv.class}' to convert to public key"
    end
  end
end

Public Instance Methods

dump(keypair, options = {} ,&block) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 391
def dump(keypair, options = {} ,&block)
  if keypair.nil?
    raise PkernelJce::Error, "Keypair is nil during writing PEM"
  end
  
  # outputStream only make sense in Java world
  #os = options[:outputStream]
  file = options[:file]
  pass = options[:password]
  
  #binOut = java.io.ByteArrayOutputStream.new
  
  if (pass.nil? or pass.empty?) and block
    pass = block.call(:prompt_pass)
  end

  ## BC API
  #if file.nil?
  #  PkernelJce::GConf.instance.glog.debug "Dump output to memory"
  #  # return binary to caller
  #  writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(binOut));
  #else
  #  PkernelJce::GConf.instance.glog.debug "Dump output to file '#{file}'"
  #  out = java.io.FileOutputStream.new(file)
  #  writer = org.bouncycastle.openssl.jcajce.JcaPEMWriter.new(java.io.OutputStreamWriter.new(out));
  #end

  #begin
  #  if pass.nil? or pass.empty?
  #    writer.writeObject(keypair.getPrivate)
  #  else
  #    builder = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8EncryptorBuilder.new(org.bouncycastle.openssl.PKCS8Generator::AES_256_CBC).setProvider(PkernelJce::Provider::DefProvider).setPasssword(pass.to_java.toCharArray());

  #    pkcs8 = org.bouncycastle.openssl.jcajce.JcaPKCS8Generator.new(keypair.getPrivate, builder.build);
  #    writer.writeObject(pkcs8)
  #  end
  #ensure
  #  writer.flush
  #  writer.close
  #end

  # Java API
  prov = options[:provider]
  if not prov.nil?
    prov = PkernelJce::Provider.add_provider(prov)
  end

  if pass.nil? or pass.empty?
    PkernelJce::GConf.instance.glog.warn "Dumping of private key without password!"
    encInfo = java.security.spec.PKCS8EncodedKeySpec.new(PkernelJce::KeyPair.private_key(keypair).encoded)
  else
    pbeAlgo = options[:pbeAlgo]
    # todo test this algo with openssl and see...
    pbeAlgo = "PBEWithSHA1AndRC4_128" if pbeAlgo.nil? or pbeAlgo.empty?

    salt = Java::byte[32].new
    Java::JavaSecurity::SecureRandom.new.nextBytes(salt)
    pbeParamSpec = Java::JavaxCryptoSpec::PBEParameterSpec.new(salt,88)
    pbeKeySpec = Java::JavaxCryptoSpec::PBEKeySpec.new(pass.to_java.toCharArray)
    if not prov.nil?

      secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(pbeAlgo,prov)
      pbeKey = secKeyFact.generateSecret(pbeKeySpec)
      cipher = Java::JavaxCrypto::Cipher.getInstance(pbeAlgo,prov)
      cipher.init(Java::JavaxCrypto::Cipher::ENCRYPT_MODE,pbeKey,pbeParamSpec)
      output = cipher.doFinal(PkernelJce::KeyPair.private_key(keypair).getEncoded())
      algoParam = Java::JavaSecurity::AlgorithmParameters.getInstance(pbeAlgo,prov)

    else
      secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(pbeAlgo)
      pbeKey = secKeyFact.generateSecret(pbeKeySpec)
      cipher = Java::JavaxCrypto::Cipher.getInstance(pbeAlgo)
      cipher.init(Java::JavaxCrypto::Cipher::ENCRYPT_MODE,pbeKey,pbeParamSpec)
      output = cipher.doFinal(PkernelJce::KeyPair.private_key(keypair).getEncoded())
      algoParam = Java::JavaSecurity::AlgorithmParameters.getInstance(pbeAlgo)
    end

    algoParam.init(pbeParamSpec)
    encPrivInfo = Java::JavaxCrypto::EncryptedPrivateKeyInfo.new(algoParam,output)
    encInfo = encPrivInfo
  end

  cont = []
  keyType = KeyPair.key_type(keypair)
  case keyType
  when Pkernel::KeyPair::RSA_KEY_NAME
    cont << "-----BEGIN RSA PRIVATE KEY-----" 
    cont << PkernelJce::Converter.to_mb64(encInfo.getEncoded)
    cont << "-----END RSA PRIVATE KEY-----" 
  when Pkernel::KeyPair::DSA_KEY_NAME
    cont << "-----BEGIN DSA PRIVATE KEY-----" 
    cont << PkernelJce::Converter.to_mb64(encInfo.getEncoded)
    cont << "-----END DSA PRIVATE KEY-----" 
  when Pkernel::KeyPair::EC_KEY_NAME
    cont << "-----BEGIN EC PRIVATE KEY-----" 
    cont << PkernelJce::Converter.to_mb64(encInfo.getEncoded)
    cont << "-----END EC PRIVATE KEY-----" 
  else
    raise PkernelJce::Error, "Unsupported key type #{keyType}"
  end

  pkcs8Envelope = cont.join("\n")

  #pkcs8Envelope = encPrivInfo.getEncoded()

  if not file.nil?
    fos = java.io.FileOutputStream.new(file)
    fos.write(pkcs8Envelope.to_java.getBytes)
    fos.flush
    fos.close
  end

  pkcs8Envelope

end
generate(algo, conf = {}) click to toggle source
# File lib/pkernel_jce/keypair.rb, line 12
def generate(algo, conf = {})
 
  log = conf[:log]
  if log.nil?
    log = GConf.instance.glog
  end 
  
  prov = conf[:provider]
  #log.debug "Provider is #{prov == nil ? 'nil' : prov.name}"
  
  case algo.to_s.upcase
  when "RSA"
    len = conf[:len] || 2048
    log.debug "Generating RSA #{len} bits with provider #{prov == nil ? 'default' : prov.name}"
    if prov.nil?
      kpg = java.security.KeyPairGenerator.getInstance("RSA")
    else
      PkernelJce::Provider.add_provider(prov)
      kpg = java.security.KeyPairGenerator.getInstance("RSA", prov)
    end
    
    kpg.java_send :initialize, [Java::int], len
    kpg.generate_key_pair

  when "DSA"
    len = conf[:len] || 2048
    log.debug "Generating DSA #{len} bits with provider #{prov == nil ? 'default' : prov.name}"
    if prov.nil?
      kpg = java.security.KeyPairGenerator.getInstance("DSA")
    else
      PkernelJce::Provider.add_provider(prov)
      kpg = java.security.KeyPairGenerator.getInstance("DSA", prov)
    end
    kpg.java_send :initialize, [Java::int], len
    kpg.generate_key_pair
  when "ECC","EC"
    # this only supported by bc?
    curve = conf[:curve] || "prime256v1"
    curve.strip!
    # Fp
    # X9.62 : prime192v1, prime192v2, prime192v3, prime239v1, prime239v2, prime239v3, prime256v1
    # SEC : secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, secp256r1, secp384r1, secp521r1
    # NIST: P-224, P-256, P-384, P-521
    # F 2m
    # X9.62 : c2pnb163v1, c2pnb163v2, c2pnb163v3, c2pnb176w1, c2tnb191v1, c2tnb191v2, c2tnb191v3, c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, c2pnb272w1, c2pnb304w1, c2tnb359v1, c2pnb368w1, c2tnb431r1
    # SEC: sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1
    # NIST : B-163, B-233, B-283, B-409, B-571
    # Teletrust : brainpoolp160r1, brainpoolp160t1, brainpoolp192r1, brainpoolp192t1, brainpoolp224r1, brainpoolp224t1, brainpoolp256r1, brainpoolp256t1, brainpoolp320r1, brainpoolp320t1, brainpoolp384r1, brainpoolp384t1, brainpoolp512r1, brainpoolp512t1
    # GostR3410-2001-CryptoPro-A, GostR3410-2001-CryptoPro-XchB, GostR3410-2001-CryptoPro-XchA, GostR3410-2001-CryptoPro-C, GostR3410-2001-CryptoPro-B
    if prov.nil?
      #kpg = java.security.KeyPairGenerator.getInstance("ECDSA")
      # default Java does not have ECDSA yet as of Java 8
      prov = PkernelJce::Provider.add_default
    end
    log.debug "Generating ECC curve '#{curve}' with provider #{prov == nil ? 'default' : prov.name}"
    
    PkernelJce::Provider.add_provider(prov)
    kpg = java.security.KeyPairGenerator.getInstance("ECDSA", prov)
    kpg.java_send :initialize, [java.security.spec.AlgorithmParameterSpec, java.security.SecureRandom], java.security.spec.ECGenParameterSpec.new(curve), java.security.SecureRandom.new
    kpg.generate_key_pair

  when "DH"

    len = conf[:len] || 1024
    certainty = conf[:certainty] || org.bouncycastle.jcajce.provider.asymmetric.util.PrimeCertaintyCalculator.getDefaultCertainty(len)
    # for DH key, these two values can be shared...
    # https://news.ycombinator.com/item?id=10397326
    # this two values shall be in hex
    p = conf[:p]
    g = conf[:g]

    if not p.nil?
      p = java.math.BigInteger.new(p,16)
    end

    if not g.nil?
      g = java.math.BigInteger.new(g,16)
    end

    prov = PkernelJce::Provider::DefProvider

    if not (p.nil? and g.nil?)
      log.debug "Generating DH key from given p and g"
      gparam = org.bouncycastle.crypto.params.DHParameters.new(p,g)

    else
    
      log.debug "Generating DH #{len} bits with provider #{prov.name}, certainty : #{certainty}."
      if len > 1024
        log.warn "Generating #{len} bits of DH key may take some time... so be patient..."
      end

      dhParamGen = org.bouncycastle.crypto.generators.DHParametersGenerator.new
      dhParamGen.init(len,certainty, java.security.SecureRandom.new)
      gparam = dhParamGen.generate_parameters
    end

    kgParam = org.bouncycastle.crypto.params.DHKeyGenerationParameters.new(java.security.SecureRandom.new, gparam)
    kpg = org.bouncycastle.crypto.generators.DHKeyPairGenerator.new
    kpg.init(kgParam)
    kpg.generateKeyPair
     
  else
    log.error "Unknown '#{algo}' for java keypair"
    raise PkernelJce::Error, "Unknown algo '#{algo}' for java keypair"
  end
end
load(opts = {}, &block) click to toggle source

end dump

# File lib/pkernel_jce/keypair.rb, line 508
def load(opts = {}, &block)
  
  file = opts[:file]
  bin = opts[:bin]

  baos = java.io.ByteArrayOutputStream.new
  
  if not file.nil? and not file.empty?
    PkernelJce::GConf.instance.glog.debug "Load keypair from file '#{file}'"
    f = java.io.File.new(file)
    if f.exists?
      b = Java::byte[f.length].new
      dis = java.io.DataInputStream.new(java.io.FileInputStream.new(f))
      dis.readFully(b)
      dis.close
      
      baos.write(b)
    else
      raise PkernelJce::Error, "Given file to load '#{f.absolute_path}' does not exist"
    end
  elsif not bin.nil?
    PkernelJce::GConf.instance.glog.debug "Load keypair from memory"
    baos.write(bin)
  else
    raise PkernelJce::Error, "No 'file' or 'bin' is defined to load keypair"
  end

  prov = opts[:provider]
  if not prov.nil?
    prov = PkernelJce::Provider.add_provider(prov)
  end

  pass = opts[:password]
  if (pass.nil? or pass.empty?) and block
    pass = block.call(:prompt_pass) 
  end

  cont = String.from_java_bytes(baos.toByteArray)
  cont.gsub!("-----BEGIN RSA PRIVATE KEY-----","")
  cont.gsub!("-----END RSA PRIVATE KEY-----","")
  cont.gsub!("-----BEGIN DSA PRIVATE KEY-----","")
  cont.gsub!("-----END DSA PRIVATE KEY-----","")
  cont.gsub!("-----BEGIN EC PRIVATE KEY-----","")
  cont.gsub!("-----END EC PRIVATE KEY-----","")
  econt = PkernelJce::Converter.from_mb64(cont)
  #fos = java.io.FileOutputStream.new("test.bin")
  #fos.write(econt)
  #fos.flush
  #fos.close

  # Java API
  if not (pass.nil? or pass.empty?)

    PkernelJce::GConf.instance.glog.debug "Password protected envelope"
    encPrivInfo = Java::JavaxCrypto::EncryptedPrivateKeyInfo.new(econt)
    cipher = Java::JavaxCrypto::Cipher::getInstance(encPrivInfo.getAlgName())
    pbeKeySpec = Java::JavaxCryptoSpec::PBEKeySpec.new(pass.to_java.toCharArray)
    if(prov != nil)
      secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(encPrivInfo.getAlgName(),prov)
    else
      secKeyFact = Java::JavaxCrypto::SecretKeyFactory.getInstance(encPrivInfo.getAlgName())
    end
    pbeKey = secKeyFact.generateSecret(pbeKeySpec)

    cipher.init(Java::JavaxCrypto::Cipher::DECRYPT_MODE, pbeKey,encPrivInfo.getAlgParameters())

    pkcs8KeySpec = encPrivInfo.getKeySpec(cipher)
    #privKeyParam = Java::OrgBouncycastleCryptoUtil::PrivateKeyFactory::createKey(pkcs8KeySpec)
  else
    pkcs8KeySpec = java.security.spec.PKCS8EncodedKeySpec.new(econt)
  end

                    key = org.bouncycastle.crypto.util.PrivateKeyFactory::createKey(java.io.ByteArrayInputStream.new(pkcs8KeySpec.getEncoded))
  keyType = KeyPair.key_type(key)
  case keyType
  when Pkernel::KeyPair::RSA_KEY_NAME
    
    if prov.nil?
      keyFact = Java::JavaSecurity::KeyFactory.getInstance("RSA")
    else
      keyFact = Java::JavaSecurity::KeyFactory.getInstance("RSA",prov)
    end
                            #privKey = keyFact.generatePrivate(pkcs8KeySpec)
                            ## here is how to convert into RSAPublicKey, become keypair!
                            #pubKeySpec = Java::JavaSecuritySpec::RSAPublicKeySpec.new(privKey.getModulus(),privKey.getPublicExponent())
                            #pubKey = keyFact.generatePublic(pubKeySpec)

                            #Java::JavaSecurity::KeyPair.new(pubKey,privKey)

  when Pkernel::KeyPair::DSA_KEY_NAME

    if prov.nil?
      keyFact = Java::JavaSecurity::KeyFactory.getInstance("DSA")
    else
      keyFact = Java::JavaSecurity::KeyFactory.getInstance("DSA",prov)
    end
    
  when Pkernel::KeyPair::EC_KEY_NAME

    if prov.nil?
      keyFact = Java::JavaSecurity::KeyFactory.getInstance("EC")
    else
      keyFact = Java::JavaSecurity::KeyFactory.getInstance("EC",prov)
    end

  else
    
    raise PkernelJce::Error, "Unknown key type #{keyType}"
 
  end

  privKey = keyFact.generatePrivate(pkcs8KeySpec)
  ## here is how to convert into RSAPublicKey, become keypair!
  #pubKeySpec = Java::JavaSecuritySpec::RSAPublicKeySpec.new(privKey.getModulus(),privKey.getPublicExponent())
  #pubKey = keyFact.generatePublic(pubKeySpec)

  #pubKey = PkernelJce::KeyPair.public_key(privKey)
  #Java::JavaSecurity::KeyPair.new(pubKey,privKey)

  privKey


                    #if key.java_kind_of? org.bouncycastle.crypto.params.RSAPrivateCrtKeyParameters
                    #    keyFact = Java::JavaSecurity::KeyFactory.getInstance("RSA")
                    #    privKey = keyFact.generatePrivate(pkcs8KeySpec)
                    #    # here is how to convert into RSAPublicKey, become keypair!
                    #    pubKeySpec = Java::JavaSecuritySpec::RSAPublicKeySpec.new(privKey.getModulus(),privKey.getPublicExponent())
                    #    pubKey = keyFact.generatePublic(pubKeySpec)

                    #    Java::JavaSecurity::KeyPair.new(pubKey,privKey)
                    #else
                    #    raise PkernelJce::Error, "Unsupported PKCS8 store of type #{key}"
                    #end
 
  # BC API
  #reader = org.bouncycastle.openssl.PEMParser.new(java.io.InputStreamReader.new(java.io.ByteArrayInputStream.new(baos.toByteArray)))
  #obj = reader.readObject
  ##p obj.inspect
  ##p obj.methods.sort
  ##p obj.java_kind_of?(org.bouncycastle.openssl.PEMEncryptedKeyPair)
  #if obj.is_a?(org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo)
  #  pass = opts[:password]
  #  if pass.nil?
  #    if block
  #      pass = block.call(:password)
  #    else
  #      raise PkernelJce::Error, "PEM key is encrypted. Please provide a password to load the key."
  #    end
  #  end
  #  decProv = org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder.new.setProvider(PkernelJce::Provider::DefProvider).build(pass.to_java.toCharArray)
  #  keyinfo = obj.decryptPrivateKeyInfo(decProv)

  #  converter = org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter.new
  #  converter.getPrivateKey(keyinfo)
  #else
  #  keySpec = java.security.spec.PKCS8EncodedKeySpec.new(obj.getPrivateKeyInfo.encoded)
  #  # Now it's in a PKCS#8 PrivateKeyInfo structure. Read its Algorithm
  #  # OID and use that to construct a KeyFactory.
  #  bIn = org.bouncycastle.asn1.ASN1InputStream.new(java.io.ByteArrayInputStream.new(keySpec.getEncoded()));
  #  pki = org.bouncycastle.asn1.pkcs.PrivateKeyInfo.getInstance(bIn.readObject());
  #  algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
  #  java.security.KeyFactory.getInstance(algOid,prov).generatePrivate(keySpec);
  #
  #  #privKey = java.security.KeyFactory.getInstance("RSA").generatePrivate(keySpec)
  #  #privKey
  #end
    
end