[英]Printing out ! with printf inside swift code
我正在嘗試用 openssl 加密一個字符串。要加密的字符串是由字母、數字和符號組成的隨機生成的字符串。 運行以下命令以嘗試加密字符串:
printf "randomString" | openssl enc -base64 -e -aes-256-cbc -salt -pass pass: "passwordSalt"
只要字符串中沒有生成任何 printf 不喜歡的字符,這就可以正常工作。 我看過其他關於通過將兩個百分比放在一起來處理%
的帖子%%
。
但是,如果有!
在字符串中。 其他來源說單引號字符串而不是雙引號,因為雙引號導致 bash 插入字符串。 如果我只是在命令行中運行它,這將不是問題。 printf
和 openssl 命令在 swift 中作為Process()
運行,不幸的是在 swift 中沒有單引號這樣的東西。我什至嘗試在字符串生成后用單引號括起來,但這會導致單引號在加密期間成為字符串的一部分。 printf 是否提供了允許使用 a 的任何方式或選項? 當雙引號不是一個選項時在字符串中? echo
也以類似的方式工作,其中單引號有效,但雙引號插入某些字符,但我可以使用echo
或printf
。
停止使用printf
並將輸入字符串直接寫入openssl
的標准輸入。 那么你就不用擔心引用奇怪的字符了。
import Foundation
func encrypt(_ plainText: String) async throws -> String? {
let pipeToChild = Pipe()
let fileHandleToChild = pipeToChild.fileHandleForWriting
let pipeFromChild = Pipe()
let fileHandleFromChild = pipeFromChild.fileHandleForReading
let child = Process()
child.executableURL = URL(fileURLWithPath: "/usr/bin/openssl")
child.arguments = [
"enc",
"-base64",
"-e",
"-aes-256-cbc",
"-salt",
"-pass", "pass:passwordSalt"
]
child.standardInput = pipeToChild
child.standardOutput = pipeFromChild
try child.run()
async let writeResult: () = Task {
try fileHandleToChild.write(contentsOf: plainText.data(using: .utf8)!)
try fileHandleToChild.close()
}.value
async let readResult = Task {
try fileHandleFromChild.readToEnd()
}.value
let _ = try await writeResult
let data = try await readResult
return data.flatMap { String(data: $0, encoding: .utf8) }
}
@main
struct MyMain {
static func main() async {
do {
let answer = try await encrypt(#"string with \/\/eird ${embedded} "c"harac't'ers"#)
print(answer ?? "(failed to encrypt)")
}
catch {
print("error: \(error)")
}
}
}
這是一個不使用async
的版本。 如果openssl
在讀取其所有輸入之前嘗試寫入大量 output,理論上它可能會死鎖。 如果明文不超過 4k,這可能不會有問題。
import Foundation
func encrypt(_ plainText: String) throws -> String? {
let pipeToChild = Pipe()
let fileHandleToChild = pipeToChild.fileHandleForWriting
let pipeFromChild = Pipe()
let fileHandleFromChild = pipeFromChild.fileHandleForReading
let child = Process()
child.executableURL = URL(fileURLWithPath: "/usr/bin/openssl")
child.arguments = [
"enc",
"-base64",
"-e",
"-aes-256-cbc",
"-salt",
"-pass", "pass:passwordSalt"
]
child.standardInput = pipeToChild
child.standardOutput = pipeFromChild
try child.run()
try fileHandleToChild.write(contentsOf: plainText.data(using: .utf8)!)
try fileHandleToChild.close()
let data = try fileHandleFromChild.readToEnd()
return data.flatMap { String(data: $0, encoding: .utf8) }
}
@main
struct MyMain {
static func main() {
do {
let answer = try encrypt(#"string with \/\/eird ${embedded} "c"harac't'ers"#)
print(answer ?? "(failed to encrypt)")
}
catch {
print("error: \(error)")
}
}
}
做這個
printf '%s' 'randomString' | openssl enc -base64 -e -aes-256-cbc -salt -pass pass: "passwordSalt"
避免通過printf
解釋特殊格式字符
使用單引號
printf '%s' '!@#$%%^&*()_+=-0987654321\][{}|;:/.?>,<'
!@#$%%^&*()_+=-0987654321\][{}|;:/.?>,<
在@rob mayoff 的幫助下,我能夠完全避免將 printf/echo 管道傳輸到 openssl。 盡管我確實認為這仍然是一個可能最終需要回答的話題。 我能夠將 pipe 字符串發送到 swift 中的 openssl 進程:
mutating func encryptString(_ plainText: String) throws -> String? {
let pipeToChild = Pipe()
let fileHandleToChild = pipeToChild.fileHandleForWriting
let pipeFromChild = Pipe()
let fileHandleFromChild = pipeFromChild.fileHandleForReading
let child = Process()
child.executableURL = URL(fileURLWithPath: "/usr/bin/openssl")
child.arguments = [
"enc",
"-base64",
"-e",
"-aes-256-cbc",
"-salt",
"-pass", "pass:\(self.passwordSalt)"
]
child.standardInput = pipeToChild
child.standardOutput = pipeFromChild
try child.run()
try fileHandleToChild.write(contentsOf: plainText.data(using: .utf8)!)
try fileHandleToChild.close()
var output = try fileHandleFromChild.readToEnd()
var outputString = String(decoding: output!, as: UTF8.self)
print("output: \(output!)")
child.waitUntilExit()
print("encrypted String: \(outputString)")
self.encryptedPassword = outputString
return "Success"
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.