Использование закодированного PEM-шифрованного закрытого ключа для подписи сообщения изначально
Я пытаюсь использовать сертификат PEM (X.509) (хранящийся в файле privateKey.pem на диске), чтобы подписывать сообщения, отправленные через сокеты на Java, но мне очень трудно найти пример, который близок. Обычно я парень из C ++, который просто вступает, чтобы помочь в этом проекте, поэтому мне было сложно скомпоновать все это в код, который работает, когда я незнаком с API.
К сожалению, меня ограничивают методы, которые соответствуют стандарту Java (1.6.0 Update 16), поэтому, хотя я нашел аналогичный пример с помощью PEMReader от BouncyCastle , он мало помог этому проекту.
Мой ключ privateKey.pem защищен парольной фразой в виде:
- Как добавить субтитры ggplot2 с разным размером и цветом?
- Могут ли аргументы основной подписи на C ++ иметь unsiged и const qualifiers?
- Как показать цифровую подпись PDF на странице документа с помощью iText?
- Как проверить банку, подписанную с программным обеспечением jarsigner
- C ++ Функция Обратные вызовы: невозможно преобразовать из функции-члена в подпись функции
-----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 варианта,
-
Импортируйте ключ в хранилище ключей, и вы можете прочитать его оттуда. Keytool не позволяет импортировать личные ключи. Вы можете найти другие инструменты для этого.
-
Библиотека OAuth имеет функцию для обработки этого. Посмотрите на код здесь,