# REALITY Implementation: Reference Comparison & Work Items

This document compares the shoes REALITY implementation against the reference implementations:
- **XTLS/REALITY** - The authoritative Go reference at https://github.com/XTLS/REALITY
- **sing-box/utls** - Go implementation used by sing-box (vendored at `/sing-box/vendor/github.com/metacubex/utls/reality.go`) - **NOTE: This is a modified fork with differences from original**

The shoes implementation is a **sans-I/O** model for rustls compatibility, located in `src/reality/`.

---

## Architecture Overview

### Reference Implementation (XTLS/REALITY)
- Integrated with Go's crypto/tls library
- Modifies TLS handshake in-place
- Uses goroutines for parallel dest connection and fallback
- Implements "mirror connection" pattern for transparent fallback
- **SessionId encryption: Always AES-GCM**

### sing-box/utls (Modified Fork)
- Based on XTLS/REALITY but with modifications
- **SessionId decryption: Uses `aesgcmPreferred()` to choose AES-GCM or ChaCha20** ← Different from original!
- Client side still always uses AES-GCM

### Shoes Implementation
- Sans-I/O design (state machine, no direct I/O)
- Separate client (`reality_client_connection.rs`) and server (`reality_server_connection.rs`) implementations
- Fallback handled at handler level (`tls_server_handler.rs:347`)
- Uses rustls-compatible API patterns
- **SessionId encryption: Always AES-GCM** ← Matches original XTLS/REALITY

---

## Critical Issues

### 1. **SessionId Cipher Mismatch with sing-box Server**  CRITICAL

**The Problem:**

| Implementation | SessionId Encryption (Client) | SessionId Decryption (Server) |
|---------------|------------------------------|------------------------------|
| XTLS/REALITY (original) | Always AES-GCM | Always AES-GCM |
| sing-box client | Always AES-GCM | N/A |
| sing-box server (utls) | N/A | **AES-GCM or ChaCha20** (based on `aesgcmPreferred`) |
| shoes client | Always AES-GCM | N/A |
| shoes server | N/A | Always AES-GCM |

**sing-box/utls added `aesgcmPreferred` check** (`reality.go` lines 393-398) that the original XTLS/REALITY doesn't have:
```go
// sing-box/utls modification - NOT in original XTLS/REALITY
if aesgcmPreferred(hs.clientHello.cipherSuites) {
    block, _ := aes.NewCipher(hs.AuthKey)
    aead, _ = cipher.NewGCM(block)
} else {
    aead, _ = chacha20poly1305.New(hs.AuthKey)  // Uses ChaCha20 if client prefers it
}
```

**Original XTLS/REALITY** (`/tmp/REALITY/tls.go` lines 236-237):
```go
// Always AES-GCM, no preference check
block, _ := aes.NewCipher(hs.c.AuthKey)
aead, _ := cipher.NewGCM(block)
```

**When Issues Manifest:**

| Scenario | Result |
|----------|--------|
| shoes client (ChaCha20 first) → sing-box server | **FAIL** - shoes encrypts with AES-GCM, sing-box decrypts with ChaCha20 |
| shoes client (AES first) → sing-box server | OK |
| sing-box client → shoes server | OK - sing-box always encrypts with AES-GCM |
| shoes ↔ shoes | OK - both use AES-GCM |
| shoes ↔ XTLS/REALITY original | OK - both use AES-GCM |

**Current Test Coverage Gap:**
All cipher suite tests in `tests/reality_integration.rs` use `add_singbox_client` (sing-box client → shoes server), which always works. No tests for shoes client with ChaCha20-first config → sing-box server.

**Fix Required:**
To be compatible with sing-box server's modified behavior, shoes client should:
1. Check if first cipher suite in ClientHello is AES-GCM
2. Use ChaCha20-Poly1305 for SessionId encryption if not AES-GCM preferred
3. This matches what sing-box server expects

**Files to modify:**
- `src/reality/reality_auth.rs` - Add cipher selection parameter to `encrypt_session_id`
- `src/reality/reality_client_connection.rs` - Pass cipher preference based on configured cipher suites

---

### 2. **Certificate Size Difference**  FIXED

**Reference:** 178 bytes minimal certificate with empty Subject/Issuer, serial 0, no SAN.

**shoes:** Now generates 176 bytes (~2 bytes smaller than reference).

**Fix applied:** Updated `generate_template_cert()` to use minimal rcgen params:
- Empty `subject_alt_names`
- Empty `distinguished_name`
- Serial number 0

No yasna needed - rcgen fully supports minimal certificates when properly configured.

---

### 3. **X25519MLKEM768 (Post-Quantum Hybrid) Not Supported**  MEDIUM

