syntax = "proto3"; // 32-byte value in bigendian format message CryptoKey { fixed32 u0 = 1; fixed32 u1 = 2; fixed32 u2 = 3; fixed32 u3 = 4; fixed32 u4 = 5; fixed32 u5 = 6; fixed32 u6 = 7; fixed32 u7 = 8; } // 64-byte value in bigendian format message Signature { fixed32 u0 = 1; fixed32 u1 = 2; fixed32 u2 = 3; fixed32 u3 = 4; fixed32 u4 = 5; fixed32 u5 = 6; fixed32 u6 = 7; fixed32 u7 = 8; fixed32 u8 = 9; fixed32 u9 = 10; fixed32 u10 = 11; fixed32 u11 = 12; fixed32 u12 = 13; fixed32 u13 = 14; fixed32 u14 = 15; fixed32 u15 = 16; } // 24-byte value in bigendian format message Nonce { fixed32 u0 = 1; fixed32 u1 = 2; fixed32 u2 = 3; fixed32 u3 = 4; fixed32 u4 = 5; fixed32 u5 = 6; } // 36-byte typed crypto key message TypedKey { // CryptoKind FourCC in bigendian format fixed32 kind = 1; // Key value CryptoKey value = 2; } // Key pair message KeyPair { // Public key CryptoKey key = 1; // Private key CryptoKey secret = 2; } // DHTData - represents chunked blob data in the DHT // Header in subkey 0 follows this structure // // stride = descriptor subkey count on first key - 1 // Subkeys 1..=stride on the first key are concatenated chunks // Subkeys 0..stride on the 'keys' keys are concatenated chunks // // Keys must use writable schema in order to make this data mutable message DHTData { // Other keys to concatenate // Uses the same writer as this DHTList with SMPL schema repeated TypedKey keys = 1; // Hash of reassembled data to verify contents TypedKey hash = 2; // Chunk size per subkey uint32 chunk = 3; // Total data size uint32 size = 4; } // DHTShortArray - represents a re-orderable collection of up to 256 individual elements // Header in subkey 0 of first key follows this structure // // stride = descriptor subkey count on first key - 1 // Subkeys 1..=stride on the first key are individual elements // Subkeys 0..stride on the 'keys' keys are also individual elements // // Keys must use writable schema in order to make this list mutable message DHTShortArray { // Other keys to concatenate // Uses the same writer as this DHTList with SMPL schema repeated TypedKey keys = 1; // Item position index (uint8[256]) // Actual item location is: // idx = index[n] + 1 (offset for header at idx 0) // key = idx / stride // subkey = idx % stride bytes index = 2; // Free items are not represented in the list but can be // calculated through iteration } // DHTLog - represents an appendable/truncatable log collection of individual elements // Header in subkey 0 of first key follows this structure // // stride = descriptor subkey count on first key - 1 // Subkeys 1..=stride on the first key are individual elements // Subkeys 0..stride on the 'keys' keys are also individual elements // // Keys must use writable schema in order to make this list mutable message DHTLog { // Other keys to concatenate repeated TypedKey keys = 1; // Back link to another DHTLog further back TypedKey back = 2; // Count of subkeys in all keys in this DHTLog repeated uint32 subkey_counts = 3; // Total count of subkeys in all keys in this DHTLog including all backlogs uint32 total_subkeys = 4; } // DataReference // Pointer to data somewhere in Veilid // Abstraction over DHTData and BlockStore message DataReference { oneof kind { TypedKey dht_data = 1; // TypedKey block = 2; } } // AttachmentKind // Enumeration of well-known attachment types enum AttachmentKind { ATTACHMENT_KIND_UNSPECIFIED = 0; ATTACHMENT_KIND_FILE = 1; ATTACHMENT_KIND_IMAGE = 2; } // A single attachment message Attachment { // Type of the data AttachmentKind kind = 1; // MIME type of the data string mime = 2; // Title or filename string name = 3; // Pointer to the data content DataReference content = 4; // Author signature over all attachment fields and content fields and bytes Signature signature = 5; } // A single message as part of a series of messages // Messages are stored in a DHTLog message Message { // Author of the message TypedKey author = 1; // Time the message was sent (us since epoch) uint64 timestamp = 2; // Text of the message string text = 3; // Author signature over all of the fields and attachment signatures Signature signature = 4; // Attachments on the message repeated Attachment attachments = 5; } // A record of a 1-1 chat that is synchronized between // two users. Visible and encrypted for the other party // // DHT Schema: SMPL(0,1,[identityPublicKey]) // DHT Key (UnicastOutbox): localConversation // DHT Secret: None // Encryption: DH(IdentityA, IdentityB) message Conversation { // Profile to publish to friend Profile profile = 1; // Identity master (JSON) to publish to friend string identity_master_json = 2; // Messages DHTLog (xxx for now DHTShortArray) OwnedDHTRecordPointer messages = 3; } // A record of a contact that has accepted a contact invitation // Contains a copy of the most recent remote profile as well as // a locally edited profile. // Contains a copy of the most recent identity from the contact's // Master identity dht key // // Stored in ContactList DHTList message Contact { // Friend's profile as locally edited Profile edited_profile = 1; // Copy of friend's profile from remote conversation Profile remote_profile = 2; // Copy of friend's IdentityMaster in JSON from remote conversation string identity_master_json = 3; // Copy of friend's most recent identity public key from their identityMaster TypedKey identity_public_key = 4; // Remote conversation key to sync from friend TypedKey remote_conversation_key = 5; // Our conversation key for friend to sync OwnedDHTRecordPointer local_conversation = 6; // Show availability bool show_availability = 7; } // Contact availability enum Availability { AVAILABILITY_UNSPECIFIED = 0; AVAILABILITY_OFFLINE = 1; AVAILABILITY_FREE = 2; AVAILABILITY_BUSY = 3; AVAILABILITY_AWAY = 4; } // Publicly shared profile information for both contacts and accounts // Contains: // Name - Friendly name // Title - Title of user // Icon - Little picture to represent user in contact list message Profile { // Friendy name string name = 1; // Title of user string title = 2; // Status/away message string status = 3; // Availability Availability availability = 4; // Avatar DHTData optional TypedKey avatar = 5; } // A pointer to an child DHT record message OwnedDHTRecordPointer { // DHT Record key TypedKey record_key = 1; // DHT record owner key KeyPair owner = 2; } enum ChatType { CHAT_TYPE_UNSPECIFIED = 0; SINGLE_CONTACT = 1; GROUP = 2; } // Either a 1-1 converation or a group chat (eventually) message Chat { // What kind of chat is this ChatType type = 1; // 1-1 Chat key TypedKey remote_conversation_key = 2; } // A record of an individual account // Pointed to by the identity account map in the identity key // // DHT Schema: DFLT(1) // DHT Private: accountSecretKey message Account { // The user's profile that gets shared with contacts Profile profile = 1; // Invisibility makes you always look 'Offline' bool invisible = 2; // Auto-away sets 'away' mode after an inactivity time uint32 auto_away_timeout_sec = 3; // The contacts DHTList for this account // DHT Private OwnedDHTRecordPointer contact_list = 4; // The ContactInvitationRecord DHTShortArray for this account // DHT Private OwnedDHTRecordPointer contact_invitation_records = 5; // The chats DHTList for this account // DHT Private OwnedDHTRecordPointer chat_list = 6; } // EncryptionKeyType // Encryption of secret enum EncryptionKeyType { ENCRYPTION_KEY_TYPE_UNSPECIFIED = 0; ENCRYPTION_KEY_TYPE_NONE = 1; ENCRYPTION_KEY_TYPE_PIN = 2; ENCRYPTION_KEY_TYPE_PASSWORD = 3; } // Invitation that is shared for VeilidChat contact connections // serialized to QR code or data blob, not send over DHT, out of band. // Writer secret is unique to this invitation. Writer public key is in the ContactRequestPrivate // in the ContactRequestInbox subkey 0 DHT key message ContactInvitation { // Contact request DHT record key TypedKey contact_request_inbox_key = 1; // Writer secret key bytes possibly encrypted with nonce appended bytes writer_secret = 2; } // Signature of invitation with identity message SignedContactInvitation { // The serialized bytes for the contact invitation bytes contact_invitation = 1; // The signature of the contact_invitation bytes with the identity Signature identity_signature = 2; } // Contact request unicastinbox on the DHT // DHTSchema: SMPL 1 owner key, 1 writer key symmetrically encrypted with writer secret message ContactRequest { // The kind of encryption used on the unicastinbox writer key EncryptionKeyType encryption_key_type = 1; // The private part encoded and symmetrically encrypted with the unicastinbox writer secret bytes private = 2; } // The private part of a possibly encrypted contact request // Symmetrically encrypted with writer secret message ContactRequestPrivate { // Writer public key for signing writes to contact request unicastinbox CryptoKey writer_key = 1; // Snapshot of profile Profile profile = 2; // Identity master DHT record key TypedKey identity_master_record_key = 3; // Local chat DHT record key TypedKey chat_record_key = 4; // Expiration timestamp uint64 expiration = 5; } // To accept or reject a contact request, fill this out and send to the ContactRequest unicastinbox message ContactResponse { // Accept or reject bool accept = 1; // Remote identity master DHT record key TypedKey identity_master_record_key = 2; // Remote chat DHT record key if accepted TypedKey remote_conversation_key = 3; } // Signature of response with identity // Symmetrically encrypted with writer secret message SignedContactResponse { // Serialized bytes for ContactResponse bytes contact_response = 1; // Signature of the contact_accept bytes with the identity Signature identity_signature = 2; } // Contact request record kept in Account DHTList to keep track of extant contact invitations message ContactInvitationRecord { // Contact request unicastinbox DHT record key (parent is accountkey) OwnedDHTRecordPointer contact_request_inbox = 1; // Writer key sent to contact for the contact_request_inbox smpl inbox subkey CryptoKey writer_key = 2; // Writer secret sent encrypted in the invitation CryptoKey writer_secret = 3; // Local chat DHT record key (parent is accountkey, will be moved to Contact if accepted) OwnedDHTRecordPointer local_conversation = 4; // Expiration timestamp uint64 expiration = 5; // A copy of the raw SignedContactInvitation invitation bytes post-encryption and signing bytes invitation = 6; // The message sent along with the invitation string message = 7; }