Skip to content

Obfuscated 2.1.0

Latest

Choose a tag to compare

@tomisacat tomisacat released this 14 Jun 09:36
· 1 commit to main since this release

Obfuscated 2.1.0

Obfuscated 2.1.0 extends #Obfuscated beyond strings to Int, Bool, Data, and enums. This is an additive minor release — existing string macro usage, built-in methods, and custom step wiring are unchanged.

Requirements

  • macOS 15+, iOS 14+, tvOS 14+, watchOS 7+, macCatalyst 14+
  • Swift 6.2+
  • Xcode 16+ (macro plugin support)

Installation

Add Obfuscated via Swift Package Manager:

dependencies: [
    .package(url: "https://github.com/tomisacat/Obfuscated.git", from: "2.1.0"),
],
targets: [
    .target(
        name: "<YourAppTarget>",
        dependencies: ["Obfuscated"]
    ),
]

For an Xcode app target, use File → Add Package Dependencies and enter https://github.com/tomisacat/Obfuscated.git.

Products

Product Use when
Obfuscated Default — built-in methods only; #Obfuscated via ObfuscatedMacros
ObfuscatedCore Direct pipeline access, tests, or custom step libraries
ObfuscatedMacroSupport Building a user-owned macro plugin with custom ObfuscationStep types

Highlights

Typed value obfuscation

#Obfuscated now accepts compile-time literals for multiple types and returns ordinary values at runtime — no wrapper types, no manual decode:

Type Example
String #Obfuscated("secret", methods: [...])
Int #Obfuscated(443, methods: [...])
Bool #Obfuscated(true, methods: [...])
Data #Obfuscated([0xDE, 0xAD], methods: [...])
Enum case #Obfuscated(Environment.production, methods: [...]) — requires CaseIterable
RawRepresentable #Obfuscated(1, as: Color.self, methods: [...])
let port: Int = #Obfuscated(443, methods: [.xor(key: 0x11)])
let enabled: Bool = #Obfuscated(true, methods: [.xor(key: 1)])
let token: Data = #Obfuscated([0xDE, 0xAD, 0xBE, 0xEF], methods: [.xor(key: 0x5A)])

enum Environment: CaseIterable { case production, staging }
let env: Environment = #Obfuscated(Environment.production, methods: [.xor(key: 0x3C)])

enum Role: String { case admin, guest }
let role: Role = #Obfuscated("admin", as: Role.self, methods: [.xor(key: 0x2A)])

Enum semantics:

  • Type.case obfuscates the case name as UTF-8. Requires CaseIterable and Sendable. Applies to any CaseIterable enum — even when it also has an Int or String raw value.
  • as: Type.self obfuscates the raw value (Int → 8-byte big-endian Int64; String → UTF-8). Requires RawRepresentable. Use when you want the stored raw value hidden.
  • Both forms are valid when an enum conforms to CaseIterable and RawRepresentable: #Obfuscated(Color.red, ...) hides "red"; #Obfuscated(1, as: Color.self, ...) hides 1.
  • Enums without a raw value (e.g. Environment) only support the Type.case form.

See README — Limitations for the full caveat list.

All types share the same obfuscation method pipeline (XOR, crypto, custom steps, etc.) after per-type serialization to plaintext bytes.

New public types

Type Role
ObfuscatedValue Protocol for serializing values to/from plaintext bytes before/after the pipeline
ObfuscatedEnumSupport CaseIterable case lookup by decoded case name
ObfuscatedRawRepresentableSupport Encode/decode helpers for RawRepresentable raw values

Built-in ObfuscatedValue conformances: String, Int, Bool, Data.

Re-exported from Obfuscated as public typealias ObfuscatedValue.

Pipeline and runtime extensions

API Role
ObfuscationPipeline.encode(bytes:methods:) Byte-level encode entry point
ObfuscationPipeline.encode<T: ObfuscatedValue>(_:methods:) Generic value encode
ObfuscationPipeline.decodeBytes(_:methods:) Reverse pipeline to plaintext bytes
ObfuscationPipeline.decode<T: ObfuscatedValue>(_:methods:as:) Generic value decode
ObfuscatedRuntime._decode(bytes:methods:material:as:) Typed runtime decode for macro expansions
ObfuscatedRuntime._decodeRawRepresentable(...) Raw-representable enum decode
ObfuscatedRuntime._decodeCaseIterable(...) Case-name enum decode

Existing ObfuscationPipeline.encode(_:methods:) / decode(_:methods:) -> String and ObfuscatedRuntime._decode(bytes:methods:material:) -> String are unchanged.

Demo updates

The demo app adds a Typed Values section covering Int, Bool, Data, CaseIterable enum cases, and RawRepresentable enums. ObfuscatedDemoKit mirrors the new macro overloads.

Migration from 2.0.0

  1. Typical app (strings only) — bump the dependency and rebuild:

    .package(url: "https://github.com/tomisacat/Obfuscated.git", from: "2.1.0")

    No source changes expected.

  2. Adopting typed values — use the new overloads where compile-time literals fit your use case. Variables and runtime expressions are still not supported.

  3. Custom macro plugin authors — rebuild your plugin. If you exhaustively switch on ObfuscatedMacroError, add cases for missingValueLiteral and invalidTypeExpression.

  4. Pin to 2.0.0 if you are not ready to upgrade:

    .package(url: "https://github.com/tomisacat/Obfuscated.git", exact: "2.0.0")

Unchanged from 2.0.0

  • String #Obfuscated overload, expansion shape, and default plugin (ObfuscatedMacros)
  • All built-in and custom obfuscation methods
  • ObfuscationMethod, ObfuscationError, and CryptoMaterial shapes
  • Static string interpolation (\("...") literals folded at compile time)
  • Custom step setup via ObfuscationStep and user-owned macro plugins
  • Platform and Swift version requirements

Limitations

See also the canonical list in README — Limitations.

  • Compile-time literals only — not variables or runtime expressions
  • Enum cases via Type.case require CaseIterable and Sendable; associated values are not supported
  • Type.case works for any CaseIterable enum, including Int- or String-backed enums that also conform to RawRepresentable — it obfuscates the case name, not the raw value
  • When an enum is both CaseIterable and RawRepresentable, choose the overload by what you want hidden: #Obfuscated(Color.red, ...) → name "red"; #Obfuscated(1, as: Color.self, ...) → raw value 1
  • Enums without RawRepresentable (e.g. Environment.production) only support the Type.case form

Documentation

Testing

60 unit tests cover encode/decode round-trips, typed values (ObfuscatedValueTests), built-in and custom step pipelines, macro parsing, and expansion. CI runs swift test and demo app builds on every push and pull request to main.

License

MIT License — see LICENSE.


Tag: 2.1.0