How vphone-cli Handles AEA-Encrypted DMGs: Detection and Decryption
vphone-cli detects AEA-encrypted DMGs by checking for the "AEA1" magic bytes, then uses the external ipsw utility to decrypt Cryptex images in-place during offline restore operations.
The vphone-cli tool provides a streamlined workflow for managing iPhone virtual machines, including handling Apple Encrypted Archive (AEA) disk images that appear in iOS restore bundles. When performing offline restores, the CLI must decrypt AEA-protected DMGs—such as SystemOS.dmg.aea—to plain DMG format before the VM can mount them. This article examines the Swift implementation that automates this decryption process.
Detecting AEA-Encrypted DMGs
Before attempting decryption, vphone-cli validates whether a disk image actually uses AEA encryption.
Magic Byte Validation
The detection logic resides in sources/VPhoneCore/VPhoneRestoreOps.swift. The isAEAEncrypted(_:) method reads the first four bytes of the file and compares them against the AEA1 magic signature 0x41454131 (ASCII "AEA1"):
// VPhoneRestoreOps.swift, lines 41-47
static func isAEAEncrypted(_ url: URL) throws -> Bool {
let handle = try FileHandle(forReadingFrom: url)
defer { handle.closeFile() }
guard let data = handle.readData(ofLength: 4) else { return false }
return data == Data([0x41, 0x45, 0x41, 0x31]) // "AEA1"
}
This lightweight check prevents unnecessary processing of already-decrypted DMG files and ensures the tool only attempts decryption on valid Apple Encrypted Archives.
Decryption Process
When the --offline flag is passed to the restore command, vphone-cli orchestrates the decryption of all .dmg.aea files within the restore bundle.
Offline Restore Workflow
The decryptAEAImages(inRestoreDir:) method scans the restore directory for *.dmg.aea files and processes each one sequentially. According to the source code in VPhoneRestoreOps.swift (lines 49-68), the implementation:
- Locates all AEA-encrypted files in the specified directory
- Validates each file using the magic byte check
- Invokes the external ipsw utility to perform decryption
- Swaps the encrypted file with the decrypted output
- Verifies the result is no longer encrypted
If the final verification step detects that the file still contains AEA1 magic bytes, the method throws VPhoneRestoreError.aeaStillEncrypted, preventing corrupted restores.
The ipsw Integration
The actual cryptographic work is delegated to the ipsw command-line tool. vphone-cli uses VPhoneProcessRunner.runStreaming to execute:
// VPhoneRestoreOps.swift, lines 56-58
let code = try VPhoneProcessRunner.runStreaming(
URL(fileURLWithPath: "/usr/bin/env"),
["ipsw", "fw", "aea", "-o", dir.path, aea.path])
The ipsw fw aea command extracts the decryption key from cached SHSH blobs and writes the decrypted DMG adjacent to the encrypted source. The Swift code then atomically removes the .aea file and renames the decrypted output to take its place, ensuring the restore bundle contains only readable disk images.
Integration with the Restore Flow
The decryption functionality is exposed through the CLI interface defined in sources/vphone-cli/VPhoneRestoreCLI.swift. When a user initiates a restore with the offline flag:
vphone-cli restore MyVM --offline
The run() method (lines 49-62) locates the restore directory, prints a status message indicating decryption is in progress, and invokes decryptAEAImages(inRestoreDir:) before handing control to the pmd3 utility that writes firmware to the virtual machine. This sequencing ensures that Cryptex images are decrypted before the VM attempts to boot from them.
Why AEA Decryption Is Required
Modern iOS restore bundles ship Cryptex system images—such as SystemOS.dmg.aea and Cryptex1.dmg.aea—in encrypted format. The virtual machine's boot process requires unencrypted DMG files to mount these volumes.
During online restores, a connected iOS device can provide fresh SHSH blobs for decryption. However, offline restores (performed without a connected device) rely on cached blobs and require pre-decryption of these assets. The vphone-cli implementation bridges this gap by programmatically orchestrating the ipsw tool's AEA subcommand, enabling fully autonomous restore workflows without hardware dependencies.
Practical Code Examples
Detecting AEA Encryption in Swift
import Foundation
import VPhoneCore
let dmgURL = URL(fileURLWithPath: "/path/to/SystemOS.dmg.aea")
do {
let isEncrypted = try VPhoneRestoreOps.isAEAEncrypted(dmgURL)
print(isEncrypted ? "AEA encryption detected" : "File is already decrypted")
} catch {
print("Failed to read file: \(error)")
}
Decrypting an Entire Restore Bundle
import Foundation
import VPhoneCore
let restoreDir = URL(fileURLWithPath: "/path/to/iPhone14_2_Restore")
do {
try VPhoneRestoreOps.decryptAEAImages(inRestoreDir: restoreDir)
print("Decryption complete - all DMGs are ready for restore")
} catch VPhoneRestoreError.aeaStillEncrypted {
print("Error: Decryption failed, files remain encrypted")
} catch {
print("Decryption workflow failed: \(error)")
}
Shell Script Equivalents
The repository includes helper scripts (cfw_install.sh, cfw_install_dev.sh, cfw_install_exp.sh) that perform equivalent operations using shell commands. These scripts extract AEA keys via ipsw fw aea --key and invoke the external aea binary, mirroring the Swift implementation's logic for custom firmware installation scenarios.
Summary
- vphone-cli identifies AEA-encrypted DMGs by checking for the
AEA1magic bytes at file offset 0 usingisAEAEncrypted(_:)inVPhoneRestoreOps.swift. - Decryption occurs during offline restores via
decryptAEAImages(inRestoreDir:), which iterates restore bundles and invokes the externalipsw fw aeacommand. - The
--offlineflag inVPhoneRestoreCLI.swifttriggers decryption beforepmd3handles the actual firmware write, ensuring VM compatibility with Cryptex images. - Failed decryptions raise
VPhoneRestoreError.aeaStillEncryptedafter verification to prevent boot failures. - Shell script implementations in
cfw_install*.shprovide alternative entry points for the same decryption workflow.
Frequently Asked Questions
How does vphone-cli know if a DMG is AEA-encrypted?
The tool reads the first four bytes of the file and compares them against the hexadecimal sequence 0x41454131 (representing the ASCII string "AEA1"). This check is performed by the isAEAEncrypted(_:) method in VPhoneRestoreOps.swift, which returns a boolean indicating encryption status without reading the entire file into memory.
What happens if AEA decryption fails during an offline restore?
If the decryption process completes but the output file still contains AEA1 magic bytes, vphone-cli throws VPhoneRestoreError.aeaStillEncrypted and halts the restore operation. This prevents the system from attempting to boot a virtual machine using encrypted disk images that the hypervisor cannot mount.
Why does vphone-cli use the external ipsw tool instead of native Swift decryption?
The ipsw utility handles the complex cryptographic operations required to extract decryption keys from cached SHSH blobs and perform AES decryption on AEA archives. By shelling out to this established tool via VPhoneProcessRunner.runStreaming, vphone-cli avoids reimplementing Apple's proprietary encryption protocols while maintaining compatibility with evolving iOS firmware formats.
Can I decrypt AEA DMGs manually without using the Swift code?
Yes. The repository includes shell scripts (cfw_install.sh and variants) that demonstrate manual decryption using the ipsw fw aea command and the standalone aea binary. These scripts extract the necessary keys and decrypt Cryptex DMGs independently, providing a command-line alternative to the Swift implementation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →