Использование закодированного PEM-шифрованного закрытого ключа для подписи сообщения изначально

Я пытаюсь использовать сертификат PEM (X.509) (хранящийся в файле privateKey.pem на диске), чтобы подписывать сообщения, отправленные через сокеты на Java, но мне очень трудно найти пример, который близок. Обычно я парень из C ++, который просто вступает, чтобы помочь в этом проекте, поэтому мне было сложно скомпоновать все это в код, который работает, когда я незнаком с API.

К сожалению, меня ограничивают методы, которые соответствуют стандарту Java (1.6.0 Update 16), поэтому, хотя я нашел аналогичный пример с помощью PEMReader от BouncyCastle , он мало помог этому проекту.

Мой ключ privateKey.pem защищен парольной фразой в виде:

-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: DES-EDE3-CBC,63A862F284B1280B [...] tsjQI4H8lhOBuk+NelHu7h2+uqbBQzwkPoA8IqbPXUz+B/MAGhoTGl4AKPjfm9gu OqEorRU2vGiSaUPgDaRhdPKK0stxMxbByUi8xQ2156d/Ipk2IPLSEZDXONrB/4O5 [...] -----END RSA PRIVATE KEY----- 

Они были сгенерированы с использованием OpenSSL:

 openssl.exe genrsa -out private_key.pem 4096 

Я не могу преобразовать этот ключ в DER или другой формат до времени выполнения, любые необходимые преобразования должны быть сделаны внутри кода, так как ключ должен быть легко заменен, а формат останется PEM.

Я слышал множество вещей, о которых я не совсем уверен, и надеялся, что коллективные умы здесь, в SO, помогут собрать кусочки вместе.

Я слышал, что он сказал, что для сертификата PEM требуется Base64 Decoded, чтобы преобразовать его в сертификат DER, который можно использовать. У меня есть инструмент для декодирования Base64 под названием MiGBase64, но я не совсем уверен, как это сделать.

Я потерялся в документах API Java, пытаясь отследить 15 различных типов ключей, KeyStores, KeyGenerators, Certificates и т. Д., Которые существуют, но я недостаточно знаком с любым из них, чтобы правильно определить, что мне нужно используя и как их использовать вместе.

Основной алгоритм кажется довольно простым, поэтому особенно разочаровывает то, что я не смог написать столь же простую реализацию:

1) Прочтите файл privateKey.pem из файла
2) Загрузите закрытый ключ в class XXX, используя Passphrase, чтобы расшифровать ключ
3) Используйте ключевой объект с classом Signature для подписания сообщения

Помощь с этим, особенно пример кода, очень ценится. Я пытаюсь найти полезные примеры для этой проблемы, так как большинство «близких» примеров генерируют новые ключи, используя BouncyCastle, или просто иначе используют разные формы ключей / classов, не применимые здесь.

Это кажется очень простой проблемой, но это сводит меня с ума, какие-то очень простые ответы?

Если вы используете BouncyCastle, попробуйте следующее:

 import java.io.File; import java.io.FileReader; import java.io.IOException; import java.security.KeyPair; import java.security.Security; import java.security.Signature; import java.util.Arrays; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.openssl.PEMReader; import org.bouncycastle.openssl.PasswordFinder; import org.bouncycastle.util.encoders.Hex; public class SignatureExample { public static void main(String [] args) throws Exception { Security.addProvider(new BouncyCastleProvider()); String message = "hello world"; File privateKey = new File("private.pem"); KeyPair keyPair = readKeyPair(privateKey, "password".toCharArray()); Signature signature = Signature.getInstance("SHA256WithRSAEncryption"); signature.initSign(keyPair.getPrivate()); signature.update(message.getBytes()); byte [] signatureBytes = signature.sign(); System.out.println(new String(Hex.encode(signatureBytes))); Signature verifier = Signature.getInstance("SHA256WithRSAEncryption"); verifier.initVerify(keyPair.getPublic()); verifier.update(message.getBytes()); if (verifier.verify(signatureBytes)) { System.out.println("Signature is valid"); } else { System.out.println("Signature is invalid"); } } private static KeyPair readKeyPair(File privateKey, char [] keyPassword) throws IOException { FileReader fileReader = new FileReader(privateKey); PEMReader r = new PEMReader(fileReader, new DefaultPasswordFinder(keyPassword)); try { return (KeyPair) r.readObject(); } catch (IOException ex) { throw new IOException("The private key could not be decrypted", ex); } finally { r.close(); fileReader.close(); } } private static class DefaultPasswordFinder implements PasswordFinder { private final char [] password; private DefaultPasswordFinder(char [] password) { this.password = password; } @Override public char[] getPassword() { return Arrays.copyOf(password, password.length); } } } 

Команда OpenSSL генерирует пару ключей и кодирует ее в формате PKCS # 1. Если вы не используете шифрование (не предоставили пароль для команды), PEM просто DER для кодировки Base64 для PKCS # 1 RSAPrivateKey.

К сожалению, JCE Sun не предоставляет публичный интерфейс для чтения ключа в этом формате. У вас есть 2 варианта,

  1. Импортируйте ключ в хранилище ключей, и вы можете прочитать его оттуда. Keytool не позволяет импортировать личные ключи. Вы можете найти другие инструменты для этого.

  2. Библиотека OAuth имеет функцию для обработки этого. Посмотрите на код здесь,

http://oauth.googlecode.com/svn/code/java/core/commons/src/main/java/net/oauth/signature/pem/PKCS1EncodedKeySpec.java

Давайте будем гением компьютера.