**Reference (`reality.go` lines 372-378):**
```go
for _, keyShare := range hs.clientHello.keyShares {
    if keyShare.group == X25519MLKEM768 && len(keyShare.data) == mlkem.EncapsulationKeySize768+32 {
        peerPub = keyShare.data[mlkem.EncapsulationKeySize768:]
        break
    }
}
```

**sing-box client (`reality_client.go` lines 134-143):** Explicitly filters OUT X25519MLKEM768:
```go
for _, extension := range uConn.Extensions {
    if ks, ok := extension.(*utls.KeyShareExtension); ok {
        ks.KeyShares = common.Filter(ks.KeyShares, func(share utls.KeyShare) bool {
            return share.Group != utls.X25519MLKEM768  // Removed!
        })
    }
}
```

**shoes:** Only handles X25519 key shares.

**Impact:**
- sing-box client removes X25519MLKEM768, so no immediate interop issue
- Future clients using post-quantum hybrid will fail against shoes server
- The X25519 portion must be extracted from the last 32 bytes of the hybrid key share

**Fix Required:**
1. Detect X25519MLKEM768 group (0x4588) in key shares
2. Extract X25519 public key from bytes `[mlkem.EncapsulationKeySize768:]` (last 32 bytes)
3. Continue with standard ECDH using extracted X25519 key

**Files to modify:**
- `src/reality/reality_util.rs` - `extract_client_public_key` function
- `src/reality/reality_server_connection.rs` - Key share parsing

---

## Lower Priority Issues

### 4. **Rate Limiting for Fallback Connections**  LOW

**Reference (`reality.go` lines 92-171):**
```go
type RealityLimitFallback struct {
    AfterBytes       uint64
    BytesPerSec      uint64
    BurstBytesPerSec uint64
}
```

**shoes:** No rate limiting on fallback connections.

**Impact:** Fallback connections can consume unlimited bandwidth, potentially allowing abuse.

**Files to modify:**
- `src/tls_server_handler.rs` - `reality_fallback_to_dest` function
- `src/config.rs` - Add rate limit config options

---

### 5. **Fallback Timing: Sequential vs Parallel Dest Connection**  LOW

**Reference:** Connects to dest immediately in parallel with ClientHello processing.

**shoes:** Connects to dest only after authentication fails.

**Impact:** Added latency on fallback that could theoretically be fingerprinted.

---

### 6. **Mirror Connection Pattern Not Implemented**  LOW

**Reference:** Mirrors client data to real server during handshake validation.

**shoes:** Simple bidirectional copy after fallback decision.

**Impact:** Advanced anti-fingerprinting feature not implemented.

---

## Correct Items 

### 7. **HMAC Certificate Signature**  CORRECT

Both compute HMAC-SHA512 over the Ed25519 public key and place full 64-byte result in signature field.

Client verification now correctly compares all 64 bytes of the HMAC-SHA512 signature.

### 8. **Timestamp Validation**  CORRECT

Both implementations validate with configurable `max_time_diff`.

### 9. **Version Validation**  CORRECT

Both validate against `min_client_version` and `max_client_version`.

### 10. **Short ID Validation**  CORRECT

Both check client's short_id against configured list.

### 11. **Fallback Mechanism**  IMPLEMENTED

Fallback triggered on `PermissionDenied` errors via `reality_fallback_to_dest`.

### 12. **TLS 1.3 Cipher Suite Negotiation**  CORRECT

shoes correctly negotiates TLS 1.3 cipher suites for the actual TLS connection (separate from SessionId encryption).

---

## Work Items Summary

| Priority | Issue | Effort | Status |
|----------|-------|--------|--------|
| **CRITICAL** | SessionId cipher mismatch with sing-box server | Medium | Needs fix for ChaCha20-first clients |
| **MEDIUM** | ~~Certificate size fingerprinting~~ | ~~Medium~~ |  FIXED - now 176 bytes (reference: 178) |
| **MEDIUM** | X25519MLKEM768 post-quantum support | Medium | Not blocking current interop |
| **LOW** | Rate limiting for fallback | Low | Security hardening |
| **LOW** | Parallel dest connection | Medium | Anti-fingerprinting enhancement |
| **LOW** | Mirror connection pattern | High | Advanced anti-fingerprinting |

---

## Test Gaps

1. **Missing:** shoes client with ChaCha20-first cipher config → sing-box server
2. **Missing:** Post-quantum (X25519MLKEM768) client → shoes server
3. **Existing tests pass** because sing-box client always uses AES-GCM for SessionId

---

## Reference Files

- XTLS/REALITY: `/tmp/REALITY/` (cloned)
- sing-box utls: `/sing-box/vendor/github.com/metacubex/utls/reality.go`
- sing-box client: `/sing-box/common/tls/reality_client.go`
- shoes reality: `/shoes/src/reality/`
