Формат файла для открытых / закрытых ключей EC? - PullRequest
4 голосов
/ 04 марта 2011

Если бы я хотел хранить как закрытый, так и открытый ключ в одном файле, какой формат был бы наиболее простым для использования? Особенно, если я планирую использовать библиотеку BouncyCastle для Java?

Ответы [ 2 ]

3 голосов
/ 04 марта 2011

С теоретической точки зрения открытый ключ может быть пересчитан из закрытого ключа (вычислительные затраты для этого немного ниже, чем стоимость создания одной сигнатуры ECDSA или создания половины ECDH, поэтому это происходит быстро).Следовательно, концептуально вам нужно хранить только закрытый ключ, и стандартный формат для него - PKCS # 8 , который поддерживается Java с java.security.spec.PKCS8EncodedKeySpec.Более того, формат PKCS # 8 включает в себя положения для необязательного кодирования открытого ключа вдоль закрытого ключа в том же самом двоичном объекте, так что это действительно похоже на то, что вы ищете.

Однако сложно убедитьпоставщик криптографии (например, BouncyCastle) для извлечения открытого ключа как такового и / или его повторного вычисления.Очевидно, что если вы создадите PKCS8EncodedKeySpec из закрытого ключа EC с кодировкой PKCS # 8, который также содержит открытый ключ, BouncyCastle будет достаточно любезен, чтобы внутренне сохранить копию закодированного открытого ключа и записать ее обратно, если вы решите перекодироватьзакрытый ключ в формате PKCS # 8.Тем не менее, он ничего не делает с этим;он обрабатывает его как непрозрачный BLOB-объект.

Следовательно, вы должны пересчитать открытый ключ.Проходя через JCE и BouncyCastle API и нереализованные биты, я нашел следующее, которое работает (JDK 1.6.0_24, BouncyCastle 1.46):

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Provider;
import java.security.spec.PKCS8EncodedKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jce.provider.JCEECPrivateKey;
import org.bouncycastle.jce.provider.JCEECPublicKey;
import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec;

// Create the provider and an appropriate key factory.
Provider pp = new BouncyCastleProvider();
KeyFactory kf = KeyFactory.getInstance("EC", pp);

// Decode the private key (read as a byte[] called 'buf').
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(buf);
PrivateKey sk = kf.generatePrivate(ks);

// Recompute public key.
JCEECPrivateKey priv = (JCEECPrivateKey)sk;
ECParameterSpec params = priv.getParameters();
ECPublicKeySpec pubKS = new ECPublicKeySpec(
    params.getG().multiply(priv.getD()), params);
PublicKey pk = kf.generatePublic(pubKS);

// To reencode the private key.
buf = kf.getKeySpec(sk, PKCS8EncodedKeySpec.class).getEncoded();

Концептуально, я должен использовать kf.getkeySpec() с org.bouncycastle.jce.spec.ECPrivateKeySpec вместо того, чтобы безжалостно приводить закрытый ключ к классу JCEECPrivateKey, но метод clean, похоже, еще не реализован в BouncyCastle.

0 голосов
/ 19 июня 2012

Попробуйте это (BouncyCastle v1.47, используя JDK 1.7. *, Но я предполагаю, что JDK 1.6. * Тоже подойдет):

// Recreate the private key.
final KeyFactory kf = KeyFactory.getInstance("EC", "BC");
final PKCS8EncodedKeySpec encPrivKeySpec = new PKCS8EncodedKeySpec(rawPrivKey);
final PrivateKey privKey = kf.generatePrivate(encPrivKeySpec);
final byte[] rawPrivKey = privKey.getEncoded();

// Recreate the public key.
final X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(rawPubKey);
final PublicKey pubKey = kf.generatePublic(pubKeySpec);
final byte[] rawPubKey = pubKey.getEncoded();

, где rawPrivKey и rawPubKey - массивы байтового типа.
Я предлагаю вам зашифровать зашифрованный закрытый ключ блочным шифром (т.е. AES), иначе файл может быть украден, а затем вы подвергаетесь бессрочному раскрытию.

...