🔐 SecureQueryItem makes it easy to secure sensitive API parameters.
When working with APIs that require partial (field-level) encryption — where some parameters must be encrypted while others stay in plain text — developers often end up managing two separate dictionaries:
- values (e.g, ["username": "Alice", "password": "Hello, Bob!"])
- encryption flags (e.g., ["username": "N", "password": "Y"])
This leads to repetitive, error-prone, and messy code.
Let’s say you’re building a login request between 🤷 Alice (the user) and 🧑💻 Bob (the server).
Meanwhile, 🕵️ Trudy, an attacker lurking on the network, is eager to intercept anything she can.
let params: [String: String] = [
"username": "Alice",
"password": "Hello, Bob!"
]
let encryptionFlags: [String: String] = [
"username": "N",
"passwod": "Y"
]What happens?
- 🕵️ Trudy, the attacker on the network, can now see Alice’s password in plaintext. Since
"password"wasn’t marked for encryption (due to the"passwod"typo), it gets sent over the wire unprotected. - 🧑💻 Bob, the server, expects "password" to be encrypted. But he receives a plaintext field instead — or worse, never sees it at all because it’s named "passwod". He shrugs and returns an error, or maybe just logs something silently.
- 🤷 Alice, the user, is left wondering why her login doesn’t work — unaware that her password was just exposed.
This kind of bug doesn’t crash.
It compiles. It runs. It leaks data.
And unless you’re looking for it, you’ll never know.
SecureQueryItem solves this by:
- Representing both plaintext and encrypted fields in a single dictionary
- Automatically encrypting only the necessary fields before sending
Let the code guide you — just follow me.
let params: SecureQueryItem = [
"username": "Alice",
"password": .secure("Hello, Bob!")
]final class MyCryptoModule: CryptoProvider {
static let shared = MyCryptoModule()
private init() {}
private var _text: String?
func encrypt(_ plaintext: String) {
// encrypt and store internally
}
func getSecureText() -> String {
// return the encrypted result
}
func clear() {
// clear internal encrypted memory if needed
}
func decrypt(_ ciphertext: String) -> String {
// decrypt and return plain text
}
}let bodyData = try? JSONEncoder().encode(
params.encrypted(using: MyCryptoModule.shared)
)Now you're ready to pass bodyData to your URLSession request —
then just decrypt the response and you're done.
Task {
var request = URLRequest(url: URL(string: "https://example.com/api")!)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = bodyData
do {
let (data, response) = try await URLSession.shared.data(for: request)
// handling HTTPURLResponse starts
// ...
// handling HTTPURLResponse ends
let envelope = try JSONDecoder().decode(SecureResponse.self, from: data)
let decryptedJson = MyCryptoModule.shared.decrypt(envelope.data)
let payload = try JSONDecoder().decode(
Payload.self, from: .init(decryptedJson.utf8)
)
// result handling
} catch {
// error handling
}
}SecureQueryItem is available via Swift Package Manager.
- Open your project in Xcode
- Go to File > Add Packages…
- Enter the URL:
https://github.com/dsunny90/SecureQueryItem
- Select the version and finish
dependencies: [
.package(url: "https://github.com/dsunny90/SecureQueryItem", from: "1.0.0")
]