← Back to Home

PSTN2 Protocol Specification v1.0

PSTN2 Protocol Specification v1.0

Status: Draft Last Updated: 2025-11-30 Authors: Nick Holland, Comms Council UK

Table of Contents

  1. Introduction
  2. Architecture Overview
  3. Core Concepts
  4. Protocol Messages
  5. Authentication
  6. Routing
  7. Encryption
  8. Emergency Services
  9. Directory Service
  10. Error Handling
  11. Security Considerations
  12. Implementation Requirements

1. Introduction

1.1 Purpose

PSTN2 is a distributed telecommunications protocol designed to provide:

1.2 Design Principles

  1. Distributed Architecture: No central authority or single point of failure
  2. Backward Compatible: Falls back to traditional PSTN when needed
  3. Privacy First: Minimal data sharing, maximum encryption
  4. Real-time Performance: Sub-100ms authentication, sub-1s call setup
  5. Simplicity: Easy to implement and deploy
  6. Eventual Consistency: Directory data propagates over time

1.3 Terminology


2. Architecture Overview

2.1 System Components

┌──────────────┐         ┌──────────────┐         ┌──────────────┐
│   CP1 (UK)   │◄───────►│   CP2 (UK)   │◄───────►│   CP3 (US)   │
│              │         │              │         │              │
│ • Auth API   │         │ • Auth API   │         │ • Auth API   │
│ • Routing    │         │ • Routing    │         │ • Routing    │
│ • Directory  │         │ • Directory  │         │ • Directory  │
│ • Emergency  │         │ • Emergency  │         │ • Emergency  │
└──────┬───────┘         └──────┬───────┘         └──────┬───────┘
       │                        │                        │
       └────────────────────────┼────────────────────────┘
                                │
                    ┌───────────▼───────────┐
                    │   Directory Service   │
                    │  (Eventual Consistency)│
                    └───────────────────────┘

2.2 Communication Flow

  1. Directory Lookup: Find CP hosting destination number
  2. Authentication: Verify caller identity with originating CP
  3. Routing: Discover connection details for direct media
  4. Encryption: Exchange keys for secure media
  5. Media: Establish direct peer-to-peer connection
  6. Emergency: Query real-time location if emergency call

2.3 Network Requirements


3. Core Concepts

3.1 Identifiers

3.1.1 Phone Numbers

3.1.2 RCPID (Range-CP-ID)

3.1.3 Call Reference

3.2 Timestamps

3.3 Cryptographic Requirements

3.3.1 Key Pairs

3.3.2 Signatures


4. Protocol Messages

4.1 Message Format

All messages are JSON with UTF-8 encoding.

Common Fields:

{
  "messageId": "uuid-v4",
  "timestamp": "ISO-8601",
  "version": "1.0",
  "requestingCP": "RCPID",
  "signature": "base64-encoded-signature"
}

4.2 HTTP Headers

Required Headers:

Content-Type: application/json; charset=utf-8
User-Agent: PSTN2-Client/{version} ({implementation})
X-PSTN2-Version: 1.0
X-PSTN2-CP-ID: {RCPID}
Authorization: Bearer {JWT-token}  (optional, for token pool)

4.3 Response Codes

Success:

Client Errors:

Server Errors:


5. Authentication

5.1 Option 1: Direct Query

Direct real-time query to originating CP.

5.1.1 Verification Request

Endpoint: POST /pstn2/v1/auth/verify

Request:

{
  "messageId": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2025-11-30T21:30:00.000Z",
  "version": "1.0",
  "requestingCP": "CP1-UK-0002",
  "callerID": "+441234567890",
  "calledID": "+447700900123",
  "callReference": "0d1f2a3b-4c5d-4e6f-8a7b-9c0d1e2f3a4b",
  "signature": "base64-signature"
}

Response (200 OK):

{
  "verified": true,
  "callReference": "0d1f2a3b-4c5d-4e6f-8a7b-9c0d1e2f3a4b",
  "callerName": "John Smith",
  "callerOrg": "ACME Corp",
  "callPurpose": "Account verification",
  "trustLevel": "verified",
  "branding": {
    "displayName": "ACME Support",
    "logo": "https://cdn.acme.com/logo.png",
    "backgroundColor": "#0066cc",
    "textColor": "#ffffff"
  },
  "timestamp": "2025-11-30T21:30:00.050Z",
  "signature": "base64-signature"
}

Response (404 Not Found):

{
  "verified": false,
  "callReference": "0d1f2a3b-4c5d-4e6f-8a7b-9c0d1e2f3a4b",
  "error": "call_not_found",
  "message": "No matching call found",
  "timestamp": "2025-11-30T21:30:00.050Z"
}

5.1.2 Porting Chain Resolution

If number is ported, originating CP MUST return porting information:

