Encrypted String
The default value of an encrypted String is "". You must change the default value of the property by assigning a new plain text value in an overridden reset method.
The default value of a NSString is @"". You must change the default value of the property by assigning a new plain text value in an overridden reset method.
NSString properties should be declared in your APLConfiguration subclass header file as follows:
@import AppfigurateLibrary;
@interface Configuration : APLConfiguration
@property(nonatomic, strong) NSString* propertyName;
...The default value of an encrypted String is "". You must change the default value of the property by assigning a new plaintext value in an overridden reset method.
The default value of an encrypted String is "". You must change the default value of the property by assigning a new plaintext value in an overridden reset method.
The flutter APLNativeConfiguration class defers to the underlying platform APLConfiguration (iOS) or nz.co.electricbolt.appfiguratelibrary.Configuration (Android) subclass to read property values.
The React Native module AppfigurateModule class defers to the underlying platform APLConfiguration (iOS) or nz.co.electricbolt.appfiguratelibrary.Configuration (Android) subclass to read property values.
This page describes encrypted strings. Appfigurate also supports plain textual strings.
Local properties
Editable List UI
Allows a string property to be changed in Appfigurate by allowing the user to select from a predefined list of valid choices. The user can customize the list adding by additional values using a text field and an optional regular expression validating input.

Swift @EncryptedStringPropertyListEdit prototype
@EncryptedStringPropertyListEdit(regex, description, encrypted, restart, values)
var propertyName: The encrypted parameter of EncryptedStringPropertyListEdit must be the result of calling the ENCRYPTED() function. e.g.
... description: "url", encrypted: ENCRYPTED(), restart: ...Swift @EncryptedStringPropertyListEdit example
@EncryptedStringPropertyListEdit(regex: #"https://[\w\.-]+\.appfigurate.io/.*"#, description: "url", encrypted: ENCRYPTED(), restart: false, values: [
"Dev":ENCRYPTED_STRING("https://dev.appfigurate.io/list","H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ=="),
"Test":ENCRYPTED_STRING("https://test.appfigurate.io/list","PL+UtWB9WHuO7...aX5BdNqEcbmQE="),
"Prod":ENCRYPTED_STRING("https://m.appfigurate.io/list","IxrJFFUarMg6p...E7OWYOC2uJ1AQ==")])
var url:
override func reset() {
url = "https://m.appfigurate.io/list"
}
...ENCRYPTED_STRING function
Swift ENCRYPTED_STRING prototype
func ENCRYPTED_STRING(_ plaintext: String, _ ciphertext: String) -> StringFor an iOS app (or watchOS and it's companion iOS app) where the APLConfiguration subclass has one public key use the ENCRYPTED_STRING function for each list item in the @EncryptedStringPropertyListEdit.
The first parameter of the ENCRYPTED_STRING function is the plaintext, and will be used by DEBUG builds. The second parameter of the ENCRYPTED_STRING macro is the ciphertext, and will be used by RELEASE builds. To generate the ciphertext, use the source editor extension for Xcode or AppfigurateSE app.
Swift ENCRYPTED_STRING example
@EncryptedStringPropertyListEdit(regex: #"https://[\w\.-]+\.appfigurate.io/.*"#, description: "url", encrypted: ENCRYPTED(), restart: false, values: [
"Dev":ENCRYPTED_STRING("https://dev.appfigurate.io/list","H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ=="),
"Test":ENCRYPTED_STRING("https://test.appfigurate.io/list","PL+UtWB9WHuO7...aX5BdNqEcbmQE="),
"Prod":ENCRYPTED_STRING("https://m.appfigurate.io/list","IxrJFFUarMg6p...E7OWYOC2uJ1AQ==")])
var url: StringENCRYPTED function
Swift ENCRYPTED prototype
func ENCRYPTED() -> BoolUsed in conjunction with the @EncryptedStringPropertyListEdit property wrapper. The encrypted parameter of @EncryptedStringPropertyListEdit must be the result of calling the ENCRYPTED() function. e.g.
... description: "url", encrypted: ENCRYPTED(), restart: ...The function returns true if the calling app has been compiled in RELEASE mode or false if the calling app has been compiled in DEBUG mode.
ENCRYPTED function & Swift compiler ‣ Optimizing for Size
Warning: The ENCRYPTED function will behave incorrectly if the apps build settings Swift compiler - Code generation ‣ Optimization Level is set to Optimize for Size (-Osize). The default Swift compiler optimization levels are No Optimization for DEBUG builds and Optimize for Speed -Ospeed for RELEASE builds. If you must use -Osize, then implement your own isEncrypted() style function as follows:
Swift isEncrypted example
func isEncrypted() {
#if DEBUG
return false
#else
return true
#end
}Then call your own isEncrypted() function instead of the provided ENCRYPTED() function e.g.
... description: "url", encrypted: isEncrypted(), restart: ...Objective-C ENCRYPTED_STRING_PROPERTY_LIST_EDIT prototype
ENCRYPTED_STRING_PROPERTY_LIST_EDIT(propertyName, regex, description, restart, ...)Objective-C ENCRYPTED_STRING_PROPERTY_LIST_EDIT example
@import AppfigurateLibrary;
@interface Configuration : APLConfiguration
@property(nonatomic, strong) NSString* url;
@end
@implementation Configuration
ENCRYPTED_STRING_PROPERTY_LIST_EDIT(url, @"https://[\\w\\.-]+\\.appfigurate.io/.*", @"url", NO, @{
@"Dev": ENCRYPTED_STRING(@"https://dev.appfigurate.io/list",@"H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ=="),
@"Test": ENCRYPTED_STRING(@"https://test.appfigurate.io/list",@"PL+UtWB9WHuO7...aX5BdNqEcbmQE="),
@"Prod": ENCRYPTED_STRING(@"https://m.appfigurate.io/list",@"IxrJFFUarMg6p...E7OWYOC2uJ1AQ==")});
- (void) reset {
self.url = @"https://m.appfigurate.io/list";
}
...ENCRYPTED_STRING macro
Objective-C ENCRYPTED_STRING prototype
ENCRYPTED_STRING(plaintext, ciphertext)For an iOS app (or watchOS and it's companion iOS app) where the APLConfiguration subclass has one public key use the ENCRYPTED_STRING macro for each list item in the ENCRYPTED_STRING_PROPERTY_LIST_EDIT.
The first parameter of the ENCRYPTED_STRING macro is the plain text, and will be used by DEBUG builds. The second parameter of the ENCRYPTED_STRING macro is the ciphertext, and will be used by RELEASE builds. To generate the ciphertext, use the source editor extension for Xcode or AppfigurateSE app.
Objective-C ENCRYPTED_STRING example
ENCRYPTED_STRING_PROPERTY_LIST_EDIT(url, @"https://[\\w\\.-]+\\.appfigurate.io/.*", @"url", NO, @{
@"Dev":ENCRYPTED_STRING(@"https://dev.appfigurate.io/list",@"H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ=="),
@"Test":ENCRYPTED_STRING(@"https://test.appfigurate.io/list",@"PL+UtWB9WHuO7...aX5BdNqEcbmQE="),
@"Prod":ENCRYPTED_STRING(@"https://m.appfigurate.io/list",@"IxrJFFUarMg6p...E7OWYOC2uJ1AQ==")});Kotlin @EncryptedStringPropertyListEdit prototype
@EncryptedStringPropertyListEdit(description, regularExpression, encrypted, restart)The encrypted parameter of EncryptedStringPropertyListEdit must be the result of calling BuildConfig.ENCRYPTED. e.g.
... description = "url", encrypted = BuildConfig.ENCRYPTED, restart = ...You must implement a method with the same name as the property, but ending with Values. e.g. if your property name is url, your method must be named urlValues. The method must return a Map<String, String> of the possible property values.
Kotlin Values method prototype
var propertyName:
companion object {
var _propertyNameValues: MutableMap<String, String> = HashMap()
init {
_propertyNameValues["key1"] = if (BuildConfig.ENCRYPTED) "cipher1" else "plain1"
}
}
fun propertyNameValues(): Map<String, String> {
return _propertyNameValues;
}Kotlin example
import nz.co.electricbolt.appfiguratelibrary.Configuration
import nz.co.electricbolt.appfiguratelibrary.annotations.EncryptedStringPropertyListEdit
class AppConfiguration : Configuration() {
@EncryptedStringPropertyListEdit(description = "url", regularExpression = "https://[\w\.-]+\.appfigurate.io/.*", encrypted = BuildConfig.ENCRYPTED, restart = false)
var url:
companion object {
var _urlValues: MutableMap<String, String> _urlValues = HashMap()
init {
_urlValues["Dev"] = if (BuildConfig.ENCRYPTED) "H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ==" else "https://dev.appfigurate.io/list"
_urlValues["Test"] = if (BuildConfig.ENCRYPTED) "PL+UtWB9WHuO7...aX5BdNqEcbmQE=" else "https://test.appfigurate.io/list"
_urlValues["Prod"] = if (BuildConfig.ENCRYPTED) "IxrJFFUarMg6p...E7OWYOC2uJ1AQ==" else "https://m.appfigurate.io/list"
}
}
fun urlValues(): Map<String, String> {
return _urlValues
}
override fun reset() {
url = "https://m.appfigurate.io/list"
}
...BuildConfig.ENCRYPTED build constant
In your application's build.gradle:
Add the following into the
android‣buildTypes‣debugsection:buildConfigField("boolean", "ENCRYPTED", "false")Add the following into the
android‣buildTypes‣releasesection:buildConfigField("boolean", "ENCRYPTED", "true")Ensure ProGuard runs on a Release build variant so that
BuildConfig.ENCRYPTED == falsedead code is stripped from the resulting APK or AAB (this will ensure the plaintext values are removed).
build.gradle example
apply plugin: 'com.android.application'
android {
compileSdkVersion 32
defaultConfig {
...
}
buildTypes {
debug {
debuggable true
minifyEnabled false
zipAlignEnabled false
buildConfigField("boolean", "ENCRYPTED", "false")
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
buildConfigField("boolean", "ENCRYPTED", "true")
}
}
}
...Once you've modified build.gradle and synced the Gradle project, ensure the generated BuildConfig.java contains the following for a Debug build variant:
public static final boolean ENCRYPTED = false;and the following for a Release build variant:
public static final boolean ENCRYPTED = true;To generate the ciphertext, use the AppfigurateSE app.
Java @EncryptedStringPropertyListEdit prototype
@EncryptedStringPropertyListEdit(description, regularExpression, encrypted, restart)The encrypted parameter of EncryptedStringPropertyListEdit must be the result of calling BuildConfig.ENCRYPTED. e.g.
... description = "url", encrypted = BuildConfig.ENCRYPTED, restart = ...You must implement a method with the same name as the property, but ending with Values. e.g. if your property name is url, your method must be named urlValues. The method must return a Map<String, String> of the possible property values.
Java Values method prototype
String propertyName;
static Map<String, String> _propertyNameValues = new HashMap<>();
static {
_propertyNameValues.put("key1", BuildConfig.ENCRYPTED ? "cipher1" : "plain1");
}
public Map<String, String> propertyNameValues() {
return _propertyNameValues;
}Java example
import nz.co.electricbolt.appfiguratelibrary.Configuration;
import nz.co.electricbolt.appfiguratelibrary.annotations.EncryptedStringPropertyListEdit;
public class AppConfiguration extends Configuration {
@EncryptedStringPropertyListEdit(description: "url", regularExpression = "https://[\w\.-]+\.appfigurate.io/.*", encrypted = BuildConfig.ENCRYPTED, restart = false)
String url;
static Map<String, String> _urlValues = new HashMap<>();
static {
_urlValues("Dev", BuildConfig.ENCRYPTED ? "H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ==" : "https://dev.appfigurate.io/list");
_urlValues("Test", BuildConfig.ENCRYPTED ? "PL+UtWB9WHuO7...aX5BdNqEcbmQE=" : "https://test.appfigurate.io/list");
_urlValues("Prod", BuildConfig.ENCRYPTED ? "IxrJFFUarMg6p...E7OWYOC2uJ1AQ==" : "https://m.appfigurate.io/list");
}
public Map<String, String> urlValues() {
return _urlValues;
}
@Override
public void reset() {
this.url = "https://m.appfigurate.io/list";
}
...BuildConfig.ENCRYPTED build constant
In your application's build.gradle:
Add the following into the
android‣buildTypes‣debugsection:buildConfigField("boolean", "ENCRYPTED", "false")Add the following into the
android‣buildTypes‣releasesection:buildConfigField("boolean", "ENCRYPTED", "true")Ensure ProGuard runs on a Release build variant so that
BuildConfig.ENCRYPTED == falsedead code is stripped from the resulting APK or AAB (this will ensure the plaintext values are removed).
build.gradle example
apply plugin: 'com.android.application'
android {
compileSdkVersion 32
defaultConfig {
...
}
buildTypes {
debug {
debuggable true
minifyEnabled false
zipAlignEnabled false
buildConfigField("boolean", "ENCRYPTED", "false")
}
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
buildConfigField("boolean", "ENCRYPTED", "true")
}
}
}
...Once you've modified build.gradle and synced the Gradle project, ensure the generated BuildConfig.java contains the following for a Debug build variant:
public static final boolean ENCRYPTED = false;and the following for a Release build variant:
public static final boolean ENCRYPTED = true;To generate the ciphertext, use the AppfigurateSE app.
Dart prototype
String get propertyName => nativeString('propertyName');Dart example
import 'package:appfigurateflutter/appfigurateflutter.dart';
public class Configuration extends APLNativeConfiguration {
String get url => nativeString('url');
...JavaScript example
import {
NativeModules,
} from 'react-native';
const {Appfigurate} = NativeModules;
...
let url = await Appfigurate.nativeValue("url");Encryption best practice
iOS and watchOS
Using ENCRYPTED_STRING guarantees that the plaintext of the list item values will not be included in the resulting application binary, only the ciphertext. The ciphertext can only be decrypted by Appfigurate using the correct private key.
You can verify that the plain text is not included in the RELEASE application binary using the macOS strings tool as follows:
Terminal
> cd ~/Library/Developer/Xcode/DerivedData/AppfigurateWorkspace-esajjxyazigjunfteipthjfiobut/Build/Products/Release-iphoneos/AppfigurateExample (iOS).app
> strings AppfigurateExample | grep "https://dev.appfigurate.io/list" // no results
> strings AppfigurateExample | grep "H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ==" // prints H7o9Lgqd4RgMJ...rtJQGh8DiiSAQ==It is best practice to use ENCRYPTED_STRING to encrypt sensitive information such as server urls (e.g. internal test environments), rather than expose them as plain text.
Android
Using a combination of BuildConfig.ENCRYPTED and ProGuard guarantees that the plaintext of the list item values will not be included in the resulting application binary, only the ciphertext. The ciphertext can only be decrypted by Appfigurate using the correct private key.
You can verify that the plaintext is not included in the RELEASE build variant APK or AAB using the macOS strings tool as follows:
Terminal
> cd AppfigurateExample/build/outputs/apk/release
> unzip AppfigurateExample-release.apk
> d2j-dex2jar -f classes.dex
> unzip classes-dex2jar.jar
> cd nz/co/electricbolt/appfigurateexample
> strings - ExampleConfiguration.class | grep "https://dev.appfigurate.io/list" // no results
> strings - ExampleConfiguration.class | grep "jm9SM4MEYa4FR...glwMGnpRI4JAQ==" // prints jm9SM4MEYa4FR...glwMGnpRI4JAQ==Flutter
Ensure you have read the encryption best practices for iOS and watchOS, and Android sections.
React Native
Ensure you have read the encryption best practices for iOS and watchOS, and Android sections.
Last updated