Key Hiding
Choose your SDK version below:
- Apptrove SDK → Recommended for all projects (Latest: v2.x.x)
- Trackier SDK → Will be deprecated in August 2026 (v1.x.xx)
Use the tabs below to view Key Hiding code for your chosen SDK.
Protect sensitive Apptrove SDK credentials (SDK Key, Secret ID, Secret Key) by storing them securely using iOS Keychain Services. This prevents keys from being exposed in plain text within your app's source code, reducing the risk of unauthorized access and fraudulent activities.
Purpose
Key hiding is essential for securing your Apptrove SDK integration:
- Safeguard SDK Key, Secret ID, and Secret Key from reverse engineering
- Store credentials in iOS Keychain Services for maximum security
- Automatically retrieve keys during app initialization
- Provide fallback mechanisms for key management
- Prevent fraudulent activities by securing SDK credentials
This feature works in conjunction with SDK Signing to provide comprehensive security for your Trackier SDK integration.
Prerequisites
- Apptrove SDK: iOS SDK properly integrated
- iOS: Version 12.0 or later
- Xcode: Latest version
- Trackier Panel: SDK Key, Secret ID, and Secret Key retrieved
- Permissions: Internet access
Implementation
Follow these steps to implement secure key storage in your iOS app:
Step 1: Add Keychain Services
Import the Security framework in your project:
- ✓ Apptrove SDK (Recommended)
- Trackier SDK (Deprecating August 2026)
import UIKit
import Security
import ApptroveSDK // or import apptrove_ios_sdk
import UIKit
import Security
import TrackierSDK // or import trackier_ios_sdk
Step 2: Create Secure Storage Service
Create a service to handle secure storage operations using iOS Keychain:
import Foundation
import Security
class SecureStorageService {
static let shared = SecureStorageService()
private let serviceName = "com.trackier.sdk"
private let accountName = "trackier_credentials"
private init() {}
// Store the Trackier SDK key securely
func storeTrackierKey(_ key: String) -> Bool {
return store(key: key, for: "trackier_sdk_key")
}
// Retrieve the Trackier SDK key securely
func getTrackierKey() -> String? {
return retrieve(for: "trackier_sdk_key")
}
// Store the Secret ID securely
func storeSecretId(_ secretId: String) -> Bool {
return store(key: secretId, for: "trackier_secret_id")
}
// Retrieve the Secret ID securely
func getSecretId() -> String? {
return retrieve(for: "trackier_secret_id")
}
// Store the Secret Key securely
func storeSecretKey(_ secretKey: String) -> Bool {
return store(key: secretKey, for: "trackier_secret_key")
}
// Retrieve the Secret Key securely
func getSecretKey() -> String? {
return retrieve(for: "trackier_secret_key")
}
// Clear all stored credentials
func clearAllCredentials() {
let keys = ["trackier_sdk_key", "trackier_secret_id", "trackier_secret_key"]
for key in keys {
delete(for: key)
}
}
// Private methods for Keychain operations
private func store(key: String, for identifier: String) -> Bool {
guard let data = key.data(using: .utf8) else { return false }
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: identifier,
kSecValueData as String: data,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
// Delete existing item before adding new one
SecItemDelete(query as CFDictionary)
let status = SecItemAdd(query as CFDictionary, nil)
// Handle specific error cases
switch status {
case errSecSuccess:
return true
case errSecDuplicateItem:
// Try to update existing item
let updateQuery: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: identifier
]
let updateAttributes: [String: Any] = [
kSecValueData as String: data
]
let updateStatus = SecItemUpdate(updateQuery as CFDictionary, updateAttributes as CFDictionary)
return updateStatus == errSecSuccess
default:
print("Keychain store error: \(status)")
return false
}
}
private func retrieve(for identifier: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: identifier,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
switch status {
case errSecSuccess:
guard let data = result as? Data,
let string = String(data: data, encoding: .utf8) else {
return nil
}
return string
case errSecItemNotFound:
return nil
default:
print("Keychain retrieve error: \(status)")
return nil
}
}
private func delete(for identifier: String) {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: serviceName,
kSecAttrAccount as String: identifier
]
SecItemDelete(query as CFDictionary)
}
}
Step 3: Create App Configuration
Create a configuration class to manage default values and app settings:
- ✓ Apptrove SDK (Recommended)
- Trackier SDK (Deprecating August 2026)
import ApptroveSDK // or import apptrove_ios_sdk
struct AppConfig {
// Replace these with your actual Apptrove SDK credentials
// IMPORTANT: Remove these keys after first run - they will be stored securely
static let defaultAppTroveKey = "YOUR_K_SDK_KEY_HERE"
static let defaultSecretId = "YOUR_SECRET_ID_HERE"
static let defaultSecretKey = "YOUR_SECRET_KEY_HERE"
// Environment configuration - use AppTroveSDKConfig constants
static let environment = AppTroveSDKConfig.ENV_DEVELOPMENT // or AppTroveSDKConfig.ENV_PRODUCTION
}
import TrackierSDK // or import trackier_ios_sdk
struct AppConfig {
// Replace these with your actual Trackier SDK credentials
// IMPORTANT: Remove these keys after first run - they will be stored securely
static let defaultTrackierKey = "YOUR_TRACKIER_SDK_KEY_HERE"
static let defaultSecretId = "YOUR_SECRET_ID_HERE"
static let defaultSecretKey = "YOUR_SECRET_KEY_HERE"
// Environment configuration - use TrackierSDKConfig constants
static let environment = TrackierSDKConfig.ENV_DEVELOPMENT // or TrackierSDKConfig.ENV_PRODUCTION
}
Step 4: Update App Delegate
Update your AppDelegate.swift to use secure storage for key management: