我正在尝试解决开源项目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#importsCertificatesFromKeystore)时,我收到以下错误:
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 MSK):
我想我找到了原因。我在 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
)。