Как использовать хранилище ключей в Java для хранения закрытого ключа? - PullRequest
14 голосов
/ 27 марта 2012

Я использовал KeyPairGenerator для генерации пары ключей RSA. Если я не ошибаюсь, KeyStore используется только для хранения сертификатов, а не ключей. Как правильно хранить закрытый ключ на компьютере?

Ответы [ 4 ]

12 голосов
/ 27 марта 2012

Вы можете сделать что-то вроде этого:

 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());

Функция сохранения:

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();
    }
}

И так же читай обратно:

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();
    }
}

Чтение закрытого ключа аналогично.

7 голосов
/ 10 января 2015

Этот блок кода сгенерирует и сохранит KeyPair в AndroidKeyStore.(ПРИМЕЧАНИЕ: исключения исключаются)

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 голосов
/ 27 марта 2012

В зависимости от формата вашего закрытого ключа вам может потребоваться преобразовать его в формат, который может использовать java keytool.

Но если он поддерживает формат keytool, вы можете импортировать его, используя keytool. больше информации на:

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

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

0 голосов
/ 27 марта 2012

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 Это наиболее перспективно

OR

Невозможно защитить ключ в ненадежной среде. Вы можете запутать свой код, вы можете создать ключ из произвольных переменных, что угодно. В конечном итоге, предполагая, что вы используете стандартную библиотеку javax.crypto, вы должны вызвать Mac.getInstance (), а через некоторое время вы вызовете init () для этого экземпляра. Тот, кто хочет получить ваш ключ, получит его.

Однако я думаю, что решение заключается в том, что вы привязываете ключ к среде, а не к программе. Подпись означает, что данные получены из известного источника и не были подделаны с тех пор, как этот источник предоставил их. В настоящее время вы пытаетесь сказать «гарантировать, что моя программа произвела данные». Вместо этого измените ваше требование, чтобы «гарантировать, что данные были получены конкретным пользователем моей программы». Затем бремя перекладывается на этого пользователя, чтобы позаботиться о его ключе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...