Signal · Schema
Signal Protocol Entities
Schema defining the core cryptographic entities used in the Signal Protocol, including identity keys, pre-key bundles, signed pre-keys, Kyber post-quantum pre-keys, and session state. These entities form the foundation of the key exchange and message encryption mechanisms used by Signal clients and server.
EncryptionMessagingSecurityCryptographyOpen SourcePrivacy
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://signal.org/schemas/signal/protocol-entities.json",
"title": "Signal Protocol Entities",
"description": "Schema defining the core cryptographic entities used in the Signal Protocol, including identity keys, pre-key bundles, signed pre-keys, Kyber post-quantum pre-keys, and session state. These entities form the foundation of the key exchange and message encryption mechanisms used by Signal clients and server.",
"type": "object",
"$defs": {
"IdentityKey": {
"type": "object",
"title": "Identity Key",
"description": "A long-term Curve25519 identity key pair used to identify an account. Each account has an ACI (Account Identity) key and a PNI (Phone Number Identity) key.",
"required": ["publicKey"],
"properties": {
"publicKey": {
"type": "string",
"description": "The Base64-encoded Curve25519 public identity key (32 bytes).",
"pattern": "^[A-Za-z0-9+/=]+$"
}
}
},
"PreKey": {
"type": "object",
"title": "One-Time Pre-Key",
"description": "An ephemeral Curve25519 key pair uploaded to the server for use in the X3DH or PQXDH key agreement. Each pre-key is used at most once.",
"required": ["keyId", "publicKey"],
"properties": {
"keyId": {
"type": "integer",
"format": "int64",
"description": "The unique identifier for this pre-key.",
"minimum": 0
},
"publicKey": {
"type": "string",
"description": "The Base64-encoded Curve25519 public key (32 bytes).",
"pattern": "^[A-Za-z0-9+/=]+$"
}
}
},
"SignedPreKey": {
"type": "object",
"title": "Signed Pre-Key",
"description": "A medium-term Curve25519 key pair signed by the identity key. Rotated periodically and used as a fallback when one-time pre-keys are exhausted.",
"required": ["keyId", "publicKey", "signature"],
"properties": {
"keyId": {
"type": "integer",
"format": "int64",
"description": "The unique identifier for this signed pre-key.",
"minimum": 0
},
"publicKey": {
"type": "string",
"description": "The Base64-encoded Curve25519 public key (32 bytes).",
"pattern": "^[A-Za-z0-9+/=]+$"
},
"signature": {
"type": "string",
"description": "The Base64-encoded XEdDSA signature over the public key, created with the identity private key (64 bytes).",
"pattern": "^[A-Za-z0-9+/=]+$"
}
}
},
"KyberPreKey": {
"type": "object",
"title": "Kyber Post-Quantum Pre-Key",
"description": "A post-quantum key encapsulation mechanism (KEM) key pair using CRYSTALS-Kyber, uploaded to the server for the PQXDH key agreement protocol. Provides quantum resistance for forward secrecy.",
"required": ["keyId", "publicKey", "signature"],
"properties": {
"keyId": {
"type": "integer",
"format": "int64",
"description": "The unique identifier for this Kyber pre-key.",
"minimum": 0
},
"publicKey": {
"type": "string",
"description": "The Base64-encoded Kyber-1024 public key.",
"pattern": "^[A-Za-z0-9+/=]+$"
},
"signature": {
"type": "string",
"description": "The Base64-encoded signature over the Kyber public key, created with the identity private key.",
"pattern": "^[A-Za-z0-9+/=]+$"
}
}
},
"PreKeyBundle": {
"type": "object",
"title": "Pre-Key Bundle",
"description": "A complete pre-key bundle retrieved from the server for establishing a new Signal Protocol session. Contains identity key, signed pre-key, optional one-time pre-key, and optional Kyber pre-key.",
"required": ["identityKey", "signedPreKey", "registrationId"],
"properties": {
"identityKey": {
"type": "string",
"description": "The Base64-encoded identity public key of the account."
},
"registrationId": {
"type": "integer",
"description": "The registration ID of the target device.",
"minimum": 0,
"maximum": 16383
},
"deviceId": {
"type": "integer",
"format": "int64",
"description": "The device identifier. Primary device is always 1.",
"minimum": 1
},
"preKey": {
"$ref": "#/$defs/PreKey",
"description": "An optional one-time EC pre-key."
},
"signedPreKey": {
"$ref": "#/$defs/SignedPreKey",
"description": "The current signed pre-key."
},
"pqPreKey": {
"$ref": "#/$defs/KyberPreKey",
"description": "An optional one-time Kyber post-quantum pre-key for PQXDH."
}
}
},
"MessageEnvelope": {
"type": "object",
"title": "Message Envelope",
"description": "A Signal Protocol message envelope containing encrypted content and routing metadata.",
"required": ["type", "timestamp", "content"],
"properties": {
"type": {
"type": "integer",
"description": "The envelope type: 1 (ciphertext), 3 (prekey), 6 (plaintext content), 7 (unidentified sender).",
"enum": [1, 3, 6, 7]
},
"sourceUuid": {
"type": "string",
"format": "uuid",
"description": "The sender's ACI UUID. Absent in sealed sender messages."
},
"sourceDevice": {
"type": "integer",
"description": "The sender's device ID. Absent in sealed sender messages.",
"minimum": 1
},
"destinationUuid": {
"type": "string",
"format": "uuid",
"description": "The recipient's ACI UUID."
},
"timestamp": {
"type": "integer",
"format": "int64",
"description": "The client-side send timestamp in milliseconds since epoch."
},
"serverTimestamp": {
"type": "integer",
"format": "int64",
"description": "The server-side receive timestamp in milliseconds since epoch."
},
"content": {
"type": "string",
"description": "The Base64-encoded encrypted message payload."
},
"serverGuid": {
"type": "string",
"format": "uuid",
"description": "A server-assigned GUID for this delivery instance."
},
"urgent": {
"type": "boolean",
"description": "Whether this message should be treated as urgent for push delivery."
},
"story": {
"type": "boolean",
"description": "Whether this envelope contains a story message."
}
}
},
"Account": {
"type": "object",
"title": "Signal Account",
"description": "A Signal user account identified by a phone number and one or more UUIDs.",
"required": ["uuid", "number"],
"properties": {
"uuid": {
"type": "string",
"format": "uuid",
"description": "The ACI (Account Identity) UUID, the primary stable identifier."
},
"number": {
"type": "string",
"description": "The E164-formatted phone number associated with the account.",
"pattern": "^\\+[1-9]\\d{1,14}$"
},
"pni": {
"type": "string",
"format": "uuid",
"description": "The PNI (Phone Number Identity) UUID, which changes when the phone number changes."
},
"usernameHash": {
"type": "string",
"description": "The Base64url-encoded SHA-256 hash of the username, if set."
},
"identityKey": {
"type": "string",
"description": "The Base64-encoded ACI identity public key."
},
"pniIdentityKey": {
"type": "string",
"description": "The Base64-encoded PNI identity public key."
},
"devices": {
"type": "array",
"description": "The list of devices linked to this account.",
"items": {
"$ref": "#/$defs/Device"
}
}
}
},
"Device": {
"type": "object",
"title": "Device",
"description": "A device linked to a Signal account. Each account has a primary device (ID 1) and may have additional linked devices.",
"required": ["id"],
"properties": {
"id": {
"type": "integer",
"format": "int64",
"description": "The device identifier. The primary device is always 1.",
"minimum": 1
},
"name": {
"type": "string",
"description": "The encrypted device name, Base64-encoded."
},
"registrationId": {
"type": "integer",
"description": "The Signal Protocol registration ID for this device.",
"minimum": 0,
"maximum": 16383
},
"lastSeen": {
"type": "integer",
"format": "int64",
"description": "Unix timestamp in milliseconds when the device last connected."
},
"created": {
"type": "integer",
"format": "int64",
"description": "Unix timestamp in milliseconds when the device was linked."
},
"fetchesMessages": {
"type": "boolean",
"description": "Whether this device uses WebSocket to fetch messages (true) or relies on push notifications (false)."
},
"apnId": {
"type": "string",
"description": "The Apple Push Notification Service token for iOS devices."
},
"gcmId": {
"type": "string",
"description": "The Firebase Cloud Messaging registration token for Android devices."
}
}
},
"SealedSenderCertificate": {
"type": "object",
"title": "Sealed Sender Certificate",
"description": "A delivery certificate issued by the server for sealed sender message delivery. Sealed sender hides the sender identity from the server during message transmission.",
"required": ["certificate"],
"properties": {
"certificate": {
"type": "string",
"description": "The Base64-encoded signed certificate containing the sender's UUID, device ID, identity key, and expiration."
},
"expiration": {
"type": "integer",
"format": "int64",
"description": "The certificate expiration timestamp in milliseconds since epoch."
}
}
},
"GroupV2": {
"type": "object",
"title": "Signal Group (V2)",
"description": "A Signal group using the V2 groups protocol with server-side state. Groups use zero-knowledge group credentials to maintain member privacy.",
"properties": {
"masterKey": {
"type": "string",
"description": "The Base64-encoded 32-byte group master key.",
"minLength": 1
},
"groupId": {
"type": "string",
"description": "The Base64-encoded group identifier derived from the master key."
},
"title": {
"type": "string",
"description": "The encrypted group title."
},
"avatar": {
"type": "string",
"description": "The CDN path to the encrypted group avatar."
},
"revision": {
"type": "integer",
"description": "The current group state revision number.",
"minimum": 0
},
"members": {
"type": "array",
"description": "The list of group members with their roles.",
"items": {
"$ref": "#/$defs/GroupMember"
}
},
"accessControl": {
"type": "object",
"description": "Access control settings for group modifications.",
"properties": {
"attributes": {
"type": "string",
"description": "Who can modify group attributes.",
"enum": ["UNKNOWN", "ANY", "MEMBER", "ADMINISTRATOR", "UNSATISFIABLE"]
},
"members": {
"type": "string",
"description": "Who can modify the member list.",
"enum": ["UNKNOWN", "ANY", "MEMBER", "ADMINISTRATOR", "UNSATISFIABLE"]
},
"addFromInviteLink": {
"type": "string",
"description": "Who can join via invite link.",
"enum": ["UNKNOWN", "ANY", "MEMBER", "ADMINISTRATOR", "UNSATISFIABLE"]
}
}
}
}
},
"GroupMember": {
"type": "object",
"title": "Group Member",
"description": "A member of a Signal V2 group.",
"properties": {
"uuid": {
"type": "string",
"format": "uuid",
"description": "The member's ACI UUID."
},
"role": {
"type": "string",
"description": "The member's role in the group.",
"enum": ["UNKNOWN", "DEFAULT", "ADMINISTRATOR"]
},
"joinedAtRevision": {
"type": "integer",
"description": "The group revision at which this member joined.",
"minimum": 0
}
}
}
}
}