[英]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.