obfuscateapi
obfuscateapi copied to clipboard
Mac OSX, Command line Swift 4 Utility for obfuscate / defuscate strings (API endpoints) in AES128 format.
obfuscateapi
Mac OSX, Command line Swift 4 Utility for obfuscate (mostly API endpoints) in AES128 format.
Contents
- Motivation
- Tecnology
- Install
- Running it
- Using it
- Some Recommendations
- Credits
- License
Motivation
The list of endpoints or servers that an iOS app have, is restricted information that should not be disclosed, usually developers create that network services definition in a constants file or even worse, in a plist.
A plist is easily breakable and plain text strings are also (see strings command), so anyone with a minimum of knowledge can get to know how is our network services definition, who leaves it prone to attacks.
So doing like this, is a bad security practice:
struct APIConstants {
static let baseURL = "https://server.com"
static let deviceBinding = "api/devideBinding"
This command line utility creates two Swift 4 compatible files:
- An
APIConstants.swiftfile. With strings from network layer encrypted in AES128 CBC format. See how it looks now:
struct APIConstants {
/// Base URL (https://pr2studio.com)
static let baseURL = "Cs6WqbJ4uVMXUhQ/pU96WF/wsWAT5yiBqfGVG99XZ0M="
/// Device binding (/means/getbinding)
static let deviceBinding = "Ja2p49mofIichhwVjkgQlIKQC/RDNBZe4PtZUCMaYCY="
- An inline method in file
AESKeyClass.swiftwhere password is scrambled. See it for password: secretpassword
import Foundation
// using key (ALongHiddenKey9)
@inline(__always) public func aesKey() -> [UInt8] {
return [
0x7C-0x09, 0x66-0x01, 0x51+0x12, 0x01+0x71, 0x0C+0x59, 0x59+0x1B,
0x44+0x2C, 0x6F-0x0E, 0xCA-0x57, 0x8D-0x1A,
0xAD-0x36, 0x56+0x19, 0xD9-0x67, 0x7E-0x1A
]
}
Technology
-
It uses AES128 CBC format, with an optional
iv, if you don´t specify it, the defaultivwill be00000000000000000000000000000000 -
Symmetric encryption
-
Uses standards. Done with Apple CommonCrypto and standard format. No third parties or propietary formats.
-
inline function for the aes key. So it will be more difficult to hijack it, and the attacker would need to patch all occurrences of it.
-
the inlined bytes are generated pseudo-ramdomly, so every time you run it, it will generate different hexs with operations
-
we can deploy a new version of the app with a new AES key. Just running again this command utility.
-
Secure enough
Install
1 Install Command Line Developer tools.
The easiest way is with: xcode-select --install
2 Adjust the ouput files to your needs
If you want to edit the output files format, this can be done changing how they will be created in main.swift
3 Archive the project
From your achived project, you will have an obfuscateapi date.xcarchive file
4 Copy executable to your usr/local/bin folder
Go to xcarchive, show contents and locate Products/usr/local/bin/obfuscateapi and copy it to your /usr/local/bin folder
Running it
Open a command line in Terminal and run the command obfuscateapi
NAME
obfuscateapi - obfuscates a plist to classes in AES128 format
SYNOPSIS
obfuscateapi -key aeskey [-iv ivstring] [-infile file]
DESCRIPTION
The following options are available:
-key the key for encrypting. Better to use a long one
-iv initialization vector. By default is 00000000000000000000000000000000
-infile plist to convert to classes. bu default is apiplain.plist
It will generate two files APIConstants.swift with the encrypted strings and AESKeyClass.swift with a function to retrieve the key
infile plist format
We should describe the network services in a plist, this is a sample plist. Each entry has three parts (dictionary with a long name for comments, constant name and value. Sample with three constants:
<key>Base URL</key>
<dict>
<key>key</key>
<string>baseURL</string>
<key>value</key>
<string>https://pr2studio.com</string>
</dict>
<key>Device binding</key>
<dict>
<key>key</key>
<string>deviceBinding</string>
<key>value</key>
<string>/means/getbinding</string>
</dict>
<key>Send key</key>
<dict>
<key>key</key>
<string>sendKey</string>
<key>value</key>
<string>/means/sendkey</string>
</dict>
Using it
After generated the two files (APIConstants.swift and AESKeyClass.swift), you can copy it to your project, along with Crypto+Extensions.swift
Then when you want to retrieve the string for an endpoint, you should do this:
let arrKeyString = String(data: Data(bytes: aesKey()), encoding: .utf8)
let endpoint = APIConstants.deviceBinding.aesDecryptWithKey(arrKeyString)
then use endpoint constant for doing yout network request
You can check if the strings generated work fine with this openssl command (first save the string ending with a carriage return in file test.enc):
openssl enc -aes128 -k secretpassword -p -iv 00000000000000000000000000000000 -nosalt -base64 -d -in test.enc
Some recommendations
- This is just one small step for App security, you should enforce more measures like jailbreak detection and SSL Pining among others.
- You will never be safe, whatever you do, but is better to do something than nothing
- Security is a feeling, users needs to feel secure enough
Credits
Pablo Roca Rozas. PR2Studio.
License
obfuscateapi is released under the MIT license. See LICENSE for details.