Как программно передать ввод в Java keytool?
Я пытаюсь исправить проблему в проекте с открытым исходным кодом https://github.com/jcabi/jcabi-ssl-maven-plugin.
Проблема возникает в методе com.jcabi.ssl.maven.plugin.Keytool#genkey
:
@Loggable(Loggable.DEBUG)
public void genkey() throws IOException {
final Process proc = this.proc(
"-genkeypair",
"-alias",
"localhost",
"-keyalg",
"RSA",
"-keysize",
"2048",
"-keypass",
this.password
).start(); // Here we launch the keytool
final PrintWriter writer = new PrintWriter(
new OutputStreamWriter(proc.getOutputStream())
);
writer.print("localhost\n"); // These and other writer.print(...) statements
writer.print("ACME Co.\n"); // write answers to questions of keytool
writer.print("software developers\n");
writer.print("San Francisco\n");
writer.print("California\n");
writer.print("US\n");
writer.print("yes\n");
writer.close();
new VerboseProcess(proc).stdout();
Logger.info(
this,
"Keystore created in '%s' (%s)",
this.keystore,
FileUtils.byteCountToDisplaySize(this.keystore.length())
);
}
Целью этого кода является
- запустить программу Java keytool и
- ответить на его вопросы в командной строке.
Первый шаг включает в себя программный вызов, как "C:\Program Files\Java\jdk1.8.0\jre\bin\keytool" -genkeypair -alias localhost -keyalg RSA -keysize 2048 -keypass some-password -storetype jks -noprompt -storepass some-password -keystore C:\Users\DP118M\AppData\Local\Temp\junit4133348108660376680\keystore.jks
,
Затем keytool задает вам несколько вопросов (см. Ниже, перевод с немецкого):
What is your name?
[Unknown]: A
What is the name of your organizational unit?
[Unknown]: A
What is the name of your organisation?
[Unknown]: A
What is the name of your city or county?
[Unknown]: A
What is the name of your state?
[Unknown]: A
What is the country code of your organizational unit?
[Unknown]: A
Is CN=A, OU=A, O=A, L=A, ST=A, C=A correct?
[No]: Yes
Вместо того, чтобы вводить ответы (A
выше) вручную, код выше использует writer.print(...);
заявления.
Но они, очевидно, не работают, потому что когда я запускаю тест, который включает использование keytool (например, com.jcabi.ssl.maven.plugin.CacertsTest#importCertificatesFromKeystore), я получаю следующую ошибку:
java.lang.IllegalArgumentException: Non-zero exit code 1: Keytool Error: java.lang.RuntimeException: Too many repeated attempts. Program will be terminated.
\n
at com.jcabi.log.VerboseProcess.stdout(VerboseProcess.java:220)
at com.jcabi.log.VerboseProcess.stdout(VerboseProcess.java:158)
at com.jcabi.ssl.maven.plugin.Keytool.genkey(Keytool.java:116)
at com.jcabi.ssl.maven.plugin.Keystore.activate(Keystore.java:121)
at com.jcabi.ssl.maven.plugin.CacertsTest.importsCertificatesFromKeystore(CacertsTest.java:64)
Я предполагаю, что основной причиной этой проблемы является то, что writer.print(...);
заявления не доставляют свои тексты в keytool.
Как я могу это исправить (убедитесь, что в com.jcabi.ssl.maven.plugin.Keytool#genkey
метод сообщения, написанные writer.print(...);
правильно доставлены keytool
)
Обновление 1 (28.12.2014 мск):
Я думаю, что нашел причину. Я запускаю свой тест на Windows, поэтому звонки, как writer.print("localhost\n");
должны быть заменены writer.print("localhost" + System.getProperty("line.separator"));
,
Это просто.
Но есть и другая часть. Разработчики этого кода, очевидно, работали над англоязычной версией keytool, поэтому в конце она ожидает yes
(см. последний вопрос в примере вывода keytool выше).
Поэтому есть утверждение
writer.print("yes\n");
Но я использую немецкую версию Windows, поэтому в моем случае правильный ответ не yes
, но Ja
,
Если я изменяю код следующим образом, он работает (тест не проходит):
final String newLine = System.getProperty("line.separator");
writer.print("localhost" + newLine);
writer.print("ACME Co." + newLine);
writer.print("software developers" + newLine);
writer.print("San Francisco" + newLine);
writer.print("California" + newLine);
writer.print("US" + newLine);
writer.print("Ja" + newLine);
Я ценю советы о том, как заставить эту часть кода работать на операционных системах с любым языком (как избежать жесткого кодирования yes
а также Ja
).