Response (200 OK):

{
  "verified": false,
  "ported": true,
  "newRcpid": "CP1-UK-0003",
  "portedAt": "2025-10-15T10:00:00.000Z",
  "callReference": "0d1f2a3b-4c5d-4e6f-8a7b-9c0d1e2f3a4b"
}

A ported response is a successful (HTTP 200) response, not an error. On receiving "ported": true, the client MUST re-query the directory for the new range holder identified by newRcpid and retry the verification against that CP. Maximum 5 hops.

5.2 Option 2: Token Pool

Shared token repository for reduced query load.

5.2.1 Create Token

Endpoint: POST /pstn2/v1/auth/tokens

Request:

{
  "messageId": "uuid",
  "timestamp": "ISO-8601",
  "originatingCP": "CP1-UK-0001",
  "callerID": "+441234567890",
  "calledID": "+447700900123",
  "callReference": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "ttl": 30,
  "signature": "base64"
}

Response (201 Created):

{
  "tokenId": "TK-abc123XYZ789defG",
  "expiresAt": "2025-11-30T21:30:30.000Z",
  "callReference": "7c9e6679-7425-40de-944b-e07fc1f90ae7"
}

5.2.2 Verify Token

Endpoint: GET /pstn2/v1/auth/tokens/{tokenId}

Response (200 OK):

{
  "tokenId": "TK-abc123XYZ789defG",
  "originatingCP": "CP1-UK-0001",
  "callerID": "+441234567890",
  "calledID": "+447700900123",
  "callReference": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "verified": true,
  "branding": {...},
  "expiresAt": "2025-11-30T21:30:30.000Z"
}

5.2.3 Token Format


6. Routing

Direct peer-to-peer routing discovery.

6.1 Routing Request

Endpoint: POST /pstn2/v1/routing/request

Request:

{
  "messageId": "uuid",
  "timestamp": "ISO-8601",
  "requestingCP": "CP1-UK-0001",
  "callerID": "+441234567890",
  "destinationNumber": "+447700900123",
  "callReference": "9b2f8c44-1d3e-4f6a-8b5c-2e7d9a0f4c11",
  "mediaCapabilities": {
    "codecs": ["opus", "g722", "pcmu"],
    "encryption": ["srtp-aes256", "srtp-aes128"],
    "video": false,
    "maxBandwidth": 128000
  },
  "publicKey": "base64-ed25519-public-key",
  "signature": "base64"
}

Response (200 OK):

{
  "accepted": true,
  "callReference": "9b2f8c44-1d3e-4f6a-8b5c-2e7d9a0f4c11",
  "connectionDetails": {
    "fqdn": "media.cp2.example.com",
    "ipv4": "203.0.113.42",
    "ipv6": "2001:db8::42",
    "port": 5060,
    "protocol": "udp",
    "publicKey": "base64-ed25519-public-key"
  },
  "agreedCapabilities": {
    "codecs": ["opus"],
    "encryption": ["srtp-aes256"],
    "video": false
  },
  "timestamp": "ISO-8601",
  "signature": "base64"
}

Response (503 Service Unavailable):

{
  "accepted": false,
  "reason": "capacity_exceeded",
  "fallbackToTraditional": true,
  "timestamp": "ISO-8601"
}

6.2 Media Codecs

Required Support:

Optional Support:

6.3 Encryption

Required Support:

Key Exchange:


7. Encryption

7.1 Key Exchange

Ed25519 is a signature-only algorithm and cannot perform key agreement. Media encryption keys are therefore NOT derived from the Ed25519 identity keys. Instead, session keys are established by the DTLS-SRTP handshake (RFC 5764) using X25519 ECDHE inside DTLS. The Ed25519 identity key exchanged during routing negotiation is used to authenticate the peer's DTLS certificate fingerprint, binding the media channel to the signaling identity.

Identity Public Key Format:

{
  "algorithm": "ed25519",
  "publicKey": "base64-encoded-32-bytes",
  "fingerprint": "sha256:hexadecimal"
}

7.2 Media Encryption

Required:

Key Derivation:

7.3 Signaling Encryption

Required:


8. Emergency Services

8.1 Location Query

Endpoint: POST /pstn2/v1/emergency/location

Request:

{
  "messageId": "uuid",
  "timestamp": "ISO-8601",
  "requestingPSAP": "UK-999-LONDON-01",
  "callerID": "+441234567890",
  "callReference": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "signature": "base64"
}

Response (200 OK):

