2016-11-18 4 views
0

Я использовал метод generateKeyPair() для генерации 2 разных KeyPair с использованием алгоритма ECDSA.ECDSA частные и открытые ключи - как получить SecretKey?

public KeyPair generateKeyPair(){   

    ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp192r1"); 
    KeyPairGenerator g = KeyPairGenerator.getInstance("ECDSA", "BC"); 
    g.initialize(spec, new SecureRandom()); 

    return g.generateKeyPair(); 
} 

Тогда я использовал PrivateKey и PublicKey из отдельных KeyPair, чтобы получить комбинированный SecretKey:

private SecretKey generateSecretKey(PrivateKey privateKey, PublicKey publicKey) { 

    KeyAgreement ka = KeyAgreement.getInstance("ECDH"); 
    ka.init(privateKey); 
    ka.doPhase(publicKey), 
      true); 

    return ka.generateSecret("AES"); 
} 

Но я получаю в ka.generateSecret("AES"):

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException 
    at java.lang.System.arraycopy(Native Method) 
    at org.bouncycastle.jcajce.provider.asymmetric.util.BaseAgreementSpi.engineGenerateSecret(Unknown Source) 
    at javax.crypto.KeyAgreement.generateSecret(KeyAgreement.java:648) 

Если я использую ECDSA, я получаю:

Exception in thread "main" java.security.NoSuchAlgorithmException: Algorithm ECDSA not available 
    at javax.crypto.KeyAgreement.getInstance(KeyAgreement.java:184) 

Использование DH бросает:

Exception in thread "main" java.security.InvalidKeyException: DHKeyAgreement requires DHPrivateKey 
    at org.bouncycastle.jcajce.provider.asymmetric.dh.KeyAgreementSpi.engineInit(Unknown Source) 
    at javax.crypto.KeyAgreement.implInit(KeyAgreement.java:346) 
    at javax.crypto.KeyAgreement.chooseProvider(KeyAgreement.java:378) 
    at javax.crypto.KeyAgreement.init(KeyAgreement.java:470) 

Как получить комбинированный SecretKey от PrivateKey и PublicKey, которые генерируются с использованием алгоритма ECDSA?

+0

Какой версии BouncyCastle вы используете? Также не используйте OpenJDK, поскольку он пропускает поддержку ECDSA в некоторых дистрибутивах Linux. – Robert

+0

bcpkix-jdk15on 1.54. Он отлично подходит для подписывания и проверки в Windows и Linux. – Justas

+0

Я не знаю BouncyCastle, но, глядя на ваш код, я замечаю пару вещей, которые могут вызвать проблему. Сначала похоже, что вы генерируете ключи ECDSA, но пытаетесь использовать их в соглашении с ключом DH - возможно, ключ - неправильный формат? Во-вторых, вам нужно предоставить детали кривой для объекта KeyAgreement? Я вижу, что он предоставляет [перегруженный метод 'init', который принимает' AlgorithmParameterSpec'] (https://docs.oracle.com/javase/8/docs/api/javax/crypto/KeyAgreement.html#init-java.security .KEY-java.security.spec.AlgorithmParameterSpec-). – matt

ответ

1

Он работает правильно и кривой возвращается размер общего секрета после удаления «AES» аргумента от return ka.generateSecret();:

private SecretKey generateSecretKey(PrivateKey privateKey, PublicKey publicKey) { 

    KeyAgreement ka = KeyAgreement.getInstance("ECDH"); 
    ka.init(privateKey); 
    ka.doPhase(publicKey, true); 

    return ka.generateSecret(); 
} 
+0

Это работает для меня. Как преобразовать секретный ключ в String? –

+1

Преобразование байтов в Hex или Base64. – Justas

0

Протокол с основным соглашением обычно работает между двумя сторонами, каждый из которых имеет собственный открытый и закрытый ключ ECDS (следовательно, у нас есть четыре разных ключа). Вы уверены, что это то, что вы хотите?

Поэтому, когда вы согласны с ключом вам нужно секретный ключ стороны А и открытый ключ стороны В. А на другом конце соединения вы используете закрытый ключ участника B и открытый ключ участника A.

Выбранный алгоритм согласования ключа ECDH описан в RFC3278 - для более подробного ознакомления с ним.

+0

Я знаю, я использую закрытый ключ и открытые ключи от отдельных пар ключей. Проблема в том, что я получаю исключение при создании SecretKey. – Justas

Смежные вопросы