Secret management tool.
MIT License
Secret management tool written in Swift. This was heavily inspired by CcocoaPods-Keys & NSHipster article regarding secret management.
Set up a config file for a project once:
secrets:
- API_KEY
- API_SECRET
outputs:
- ./Secrets.swift
Now, with API_KEY
and API_SECRET
stored in environment variables, you can generate a file with secrets using:
pouch retrieve
Which should generate an output similar to this one (applied xor
on a string (+ randomly generated salt) with a reverse func to read it in the app)):
import Foundation
enum Secret {
static let apiKey: String = Secret._xored([15, 26, 26, 243, 46, 124, 234, 140, 48, 169, 192], salt: [97, 115, 121, 150, 65, 18, 143, 225, 81, 221, 165, 134, 36, 222, 157, 20, 172, 203, 97, 8, 26, 81, 49, 144, 147, 1, 197, 21, 35, 32, 83, 156, 247, 108, 211, 108, 202, 174, 119, 134, 141, 176, 180, 38, 171, 110, 89, 21, 213, 32, 171, 146, 63, 245, 87, 139, 162, 194, 63, 57, 75, 0, 165, 122, 142])
static let apiSecret: String = Secret._xored([153, 59, 35, 31, 242, 106, 45, 3, 19, 67, 207, 9, 190, 40, 55, 197, 218, 221, 1, 40, 170, 117, 103, 211, 204, 168, 44, 18, 39, 207, 44, 158, 217, 135, 163, 16, 145, 120, 158, 221, 212, 49, 229, 116, 188, 145, 91, 203, 174, 184, 158, 78, 146, 106, 100, 166, 93, 239, 8, 18, 38, 129, 97, 249, 218, 137, 48, 58, 80, 252, 102, 47, 7, 92, 90, 194, 64, 61, 151, 221, 39], salt: [252, 85, 73, 112, 139, 3, 67, 100, 51, 55, 167, 96, 205, 8, 68, 168, 187, 177, 109, 8, 222, 26, 8, 191, 243, 136, 101, 50, 80, 160, 89, 242, 189, 167, 207, 127, 231, 29, 190, 174, 187, 92, 128, 84, 212, 244, 55, 187, 142, 207, 247, 58, 250, 74, 13, 210, 124, 207, 88, 64, 85, 174, 8, 138, 169])
private static func _xored(_ secret: [UInt8], salt: [UInt8]) -> String {
return String(bytes: secret.enumerated().map { index, character in
return character ^ salt[index % salt.count]
}, encoding: .utf8) ?? ""
}
}
Now, add this file to your project structure (and to .gitignore
) and use it!
api.auth(key: Secret.apiKey, secret: Secret.apiSecret)
Note: The idea is that each developer would regenerate that file and not commit to the repository (however, you can use it however you want).
Let's face it - managing secret keys is not an easy task. We usually want:
.xcconfig
makes it even easier to the attacker)While writing this tool there was nothing that I found that helped with all of the above.
pouch
will make sure that static analysis tools will not be able to get to the keys easily. Though, for your own good, do not commit this file to the repository.
The config is in YAML format. By default the tool will look for .pouch.yml
file, but you can provide a custom file path as a parameter:
pouch retrieve --config ./.custom.pouch.yml
For the config itself, you are required to have at least one secret and one output:
secrets:
- API_KEY
outputs:
- ./Secrets.swift
Though, there are also custom properties you can set.
You can change the generated type name (it's Secrets
by default):
secrets:
- API_KEY
outputs:
- filePath: ./Constants.swift
typeName: Constant
You are also able to provide a custom generated name for a secret (otherwise it will do the camelCase
):
secrets:
- name: API_KEY
generatedName: youtubeApiKey
- API_SECRET
outputs:
- ./Secrets.swift
There are also things like custom inputs, but for now we only support environment variables.
You can either build & install it by using my Homebrew tap:
brew install sunshinejr/formulae/pouch
or by cloning the repo and using Make:
make install
This project is at its early stage and it currently only supports xor
with random salt & only Swift output, but I'm open to:
Caesar
is great but shifting might be problematic for things like emoji)While this is for sure an improvement to your normal, plain-text based flow, this doesn't guarantee that your keys won't be reverse-engineered. If you want to learn more about secret management and it's security, I recomend you to read the whole article I linked at the top of the Readme: NSHipster article regarding secret management