{
  "callReference": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
  "location": {
    "latitude": 51.5074,
    "longitude": -0.1278,
    "accuracy": 15,
    "altitude": 42.5,
    "source": "gps"
  },
  "address": {
    "street": "10 Downing Street",
    "city": "London",
    "postcode": "SW1A 2AA",
    "country": "GB"
  },
  "additionalInfo": {
    "cellTowerId": "234-10-12345-67890",
    "wifiAccessPoints": ["AA:BB:CC:DD:EE:FF"],
    "lastUpdated": "2025-11-30T21:30:00.000Z"
  },
  "timestamp": "ISO-8601",
  "signature": "base64"
}

8.2 Location Sources

Priority (highest to lowest):

  1. GPS: Most accurate (±5-15m)
  2. WiFi Triangulation: Good accuracy (±20-50m)
  3. Cell Tower: Moderate accuracy (±100-1000m)
  4. User-Provided: Entered by user
  5. Billing Address: Fallback only

8.3 PSAP Authentication

PSAPs MUST be authenticated using:


9. Directory Service

9.1 Directory Entry

Format:

{
  "cpId": "CP1-UK-0001",
  "ranges": [
    {
      "numberRange": "+4471234567XX",
      "status": "active",
      "portedTo": null,
      "portedAt": null
    },
    {
      "numberRange": "+4471234568XX",
      "status": "ported",
      "portedTo": "CP1-UK-0002",
      "portedAt": "2025-10-15T10:00:00.000Z"
    }
  ],
  "endpoints": {
    "auth": "https://api.cp1.example.com/pstn2/v1/auth",
    "routing": "https://api.cp1.example.com/pstn2/v1/routing",
    "emergency": "https://api.cp1.example.com/pstn2/v1/emergency"
  },
  "publicKey": "base64-ed25519-public-key",
  "certificates": [
    {
      "fingerprint": "sha256:hexadecimal",
      "validFrom": "2025-01-01T00:00:00.000Z",
      "validTo": "2026-01-01T00:00:00.000Z"
    }
  ],
  "lastUpdated": "2025-11-30T21:00:00.000Z",
  "version": 42
}

9.2 Directory Synchronization

Pull Directory:

Push Updates:

9.3 Number Range Format

9.4 Eventual Consistency


10. Error Handling

10.1 Error Response Format

{
  "error": {
    "code": "call_not_found",
    "message": "No matching call record found",
    "timestamp": "ISO-8601",
    "requestId": "uuid"
  }
}

10.2 Error Codes

Authentication:

Routing:

Emergency:

General:

10.3 Retry Logic

Exponential Backoff:

  1. First retry: 100ms
  2. Second retry: 200ms
  3. Third retry: 400ms
  4. Max retries: 3
  5. Fallback: Use traditional PSTN

Retry Conditions:

Do NOT Retry:

Ported Numbers: A 200 OK response with "ported": true is not an error and is not a retry of the same request. The client MUST re-query the directory and send a new request to the range holder identified by newRcpid (see §5.1.2). Maximum 5 hops.


11. Security Considerations

11.1 Authentication

Message Signing:

signature = Ed25519.sign(privateKey, payload)
payload = JSON.stringify(messageBody) + timestamp

Verification:

valid = Ed25519.verify(publicKey, signature, payload)

11.2 Rate Limiting

Per CP:

Implementation:

11.3 Replay Protection

Timestamp validation alone (±30 seconds, see §3.2) does not prevent replay of a captured message within the acceptance window. Receivers MUST keep a cache of seen messageId values covering at least the timestamp-acceptance window (±30 seconds) and MUST reject any request whose messageId has already been seen with 401 Unauthorized and error code REPLAY_DETECTED.

11.4 DDoS Protection

Required:

Recommended:

11.5 Privacy

Minimize Data Sharing:

GDPR Compliance:


12. Implementation Requirements

12.1 Mandatory Features

All implementations MUST support:

12.2 Optional Features

Implementations MAY support:

12.3 Performance Targets

Latency:

Throughput:

Reliability:

12.4 Testing Requirements

Unit Tests:

Integration Tests:

Load Tests:

12.5 Logging Requirements

Required Logs:

Log Format:

Retention:


Appendix A: Example Call Flow

Complete Call: Alice → Bob

  1. Alice dials Bob's number (+447700900123)
  2. CP1 (Alice's CP) looks up Bob's CP in cached directory
  3. CP1 requests routing from CP2 (Bob's CP)
    POST https://api.cp2.example.com/pstn2/v1/routing/request
  4. CP2 accepts and returns connection details
  5. CP1 establishes encrypted media with CP2
  6. Bob's phone rings with caller ID and branding
  7. Bob answers, encrypted conversation begins
  8. Call completes, logs retained for 24 hours

Total time: ~800ms (vs 5-8 seconds traditional PSTN)


Appendix B: Security Audit Checklist


Appendix C: Version History


Appendix D: References


Document Status: Living Specification Feedback: https://github.com/njjholland-dot/pstn2/issues Website: https://pstn2.org