Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve my public and private key from the keystore we created

My task is the following:

  • Retrieve my public and private key from the keystore I created.
  • Use these keys to encrypt a paragraph using my RSA 2048-bit public key.
  • Digitally sign the result using the DSA-SHA-1 signature algorithm.
  • Save the digital signature output on a file called output.dat.

The program below is throwing error : "java.security.InvalidKeyException: No installed provider supports this key: sun.security.provider.DSAPublicKeyImpl".

import java.security.*;
import java.security.KeyStore.*;
import java.io.*;
import java.security.PublicKey;
import java.security.PrivateKey;
import javax.crypto.Cipher;
import java.nio.charset.*;
import sun.security.provider.*;
import  javax.crypto.*;

public class Code {

/**
 * @param args the command line arguments
 */
    public static void main(String[] args) {

        try {

            /* getting data for keystore */

            File file = new File(System.getProperty("user.home") + File.separatorChar + ".keystore");
            FileInputStream is = new FileInputStream(file);
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());

            /*Information for certificate to be generated */ 
            String password = "abcde";
            String alias = "mykeys";
            String alias1 = "skeys";

            String filepath ="C:\\email.txt";

            /* getting the key*/
            keystore.load(is, password.toCharArray());
            PrivateKey key = (PrivateKey)keystore.getKey(alias, "bemylife".toCharArray());
            //PrivateKey key = cert1.getPrivateKey();
            //PublicKey key1= (PrivateKey)key;

            /* Get certificate of public key */
            java.security.cert.Certificate cert = keystore.getCertificate(alias); 

            /* Here it prints the public key*/
            System.out.println("Public Key:");
            System.out.println(cert.getPublicKey());

            /* Here it prints the private key*/
            System.out.println("\nPrivate Key:");
            System.out.println(key);

            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE,cert.getPublicKey());

            String cleartextFile = "C:\\email.txt";
            String ciphertextFile = "D:\\ciphertextRSA.png";

            FileInputStream fis = new FileInputStream(cleartextFile);
            FileOutputStream fos = new FileOutputStream(ciphertextFile);
            CipherOutputStream cos = new CipherOutputStream(fos, cipher);

            byte[] block = new byte[32];
            int i;
            while ((i = fis.read(block)) != -1) {
                cos.write(block, 0, i);
            }
            cos.close();


            /* computing the signature*/
            Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");
            dsa.initSign(key);
            FileInputStream f = new FileInputStream(ciphertextFile);
            BufferedInputStream in = new BufferedInputStream(f);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer)) >= 0) {
               dsa.update(buffer, 0, len);
           };
           in.close();

           /* Here it prints the signature*/
           System.out.println("Digital Signature :");
           System.out.println( dsa.sign());

           /* Now Exporting Certificate */
           System.out.println("Exporting Certificate. ");
           byte[] buffer_out = cert.getEncoded();
           FileOutputStream os = new FileOutputStream(new File("d:\\signedcetificate.cer"));
           os.write(buffer_out);
           os.close();

           /* writing signature to output.dat file */
           byte[] buffer_out1 = dsa.sign();
           FileOutputStream os1 = new FileOutputStream(new File("d:\\output.dat"));
           os1.write(buffer_out1);
           os1.close();

       } catch (Exception e) {System.out.println(e);}

   }
}
like image 379
Zack Ef Avatar asked Nov 06 '13 09:11

Zack Ef


3 Answers

You have to read it from the keystore file (which probably ends in .jks) into a java.security.KeyStore object.

/**
 * Reads a Java keystore from a file.
 * 
 * @param keystoreFile
 *          keystore file to read
 * @param password
 *          password for the keystore file
 * @param keyStoreType
 *          type of keystore, e.g., JKS or PKCS12
 * @return the keystore object
 * @throws KeyStoreException
 *           if the type of KeyStore could not be created
 * @throws IOException
 *           if the keystore could not be loaded
 * @throws NoSuchAlgorithmException
 *           if the algorithm used to check the integrity of the keystore
 *           cannot be found
 * @throws CertificateException
 *           if any of the certificates in the keystore could not be loaded
 */
public static KeyStore loadKeyStore(final File keystoreFile,
    final String password, final String keyStoreType)
    throws KeyStoreException, IOException, NoSuchAlgorithmException,
    CertificateException {
  if (null == keystoreFile) {
    throw new IllegalArgumentException("Keystore url may not be null");
  }
  LOG.debug("Initializing key store: {}", keystoreFile.getAbsolutePath());
  final URI keystoreUri = keystoreFile.toURI();
  final URL keystoreUrl = keystoreUri.toURL();
  final KeyStore keystore = KeyStore.getInstance(keyStoreType);
  InputStream is = null;
  try {
    is = keystoreUrl.openStream();
    keystore.load(is, null == password ? null : password.toCharArray());
    LOG.debug("Loaded key store");
  } finally {
    if (null != is) {
      is.close();
    }
  }
  return keystore;
}

Once you have the KeyStore, you can get to the Certificate and the public and private keys.

But using that to sign text and save it in a file is more involved, and easy to do wrong. Take a look at Sign string using given Public Key and replace the getKeyPair method with one that uses the KeyStore. Something along the lines of

public static KeyPair getKeyPair(final KeyStore keystore, 
    final String alias, final String password) {
  final Key key = (PrivateKey) keystore.getKey(alias, password.toCharArray());

  final Certificate cert = keystore.getCertificate(alias);
  final PublicKey publicKey = cert.getPublicKey();

  return KeyPair(publicKey, (PrivateKey) key);
}

(obviously a little rougher, I didn't have a sample handy)

like image 174
Gene Gotimer Avatar answered Oct 20 '22 23:10

Gene Gotimer


The problem is that a DSA key is unsuitable for RSA encryption. You need an RSA key for encryption, maybe you can switch your signature algorithm to RSA/SHA1 to avoid the need for two keys..

like image 3
Drunix Avatar answered Oct 20 '22 22:10

Drunix


trusted.load(in, ((PBCApplication) context.getApplicationContext()).getBuildSettings().getCertificatePass());
Enumeration enumeration = trusted.aliases();

while (enumeration.hasMoreElements()) {
    String alias = (String) enumeration.nextElement();
    System.out.println("alias name: " + alias);
    Certificate certificate = trusted.getCertificate(alias);
    certificate.getPublicKey();
}
like image 1
chavanNil Avatar answered Oct 20 '22 22:10

chavanNil