Java-执行OpenSSL命令运行时出错

时间:2020-07-30 16:35:23

标签: java openssl

我有以下代码来执行Openssl命令并通过Java运行时读取该命令产生的输出

public void executeCmd() throws IOException {
        Runtime rt = Runtime.getRuntime();
        String[] commands = new String[]{"openssl", "rsa", "-noout", "-modules", "-in", "myPathToKeyFile", "|", "openssl", "sha256"};
        
        Process proc = rt.exec(commands);
        BufferedReader stdInKey = new BufferedReader(new InputStreamReader(proc.getInputStream()));

         String s = null;
        
        while ((s = stdInKey.readLine()) != null) {
            System.out.println(s);
        }
        
    }

当我通过Cmd运行命令时,它正在工作,我能够看到输出

但是当我运行这段代码时,出现以下错误:

Exception in thread "main" java.io.IOException: Cannot run program "openssl": CreateProcess error=2, The system cannot find the file specified
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
    at java.lang.Runtime.exec(Runtime.java:620)
    at java.lang.Runtime.exec(Runtime.java:485)
    at com.renault.vnext.business.impl.CmdRunner.executeCmd(CmdRunner.java:22)
    at com.renault.vnext.business.impl.CmdRunner.main(CmdRunner.java:10)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
    at java.lang.ProcessImpl.create(Native Method)
    at java.lang.ProcessImpl.<init>(ProcessImpl.java:444)
    at java.lang.ProcessImpl.start(ProcessImpl.java:140)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
    ... 4 more

注意:我已经在路径变量中设置了upto bin文件夹

我能够在cmd中运行命令并获取输出。我的要求是从命令ouptut中获取标准输入值

enter image description here

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

首先,您显然在PATH环境变量的任何目录中都没有AttributeError: 'LegendItem' object has no attribute 'setColumnCount' 。更改PATH以包括包含openssl可执行文件的目录,或者更改代码以指定openssl可执行文件的完整路径名(因此它不需要使用PATH)。如果在Windows上,请注意,您可以在单个进程中或在注册表中全局更改PATH。在后一种情况下,您需要使用PATH 重新创建任何进程,例如“命令”窗口,终端,shell,powershell或IDE。将Java exec can't run program, error = 2CreateProcess error=2, The system cannot find the file specified复制。

第二,您拼错了openssl[.exe]

第三,将-modulus之类的重定向传递为"|",etc的参数将不起作用。当您在Unix中的shell或Windows中的命令提示符下键入openssl时,不会将openssl rsa ... | openssl sha256传递给第一个openssl。相反,它运行两个不同的进程,并将第一个的输出重定向到管道,第二个的输入从该管道重定向。 | openssl sha256不是命令处理器,不能执行此操作。您可以:

  • 仅运行Runtime.exec()部分,在Java代码中读取输出,并在Java中执行该输出的SHA256

  • 运行命令解释器,并告诉 it 执行复合命令openssl rsa(全部作为一个字符串)。在Unix上,请使用适当的外壳程序-该外壳程序可能会因您的系统而异,但是openssl rsa ... | openssl sha256很常见。在Windows上,请使用/bin/sh -c

仅供参考,如果您拥有或获得BouncyCastle库,它们可以直接在Java中直接使用Java来读取cmd.exe /c可以读取的相同文件,提取模数和格式并对其进行哈希处理,而无需使用openssl rsa 。但是您没有问这个,所以在Stack上不是答案。

答案 1 :(得分:1)

我的系统是Windows 10 x64,因此也许您必须调整openssl.exe的路径。

开始解决方案路径我首先运行OpenSSL命令行:

openssl rsa -noout -modulus -in keyunencrypted.pem | openssl sha256

此结果作为参考:

(stdin)= addc742adb857539b5b7240459e4341b8de7575b437459aacfab605dc46b5e9f

请注意,我使用的是“ 模量”,而不是命令字符串中的“ 模块”。

开始Java体验,我了解到opensll命令行在shell中运行,但是在运行时却没有 通过Runtime.exec的OpenSSL。因此,有一种方法可以通过Output-> InputStream将完整的命令行拆分为两个单独的命令。在Apache的common-io-library的帮助下,有一个非常简单的解决方案。您从https://mvnrepository.com/artifact/commons-io/commons-io获取库,并且 我使用2.7版进行测试。

以下示例摘自https://stackoverflow.com/a/7226858/8166854,由用户@Bohemian编写,并给出以下结果:

[(stdin)= addc742adb857539b5b7240459e4341b8de7575b437459aacfab605dc46b5e9f]

这应该是预期的结果,并且只需一点​​点字符串格式即可获得所需的内容。

这是源代码,请记住没有适当的异常处理。

import org.apache.commons.io.IOUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.List;

public class MainSo {
    public static void main(String[] args) throws IOException {
        System.out.println("https://stackoverflow.com/questions/63177584/java-error-in-executing-openssl-command-thorugh-runtime/63182609#63182609");

        String[] commands1 = new String[]{"E:\\intellij_projects\\openssl_1_1_1g-win64-mingw\\openssl.exe",
        "rsa", "-noout", "-modulus", "-in", "keyunencrypted.pem"};
        String[] commands2 = new String[]{"E:\\intellij_projects\\openssl_1_1_1g-win64-mingw\\openssl.exe", "sha256"};

        // https://stackoverflow.com/a/7226858/8166854
        // by @Bohemian
        // you need https://mvnrepository.com/artifact/commons-io/commons-io
        // commons-io-2.7.jar
        Process p1 = Runtime.getRuntime().exec(commands1);
        InputStream input = p1.getInputStream();
        Process p2 = Runtime.getRuntime().exec(commands2);
        OutputStream output = p2.getOutputStream();
        IOUtils.copy(input, output);
        output.close(); // signals command2 to finish
        List<String> result = IOUtils.readLines(p2.getInputStream(), StandardCharsets.UTF_8);
        System.out.println(result);
    }
}