Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
dhinakg committed Aug 18, 2024
1 parent 8ac5e02 commit 0680c2f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 17 deletions.
68 changes: 55 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,82 @@

AEA OTA/IPSW decryption

## Grabbing keys with `get_key.py`
## Prerequisites

Gets a key from the key URL embedded in an AEA's auth data blob.
- `get_key.py`
- Python 3.10+ (might work with older, but not tested)
- `requests`
- `pyhpke`
- `aastuff`
- macOS 13+
- macOS 14+ for HPKE support
- `aastuff_standalone`
- macOS 12+
- macOS 14+ for HPKE support

> [!NOTE]
> OTAs before iOS 18.0 beta 3 did not have embedded auth data; for these OTAs, you must use the key provided with your response. macOS is the exception.
## Building and Installing

### `get_key.py`

```shell
pip3 install -r requirements.txt
python3 get_key.py <path to AEA>
```

Note: it is highly recommended to use a virtual environment:
> [!NOTE]
> It is highly recommended to use a virtual environment:
>
> ```shell
> python3 -m venv .env # only needed once
> source .env/bin/activate
> pip3 install -r requirements.txt # only needed once
> ```
>
> On future runs, you only need to activate the virtual environment:
>
> ```shell
> source .env/bin/activate
> ```
### `aastuff`/`aastuff_standalone`
You can pass two options to the makefile:
- `DEBUG=1`: build debug (debug prints, no optimizations, debug information)
- `HPKE=1`: build with HPKE support (needs macOS 14.0+)
```shell
make [DEBUG=1] [HPKE=1]
```
## Grabbing keys with `get_key.py`

Unwrap the decryption key using the data embedded in an AEA's auth data blob.

> [!NOTE]
> OTAs before iOS 18.0 beta 3 did not have embedded auth data; for these OTAs, you must use the decryption key provided with your response. macOS is the exception and has always had embedded auth data.
```shell
python3 -m venv .env # only needed once
source .env/bin/activate
pip3 install -r requirements.txt # only needed once
source .env/bin/activate # if you used a virtual environment
python3 get_key.py <path to AEA>
```

## Decrypting an AEA

```shell
aea decrypt -i <path to AEA> -o <decrypted output file> -key-value 'base64:<key in base64>'
# or
./aastuff -i <path to AEA> -o <decrypted output folder> -d -k <key in base64>
# or, to use the network to grab the private key
./aastuff -i <path to AEA> -o <decrypted output folder> -d -n
```

For IPSWs, you will get the unwrapped file (ie. `090-34187-052.dmg.aea` will decrypt to `090-34187-052.dmg`).

For assets, you will get specially crafted AppleArchives (see next section).
For assets, you will get specially crafted Apple Archives (see next section).

## Extracting assets

Assets (including OTA updates) are constructed specially and cannot be extracted with standard (`aa`) tooling. They can be decrypted normally, which will result in an AppleArchive that is not extractable with `aa` (we will call these "asset archives"). `aastuff` must be used to extract them.
Assets (including OTA updates) are constructed specially and cannot be extracted with standard (`aa`) tooling. They can be decrypted normally, which will result in an Apple Archive that is not extractable with `aa` (we will call these "asset archives"). `aastuff` must be used to extract them.

```shell
# Decrypt if necessary
Expand Down Expand Up @@ -68,7 +110,7 @@ For now, both are built and used in the same way. Once `aastuff_standalone` is f

## Credits

- Siguza - auth data parsing strategy, AppleArchive extraction sample code
- Siguza - auth data parsing strategy, Apple Archive extraction sample code
- Nicolas - original HPKE code
- Snoolie - auth data parsing strategy
- Flagers - AppleArchive assistance
- Flagers - Apple Archive assistance
12 changes: 8 additions & 4 deletions src/aea.m
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ int fetchKey(AEAContext context, ExtractionConfiguration* config) {
return 1;
}

// Encapsulated symmetric key. This is what was used to encrypt the archive's encryption key. Also known as the shared secret.
NSData* encryptedRequest = [[NSData alloc] initWithBase64EncodedString:response[@"enc-request"] options:0];
if (!encryptedRequest) {
ERRLOG(@"Failed to decode encrypted request");
return 1;
}

// Wrapped archive encryption key. Also known as the message, encrypted data, or ciphertext.
NSData* wrappedKey = [[NSData alloc] initWithBase64EncodedString:response[@"wrapped-key"] options:0];
if (!wrappedKey) {
ERRLOG(@"Failed to decode wrapped key");
Expand All @@ -109,9 +111,10 @@ int fetchKey(AEAContext context, ExtractionConfiguration* config) {

DBGLOG(@"Key URL: %@", url);
DBGLOG(@"Response data: %@", response);
DBGLOG(@"Encrypted request: %@", encryptedRequest);
DBGLOG(@"Wrapped key: %@", wrappedKey);
DBGLOG(@"Encrypted request (encapsulated symmetric key): %@", encryptedRequest);
DBGLOG(@"Wrapped key (ciphertext): %@", wrappedKey);

// Receipient's private key. The receipient's public key is what was used to encrypt the encapsulated symmetric key.
NSData* privateKey = nil;
PrivateKeyFormat privateKeyFormat = PrivateKeyFormatAll;
if (config.unwrapKey) {
Expand Down Expand Up @@ -141,8 +144,9 @@ int fetchKey(AEAContext context, ExtractionConfiguration* config) {
}
}

DBGLOG(@"Private key: %@", privateKey);
DBGLOG(@"Private key (recepient's private key): %@", privateKey);

// The unwrapped encryption key. This is the data that was encrypted. Also known as the plaintext/cleartext.
NSData* unwrappedKey = [HPKEWrapper unwrapPrivateKey:privateKey format:privateKeyFormat encryptedRequest:encryptedRequest
wrappedKey:wrappedKey
error:&error];
Expand All @@ -151,7 +155,7 @@ int fetchKey(AEAContext context, ExtractionConfiguration* config) {
return 1;
}

DBGLOG(@"Unwrapped key: %@ (%@)", unwrappedKey, [unwrappedKey base64EncodedStringWithOptions:0]);
DBGLOG(@"Unwrapped key (cleartext): %@ (%@)", unwrappedKey, [unwrappedKey base64EncodedStringWithOptions:0]);

config.key = unwrappedKey;

Expand Down

0 comments on commit 0680c2f

Please sign in to comment.