Подтвердить что ты не робот

Как использовать хранилище ключей в Java для хранения закрытого ключа?

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

Этот блок кода будет генерировать и хранить 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());

Ответ 3

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

ИЛИ

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

ИЛИ

http://java.sun.com/docs/books/tutorial/security/apisign/vstep2.html Это наиболее перспективный

ИЛИ

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

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

Ответ 4

В зависимости от формата вашего закрытого ключа вам может потребоваться преобразовать его в формат, который может использовать 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