簡體   English   中英

從 java 程序運行多個 unix 命令

[英]Run multiple unix commands from a java program

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Main {
  public static void main(String[] args) throws IOException, InterruptedException {
    // Set the key and iv values
    String key = "1234567812345678";
    String iv = "1234567812345678";

    // Set the string to encrypt
    String string = "passwordToBeEncrypted";

    // Create the ProcessBuilder object and specify the command and its arguments
    ProcessBuilder pb = new ProcessBuilder("echo", string, "|", "openssl enc -aes-256-cbc -k", key, "-iv", iv, "-base64");

    // Start the process and get the Process object
    Process p = pb.start();

    // Wait for the process to finish and get the exit code
    int exitCode = p.waitFor();
    System.out.println("Exit code: " + exitCode);

    // Read the output from the process
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String encryptedString = reader.readLine();

    // Print the encrypted string
    System.out.println("Encrypted string: " + encryptedString);
  }
}

我期待 output 是一個加密的字符串,而實際的 output 是命令本身,即它打印命令“加密字符串:passwordToBeEncrypted | openssl enc -aes-256-cbc -k 1234567812345678 -iv 1234567812346上面的代碼。

我正在嘗試從 java 代碼執行以下 shell 命令 -

關鍵=“1234567812345678”四=“1234567812345678”

string="passwordToBeEncrypted"

encrypted_string=$(echo "$string" | openssl enc -aes-256-cbc -k "$key" -iv "$iv" -base64)

回聲“$encrypted_string”

正如我們已故首席執行官評論的那樣,Java ProcessBuilder (以及Runtime.exec )不是 shell - 它不運行 Unix '命令',而是運行程序 您給 Unix shell 的許多命令實際上運行一個程序,但它們也可以做其他事情,例如管道或以其他方式重定向 I/O,並像您發布的命令中那樣替換變量,而ProcessBuilder不執行這些其他操作Java 9 向上的管道除外的東西。 請參閱我在Java 中 Shell 命令的回答中的編譯,其中包含 Runtime.getRuntime().exec(); .

但是,您實際上並不需要管道; 默認情況下, ProcessBuilder將其運行的程序的標准輸入和標准輸出(以及標准錯誤)分別重定向到 Java 進程的管道,您的代碼可以使用該進程。 特別是 Unix shell 命令行

echo string | openssl enc ...

echo程序運行到 output 'string'(加上換行符),它被重定向到 pipe,然后被重定向為openssl程序的輸入,在某些 shell 中,您可以獲得完全相同的結果

openssl <<<string enc ...

它運行一個程序openssl ,其輸入重定向自臨時文件或由 shell 本身(不是單獨的程序)創建的 pipe 並且ProcessBuilder可以有效地執行后者:

    String key = "1234567812345678";
    String iv = "1234567812345678";
    String string = "passwordToBeEncrypted";

    ProcessBuilder pb = new ProcessBuilder("openssl","enc","-aes-256-cbc","-k",key,"-iv",iv,"-base64");
    // note every token parsed from the shell command as a separate argument (which is every one
    // separated by unquoted whitespace) must be a separate argument to ProcessBuilder
    Process p = pb.start();
    // **CHANGE HERE**
    p.getOutputStream.write( (string+"\n").getBytes(/*charset if needed*/) );
    p.getOutputStream.close();
    // instead of using the OutputStream directly you can wrap (a) Writer(s) on it and use that(them),
    // similar to the way you wrap Readers on the InputStream below, but I didn't bother

    // if the data contains any non-ASCII character(s) then the 'charset' used for encoding matters; 
    // you need to specify it in `String.getBytes()`, or when creating Writer(s) if you do that,
    // as a Java value equivalent to the 'locale' used by the echo program in your shell, 
    // which will generally be the setting of the env var LC_ALL or LANG -- 
    // but your posted data is all ASCII so all charsets Java can default to are okay

    int exitCode = p.waitFor();
    System.out.println("Exit code: " + exitCode);
    BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String encryptedString = reader.readLine();

    System.out.println("Encrypted string: " + encryptedString);

PS:您發布的所有嘗試/版本都加密——而不是解密——一個字符串,以一種特殊的方式與openssl不完全標准,甚至不是很好,請參閱(我的) https://crypto.stackexchange。 com/questions/3298/is-there-a-standard-for-openssl-interoperable-aes-encryption/#35614 而且您實際上不需要運行openssl Java 自己的加密函數可以做完全相同的事情,盡管如果您沒有並使用 BouncyCastle 第三方庫,您需要一些代碼將幾個原語放在一起以產生與 openssl 的EVP_BytesToKey相同的結果。 關於這個問題有很多現有的問題,可以追溯到很多年前; 我稍后會嘗試挖掘一些。 但是當然你沒有問過做密碼學,更不用說做好的密碼學了,只是關於運行指定的特定程序。

您需要先運行 shell(管道是 shell 的東西),然后將正確的程序和 arguments 傳遞給 測試並使用 Java 8:

import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException, InterruptedException {
        // Set the key and iv values
        String key = "1234567812345678";
        String iv = "1234567812345678";

        // Set the string to encrypt
        String string = "passwordToBeEncrypted";

        // Create the ProcessBuilder object and specify the command and its arguments
        String command = String.format("echo %s | openssl enc -aes-256-cbc -k %s -iv %s -base64", string, key, iv);
        ProcessBuilder pb = new ProcessBuilder("bash", "-c", command);
        pb.inheritIO();

        // Start the process and get the Process object
        Process p = pb.start();


        // Wait for the process to finish and get the exit code
        int exitCode = p.waitFor();
        System.out.println("Exit code: " + exitCode);

    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM