Swift Confidential

repository·master·Indexed 43 days ago

https://github.com/securevale/swift-confidential

A tool for obfuscating Swift string literals to protect sensitive data like API keys, URLs, and certificates from static code analysis and reverse engineering. It provides the ConfidentialKit library and a package plugin to help developers meet security requirements such as OWASP MASVS-RESILIENCE. Features include the #Obfuscate macro, YAML-based configuration for encryption (AES-GCM, ChaCha20-Poly1305), compression (LZFSE, LZ4, LZMA, zlib), and randomization.

Tokens
3.1K
Snippets
9
Records
14
Agent score
6%

What's inside Swift Confidential

  1. How namespaces work in Swift Confidential

    master

    Swift Confidential uses caseless enums to encapsulate generated secrets. You can either create a new namespace or extend an existing one using specific YAML syntax.

    Creating a new namespace: Use create <name>. Example: create ObfuscatedLiterals results in internal enum ObfuscatedLiterals { ... }.

    Extending an existing namespace: Use extend <name> [from <module>]. Example: extend Pinning from Crypto results in extension Crypto.Pinning { ... }.

    Note: Nested namespace creation is currently not supported.

    YAML Syntax Examples:

    # Create new
    create ObfuscatedLiterals
    
    # Extend existing
    extend Pinning from Crypto
  2. Understand Swift Confidential API stability and versioning

    master

    Source Stability

    Swift Confidential follows semantic versioning. Because the project is currently in major version 0, source stability is only guaranteed within minor versions (e.g., between 0.5.0 and 0.5.1). To prevent breaking updates, use a source control requirement in your Swift Package Manager dependency:

    .upToNextMinor(from: "0.5.0")

    Public vs. Experimental API

    • Public API: Consists of non-underscored declarations marked public in the ConfidentialKit module.
    • Experimental API: Denoted with a leading underscore (e.g., _experimentalMethod). These are subject to change in any release, including patch releases.
  3. Install Swift Confidential via Xcode

    master

    To add Swift Confidential to an Xcode project:

    1. Select File > Add Package Dependencies....
    2. Enter https://github.com/securevale/swift-confidential.git in the Search or Enter Package URL field.
    3. Set the Dependency Rule to Up to Next Minor Version.
    4. Click Add Package.
    5. Select your target and choose the ConfidentialKit package product, then click Add Package.
  4. Install Swift Confidential for Xcode

    master

    To integrate Swift Confidential with an Xcode target:

    1. Add swift-confidential and swift-confidential-plugin packages to your Xcode project via Swift Package Manager.
    2. When adding products from the swift-confidential package, select the ConfidentialKit library.
    3. In your target's Build Phases pane, locate the Run Build Tool Plug-ins section.
    4. Click the + button, select the Confidential plugin, and click Add.

    Note: You can add confidential.yml to your Xcode project for convenience, but do not add it to any of the Xcode targets.

  5. Install Swift Confidential for SwiftPM

    master

    To use Swift Confidential with a SwiftPM target, add ConfidentialKit as a dependency and the Confidential plugin to your target's dependencies and plugins.

    Important:

    • Use the same version requirements for both swift-confidential and swift-confidential-plugin.
    • Add the confidential.yml file to your target's exclude list to prevent it from being included as a resource.
    // swift-tools-version: 6.0
    
    import PackageDescription
    
    let package = Package(
        dependencies: [
            .package(url: "https://github.com/securevale/swift-confidential.git", .upToNextMinor(from: "0.5.0")),
            .package(url: "https://github.com/securevale/swift-confidential-plugin.git", .upToNextMinor(from: "0.5.0"))
        ],
        targets: [
            .target(
                name: "MyLibrary",
                dependencies: [
                    .product(name: "ConfidentialKit", package: "swift-confidential")
                ],
                exclude: ["confidential.yml"],
                plugins: [
                    .plugin(name: "Confidential", package: "swift-confidential-plugin")
                ]
            )
        ]
    )
  6. Install Swift Confidential via SwiftPM

    master

    To add Swift Confidential to a Swift Package Manager project, add the package dependency to your Package.swift and then add the ConfidentialKit product to your target.

    // 1. Add the package dependency
    .package(url: "https://github.com/securevale/swift-confidential.git", .upToNextMinor(from: "0.5.0"))
    
    // 2. Add the ConfidentialKit library to your target
    .product(name: "ConfidentialKit", package: "swift-confidential")
  7. Enable Experimental Mode for Swift 6 Macros

    master

    Experimental features (like using Swift macros instead of property wrappers) are only available when experimentalMode is enabled. This requires the Swift 6 toolchain (Xcode 16.0 or later).

    To enable Experimental Mode:

    1. Set experimentalMode: true in your confidential.yml.
    2. Change your target dependency from ConfidentialKit to _ConfidentialKit (note the leading underscore).

    Warning: Swift macros can increase build times, especially on CI/CD machines.

  8. Disable macro and package plugin validation in CI/CD

    master

    For unattended CI/CD environments, you can bypass macro and package plugin validations using one of the following two methods:

    Method 1: xcodebuild flags

    Pass these flags directly to your xcodebuild command:

    • -skipMacroValidation
    • -skipPackagePluginValidation

    Method 2: Xcode defaults

    Set these global defaults via the terminal:

    • com.apple.dt.Xcode IDESkipMacroFingerprintValidation
    • com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation
    xcodebuild -skipMacroValidation -skipPackagePluginValidation
    
    # Or via defaults
    defaults write com.apple.dt.Xcode IDESkipMacroFingerprintValidation -bool YES
    defaults write com.apple.dt.Xcode IDESkipPackagePluginFingerprintValidatation -bool YES
  9. Configure obfuscation using Compression techniques

    master

    Compression is a non-polymorphic technique (same input produces same output) used to reduce data size. Swift Confidential applies additional polymorphic routines to mask the compression algorithm's signature.

    Use the following YAML syntax to apply compression:

    compress using <#algorithm#>

    Supported algorithms:

    • lzfse: LZFSE compression algorithm.
    • lz4: LZ4 compression algorithm.
    • lzma: LZMA compression algorithm.
    • zlib: zlib compression algorithm.
    compress using lz4
  10. Configure Swift Confidential via YAML

    master

    Swift Confidential uses a confidential.yml (or .yaml) file to manage secret literals. The plugin automatically regenerates code whenever this file changes or during a clean build.

    Global Configuration Keys

    KeyTypeDescription
    algorithmString/ListDefault obfuscation algorithm. Use random for per-secret randomness.
    defaultAccessModifierStringDefault access level (internal, package, public). Default is internal.
    defaultNamespaceStringDefault namespace (e.g., create ObfuscatedLiterals).
    experimentalModeBooleanEnables experimental features (requires Swift 6).
    internalImportBooleanIf true, generates an internal (implementation-only) ConfidentialKit import.
    secretsListRequired. The list of secret definitions.

    Secret Definition Keys

    KeyTypeDescription
    nameStringRequired. The name of the generated Swift property.
    valueString/ListRequired. The plaintext value(s) to obfuscate.
    accessModifierStringOverrides defaultAccessModifier for this specific secret.
    algorithmString/ListOverrides algorithm for this specific secret.
    namespaceStringOverrides defaultNamespace for this specific secret.

    Example Configuration

    algorithm:
      - encrypt using aes-192-gcm
      - shuffle
    defaultNamespace: create ObfuscatedLiterals
    secrets:
      - name: apiKey
        value: 214C1E2E-A87E-4460-8205-4562FDF54D1C
        algorithm: random
      - name: trustedSPKIDigests
        value:
          - 7a6820614ee600bbaed493522c221c0d9095f3b4d7839415ffab16cbf61767ad
          - cf84a70a41072a42d0f25580b5cb54d6a9de45db824bbb7ba85d541b099fd49f
  11. Configure obfuscation using Encryption techniques

    master

    Encryption is a polymorphic technique (same input produces different output each run) used to secure data.

    Use the following YAML syntax to apply encryption:

    encrypt using <#algorithm#>

    Supported algorithms:

    • aes-128-gcm: AES in GCM mode with 128-bit key.
    • aes-192-gcm: AES in GCM mode with 192-bit key.
    • aes-256-gcm: AES in GCM mode with 256-bit key.
    • chacha20-poly: ChaCha20-Poly1305 algorithm.
    encrypt using aes-256-gcm
  12. Configure obfuscation using Randomization

    master

    Randomization is a polymorphic technique that shuffles data.

    Warning: This technique is best suited for secrets $\le$ 256 bytes. For larger secrets, the output size grows significantly (from 2N to 3N, or up to 9N on 64-bit platforms for data $>65,536$ bytes).

    Use the following YAML syntax to apply randomization:

    shuffle