How to use keystore in Java to store private key?

后端 未结 4 641
南笙
南笙 2020-11-28 11:04

I have used KeyPairGenerator to generate a RSA key pair. If I\'m not wrong, the KeyStore is only used to store certificates and not keys. How can I properly sto

相关标签:
4条回答
  • 2020-11-28 11:43

    Depending on the format of your private key you might need to convert it to a format the java keytool can use.

    But if it is in a keytool supported format you should be able yo just import it using keytool. more info at:

    http://docs.oracle.com/javase/tutorial/security/toolfilex/rstep1.html

    http://docs.oracle.com/javase/1.5.0/docs/tooldocs/windows/keytool.html

    0 讨论(0)
  • 2020-11-28 11:51

    NOTE: This code is for demonstration purposes only. Private keys must be encrypted when you store them on disk. Do not use it as is.

    You can do something like this:

     KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
     kpg.initialize(2048);
    
     KeyPair kp = kpg.genKeyPair();
    
     KeyFactory fact = KeyFactory.getInstance("RSA");
    
     RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(),
            RSAPublicKeySpec.class);
     saveToFile(PUBLIC_KEY_FILE, 
            pub.getModulus(), pub.getPublicExponent());
    
     RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(),
            RSAPrivateKeySpec.class);
     saveToFile(PRIVATE_KEY_FILE, 
             priv.getModulus(), priv.getPrivateExponent());
    

    The save function:

    private static void saveToFile(String fileName,
                                   BigInteger mod, BigInteger exp) 
        throws SomeException {
        ObjectOutputStream oout = new ObjectOutputStream(
                new BufferedOutputStream(new FileOutputStream(fileName)));
        try {
            oout.writeObject(mod);
            oout.writeObject(exp);
        } catch (Exception e) {
            throw new SomeException(e);
        } finally {
            oout.close();
        }
    }
    

    And read the same way back:

    private static PublicKey readPublicKey() throws SomeException {
        InputStream in = new FileInputStream(PUBLIC_KEY_FILE);
        ObjectInputStream oin =
                new ObjectInputStream(new BufferedInputStream(in));
        try {
            BigInteger m = (BigInteger) oin.readObject();
            BigInteger e = (BigInteger) oin.readObject();
            RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
            KeyFactory fact = KeyFactory.getInstance("RSA");
            PublicKey pubKey = fact.generatePublic(keySpec);
            return pubKey;
        } catch (Exception e) {
            throw new SomeException(e);
        } finally {
            oin.close();
        }
    }
    

    Reading private key is similar.

    0 讨论(0)
  • 2020-11-28 12:01

    This block of code will generate and store a KeyPair on the AndroidKeyStore. (NOTE: Exception catches omitted)

    KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
    keyStore.load(null);
    
    String alias = "my_key"; // replace as required or get it as a function argument
    
    int nBefore = keyStore.size(); // debugging variable to help convince yourself this works
    
    // Create the keys if necessary
    if (!keyStore.containsAlias(alias)) {
    
        Calendar notBefore = Calendar.getInstance();
        Calendar notAfter = Calendar.getInstance();
        notAfter.add(Calendar.YEAR, 1);
        KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(this)
                        .setAlias(alias)
                        .setKeyType("RSA")
                        .setKeySize(2048)
                        .setSubject(new X500Principal("CN=test"))
                        .setSerialNumber(BigInteger.ONE)
                        .setStartDate(notBefore.getTime())
                        .setEndDate(notAfter.getTime())
                        .build();
        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
        generator.initialize(spec);
    
        KeyPair keyPair = generator.generateKeyPair();
    }
    int nAfter = keyStore.size();
    Log.v(TAG, "Before = " + nBefore + " After = " + nAfter);
    
    // Retrieve the keys
    KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry(alias, null);
    RSAPrivateKey privateKey = (RSAPrivateKey) privateKeyEntry.getPrivateKey();
    RSAPublicKey publicKey = (RSAPublicKey) privateKeyEntry.getCertificate().getPublicKey();
    
    Log.v(TAG, "private key = " + privateKey.toString());
    Log.v(TAG, "public key = " + publicKey.toString());
    
    0 讨论(0)
  • 2020-11-28 12:03

    http://snipplr.com/view/18368/

    OR

    http://docs.oracle.com/javase/1.5.0/docs/api/java/security/KeyStore.html

    OR

    http://java.sun.com/docs/books/tutorial/security/apisign/vstep2.html This is most Promising

    OR

    It's impossible to secure a key in an untrusted environment. You can obfuscate your code, you can create a key from arbitrary variables, whatever. Ultimately, assuming that you use the standard javax.crypto library, you have to call Mac.getInstance(), and sometime later you'll call init() on that instance. Someone who wants your key will get it.

    However, I think the solution is that you tie the key to the environment, not the program. A signature is meant to say that the data originated from a known source, and has not been tampered with since that source provided it. Currently, you're trying to say "guarantee that my program produced the data." Instead, change your requirement to "guarantee that a particular user of my program produced the data." The onus is then shifted to that user to take care of his/her key.

    0 讨论(0)
提交回复
热议问题