Metadata-Version: 2.4
Name: upk-tool
Version: 0.1.1
Summary: Inspect, extract, and create UGREEN NAS .upk package files
Project-URL: Homepage, https://github.com/fuho/upk-tool
Project-URL: Issues, https://github.com/fuho/upk-tool/issues
Author-email: fuho <ondrej.dolejsi@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: firmware,nas,package,ugreen,upk
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: System :: Archiving :: Packaging
Classifier: Topic :: Utilities
Requires-Python: >=3.8
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Provides-Extra: signing
Requires-Dist: cryptography>=3.0; extra == 'signing'
Description-Content-Type: text/markdown

# upk-tool

Inspect, extract, and create **UGREEN NAS `.upk` package files** (UGREEN-PKG-V2-FORMAT).

## What is a .upk file?

`.upk` files are application packages used by UGREEN NAS devices. They contain:

- **Cryptographic signatures** (RSA-2048) for file integrity and authenticity
- **Public keys** for signer and manufacturer verification
- **App icon** (PNG)
- **App payload** (gzip → tar → XZ → tar with app binaries, configs, web UI)
- **Hash chain** for additional integrity verification

### Format structure

```
UGREEN-PKG-V2-FORMAT
filesig:344:<base64 RSA signature>
userpub:392:<base64 DER public key>
usersig:344:<base64 RSA signature>
midpub:392:<base64 DER public key>
midsig:344:<base64 RSA signature>
ico:31350:<raw PNG binary>
ugb:15608334:<gzip compressed tar>
obj2:10204:<hex hash chain>
```

Each field follows the pattern `key:length:value` where `length` is the byte count of `value`.

## Installation

```bash
pip install upk-tool
```

For signing support:
```bash
pip install upk-tool[signing]
```

## Usage

### Inspect a .upk file

```bash
upk-tool verify firmware.upk
```

Output:
```
File: firmware.upk
Fields: 8
  filesig: 344 bytes
  userpub: 392 bytes
  usersig: 344 bytes
  midpub: 392 bytes
  midsig: 344 bytes
  ico: 31350 bytes
  ugb: 15608334 bytes
  obj2: 10204 bytes

  ugb contents (gzip tar): 2 entries
    uninstall.sh (657 bytes)
    com.ugreen.comic.ugb (15602856 bytes)
    -> com.ugreen.comic.ugb: XZ -> tar with 64 files

Signature verification:
  filesig: 256 bytes (RSA-2048)
  usersig: 256 bytes (RSA-2048)
  midsig: 256 bytes (RSA-2048)
  userpub: 294 bytes DER
  midpub: 294 bytes DER
```

### Extract a .upk file

```bash
upk-tool extract firmware.upk -o extracted/
```

This will:
1. Save all raw fields to the output directory
2. Create `metadata.json` with field metadata
3. Decompress the `ugb` payload (gzip → tar)
4. Decompress inner `.ugb` files (XZ → tar)
5. Extract the final app contents

Directory structure:
```
extracted/
├── metadata.json
├── ico.bin
├── ugb.bin
└── ugb_contents/
    ├── uninstall.sh
    ├── com.ugreen.app.ugb
    ├── com.ugreen.app_files.tar
    └── com.ugreen.app_app/
        ├── sbin/
        │   └── my_service
        ├── config.json
        ├── www/
        │   └── assets/
        └── ...
```

### Create a .upk file

```bash
upk-tool create ./my_app/ -o my_app.upk --icon icon.png --name myapp
```

Options:
- `--icon` - PNG icon file (optional, uses 1x1 placeholder if omitted)
- `--name` - App name used in the package (default: `app`)
- `--uninstall` - Custom uninstall script (optional)
- `--user-key` - RSA private key for user signing (PEM format)
- `--mfg-key` - RSA private key for manufacturer signing (PEM format)

### Create a signed .upk file

```bash
# Generate keys (for testing)
openssl genrsa -out user_key.pem 2048
openssl genrsa -out mfg_key.pem 2048

# Create signed package
upk-tool create ./my_app/ \
    -o my_app.upk \
    --icon icon.png \
    --name myapp \
    --user-key user_key.pem \
    --mfg-key mfg_key.pem
```

> **Note**: Without real UGREEN private keys, the package will have valid structure but signatures won't verify on actual hardware.

## ⚠️ Known Limitations: Package Signing

**This tool cannot create packages that will install on UGREEN NAS devices without UGREEN's private signing keys.**

### How UGREEN Package Signing Works

UGREEN uses a dual-signature RSA-2048 system:

1. **filesig** - RSA-2048 signature of the entire package content
2. **userpub/usersig** - Signer's public key and signature (developer/3rd party)
3. **midpub/midsig** - Manufacturer's public key and signature (UGREEN)

The NAS validates these signatures cryptographically:
```
1. Hash package content → hash_A
2. Decrypt signature with embedded public key → hash_B
3. Verify hash_A == hash_B
```

**Any modification to the package content (even 1 byte) invalidates the signature.** This is by design - it prevents unauthorized packages from being installed.

### Why We Can't Sign Packages

Without UGREEN's private RSA keys, we cannot produce valid signatures. The tool generates dummy signatures (all zeros) for structural completeness, but these will fail validation on actual hardware.

### Potential Workarounds (Unverified)

If you're interested in running custom packages on your UGREEN NAS, here are some approaches that might work:

1. **Developer/Debug Mode** - Some NAS devices have a setting to allow unsigned packages. Check your UGREEN admin panel or SSH into the NAS and look for config settings.

2. **Add Your Own Public Key** - If you have root access to the NAS, you could potentially:
   - Generate your own RSA-2048 keypair
   - Add your public key to the NAS's trusted keyring
   - Sign packages with your private key
   - **We're very interested in hints about where UGREEN stores trusted keys on the NAS filesystem!**

3. **Patch Package Validation** - With SSH/root access, you might be able to:
   - Locate the package validation code on the NAS
   - Modify it to skip signature checks or accept custom keys
   - **Risky and may void warranty**

4. **Contact UGREEN** - If you're developing legitimate apps for their platform, they might provide developer keys or a signing service.

### What This Tool CAN Do

✅ **Extract and analyze** existing UGREEN packages  
✅ **Inspect package structure** and signatures  
✅ **Decompress all layers** (gzip, XZ, tar)  
✅ **Create structurally valid** .upk packages  
✅ **Modify extracted packages** (then repack - but signatures will be invalid)  
❌ **Create installable packages** without UGREEN's private keys  

### We Need Your Help!

If you have:
- Information about UGREEN's signing process
- Access to a UGREEN NAS with developer mode
- Knowledge of where trusted keys are stored
- Ideas for bypassing package validation safely
- **Any hints at all!**

Please open an issue or submit a PR. We're very interested in making custom package installation possible for the UGREEN community.

## Python API

```python
from upk_tool import parse_upk, extract_upk, create_upk, verify_upk

# Parse and inspect
fields = parse_upk("firmware.upk")
print(fields.keys())  # ['filesig', 'userpub', 'usersig', ...]

# Extract
extract_upk("firmware.upk", "output_dir/")

# Create
create_upk(
    app_dir="./my_app/",
    output_path="output.upk",
    icon_path="icon.png",
    app_name="myapp",
)

# Verify/inspect
verify_upk("firmware.upk")
```

## Development

```bash
# Clone and install in development mode
git clone https://github.com/anomalyco/oc_analyze_ugreen_upk_package_file.git
cd oc_analyze_ugreen_upk_package_file
pip install -e ".[dev]"

# Run tests
pytest

# Build package
python -m build

# Upload to PyPI
twine upload dist/*
```

## License

MIT
