# Universal Asset Encryption - TODO

## ⚠️ CRITICAL: Runtime Decryptor Missing

This protection currently **ONLY encrypts** assets but does **NOT decrypt** them at runtime.
Apps protected with this will **NOT run** because they cannot access their resources.

---

## 🔴 What's Missing

### Runtime Decryptor Implementation

The protection needs code injected into the app that:

1. **Intercepts** resource loading APIs:
   - `NSBundle.main.path(forResource:ofType:)`
   - `UIImage(named:)`
   - `Data(contentsOf:)`
   - `NSData(contentsOfFile:)`
   - `String(contentsOfFile:)`

2. **Detects** encrypted files:
   - Check for magic header or encrypted file registry
   - Determine encryption key and IV

3. **Decrypts** content on-the-fly:
   - AES-256-CBC decryption
   - Return decrypted data to caller

4. **Caches** decrypted resources:
   - Keep decrypted data in memory
   - Avoid re-decryption on repeated access

---

## 💡 Implementation Options

### Option 1: Dylib Injection (RECOMMENDED)

**Pros:**
- Easier to implement
- Can be developed and tested separately
- Can be updated without recompiling

**Cons:**
- May fail with strict App Store signing
- Visible in app bundle

**Steps:**
1. Create `ShieldDecryptor.dylib` with Objective-C/Swift code
2. Implement method swizzling for resource APIs
3. Embed encryption key in dylib (obfuscated)
4. Modify Mach-O LC_LOAD_DYLIB to load the dylib
5. Update code signature

**Example Structure:**
```
shield-ios/
  decryptor/
    ShieldDecryptor.xcodeproj
    ShieldDecryptor/
      ShieldDecryptor.h
      ShieldDecryptor.m
      ResourceDecryptor.m
      MethodSwizzling.m
    build.sh
```

### Option 2: Native Code Injection

**Pros:**
- No visible dylib in bundle
- More stealthy
- Better App Store compatibility

**Cons:**
- Very complex to implement
- Requires Mach-O manipulation
- Hard to debug

**Steps:**
1. Generate Objective-C decryptor code
2. Compile to `.o` object file
3. Link into main executable using `ld`
4. Patch Mach-O to add new section
5. Update code signature

### Option 3: Source-Level Integration (FUTURE)

**Pros:**
- Most transparent
- Best performance
- App Store compatible

**Cons:**
- Requires user to add code to their project
- Not automatic like iXGuard

**Steps:**
1. Provide Swift/ObjC framework
2. User adds to their project
3. Protection injects configuration
4. User's code handles decryption

---

## 🎯 Recommended Approach

**Phase 1: Dylib Injection (Quick Win)**
- Implement basic dylib with method swizzling
- Support common resource types (images, plists, JSON)
- Test with sample apps
- **Timeline:** 1-2 days

**Phase 2: Enhanced Decryptor**
- Add caching layer
- Support all file types
- Optimize performance
- **Timeline:** 2-3 days

**Phase 3: Native Injection**
- Research Mach-O code injection
- Implement for production use
- Test with real apps
- **Timeline:** 1-2 weeks

---

## 📝 Implementation Notes

### Key Storage
- Encryption key must be embedded in decryptor
- Obfuscate key using:
  - String encryption
  - Split across multiple locations
  - XOR with constants
  - Generate from app signature

### File Detection
- Add magic header to encrypted files: `SHLD` + version
- Or maintain registry file: `.shield_encrypted`
- Check file signature before decryption attempt

### Error Handling
- Graceful fallback if decryption fails
- Log errors for debugging
- Don't crash the app

### Performance
- Decrypt on first access, cache in memory
- Use background queue for large files
- Consider lazy decryption for unused resources

---

## 🔗 References

### iXGuard Implementation (Conceptual)
iXGuard uses method swizzling to intercept resource loading:

```objc
@implementation UIImage (ShieldDecryptor)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(imageNamed:);
        SEL swizzledSelector = @selector(shield_imageNamed:);

        Method originalMethod = class_getClassMethod(class, originalSelector);
        Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

        method_exchangeImplementations(originalMethod, swizzledMethod);
    });
}

+ (UIImage *)shield_imageNamed:(NSString *)name {
    // Check if encrypted
    NSString *imagePath = [[NSBundle mainBundle] pathForResource:name ofType:@"png"];
    NSData *data = [NSData dataWithContentsOfFile:imagePath];

    if ([self isEncrypted:data]) {
        // Decrypt
        NSData *decrypted = [self decryptData:data];
        return [UIImage imageWithData:decrypted];
    }

    // Call original
    return [self shield_imageNamed:name];
}

@end
```

### Dylib Loading
Modify Mach-O to add dylib:

```bash
install_name_tool -add_rpath @executable_path ShieldDecryptor.dylib MyApp
```

Or use LIEF:

```python
import lief

macho = lief.parse("MyApp")
macho.add_library("@rpath/ShieldDecryptor.dylib")
macho.write("MyApp_modified")
```

---

## ✅ Success Criteria

- [ ] Decryptor dylib compiles successfully
- [ ] Method swizzling works for UIImage, NSBundle, Data
- [ ] Encrypted assets decrypt correctly
- [ ] App runs normally with encrypted resources
- [ ] Performance overhead < 10% on resource loading
- [ ] Works on iOS Simulator and real device
- [ ] Compatible with code signing
- [ ] No crashes or resource loading failures

---

**Status:** Not Started
**Priority:** High (blocking feature)
**Assigned:** TBD
**Last Updated:** 2025-12-29
