← MLS/
RFC 9420 · Bölüm 07 Ana Metin

6. Mesaj Çerçeveleme

El sıkışma ve uygulama mesajları ortak bir çerçeve yapısı kullanır. Bu çerçeve, grup içinde gizliliği sağlamak için şifreleme ve göndericinin kimliğini doğrulamak için imzalama sağlar.

Protokolün büyük bölümünde mesajlar, AuthenticatedContent nesneleri biçiminde ele alınır. Bu yapılar, mesajın içeriğinin kendisinin yanı sıra göndericiyi doğrulamak için gereken bilgileri de içerir (bkz. Bölüm 6.1). Bu mesajları güvenilmeyen bir kanal üzerinden iletmek için gereken ek korumalar (grup üyeliği doğrulaması veya AEAD şifrelemesi), AuthenticatedContent'in bir PublicMessage veya PrivateMessage mesajı olarak kodlanmasıyla eklenir; ardından bu mesaj MLSMessage olarak gönderilebilir. Benzer şekilde, bir PublicMessage veya PrivateMessage, AuthenticatedContent nesnesine çözümlenirken bu korumalar da uygulanır (üyelik doğrulaması veya AEAD şifre çözme yoluyla).

PrivateMessage, hem mesaj içeriği hem de buna ilişkin meta veriler için koruma sağlayan, imzalanmış ve şifrelenmiş bir mesajı temsil eder. PublicMessage ise yalnızca imzalanmış, şifrelenmemiş bir mesajı temsil eder. Uygulamalar, uygulama mesajlarını şifrelemek için PrivateMessage kullanmalıdır (MUST) ve el sıkışma mesajlarını kodlamak için PrivateMessage kullanmalıdır (SHOULD); ancak Teslimat Hizmeti'nin bu tür mesajları incelemesinin gerekli olduğu durumlarda, el sıkışma mesajlarını PublicMessage nesneleri olarak kodlanmış şekilde iletebilirler (MAY).

enum {
       reserved(0),
       mls10(1),
       (65535)
} ProtocolVersion;

enum {
       reserved(0),
       application(1),
       proposal(2),
       commit(3),
       (255)
} ContentType;

enum {
       reserved(0),
       member(1),
       external(2),
       new_member_proposal(3),
       new_member_commit(4),
       (255)
} SenderType;

struct {
       SenderType sender_type;
       select (Sender.sender_type) {
           case member:
               uint32 leaf_index;
           case external:
               uint32 sender_index;
           case new_member_commit:
           case new_member_proposal:
               struct{};
       };
} Sender;

// Değerler için "MLS Wire Formats" IANA kaydına bakınız
uint16 WireFormat;

struct {
       opaque group_id<V>;
       uint64 epoch;
       Sender sender;
       opaque authenticated_data<V>;

       ContentType content_type;
       select (FramedContent.content_type) {
           case application:
             opaque application_data<V>;
           case proposal:
             Proposal proposal;
           case commit:
             Commit commit;
       };
} FramedContent;

struct {
       ProtocolVersion version = mls10;
       WireFormat wire_format;
       select (MLSMessage.wire_format) {
           case mls_public_message:
               PublicMessage public_message;
           case mls_private_message:
               PrivateMessage private_message;
           case mls_welcome:
               Welcome welcome;
           case mls_group_info:
               GroupInfo group_info;
           case mls_key_package:
               KeyPackage key_package;
       };
} MLSMessage;

Grupta olmayan göndericilerden gelen mesajlar PublicMessage olarak gönderilir. Daha fazla ayrıntı için bkz. Bölüm 12.1.8 ve Bölüm 12.4.3.2.

Aşağıdaki yapı, açık metinlerde veya şifreli metinlerde iletilen veriyi bütünüyle tanımlamak için kullanılır.

struct {
       WireFormat wire_format;
       FramedContent content;
       FramedContentAuthData auth;
} AuthenticatedContent;

Aşağıdaki şekil, bu bölümde tanımlanan çeşitli yapıların birbiriyle nasıl ilişkili olduğunu ve bunları üretmek ve tüketmek için kullanılan üst düzey işlemleri göstermektedir:

       Proposal        Commit     Uygulama Verisi
          |              |              |
          +--------------+--------------+
                         |
                         V
                  FramedContent
                      |  |                -.
             +--------+  |                  |
             |           |                  |
             V           |                  +-- Asimetrik
FramedContentAuthData    |                  |   İmzala / Doğrula
             |           |                  |
             +--------+  |                  |
                      |  |                  |
                      V  V                -'
                AuthenticatedContent
                         |                -.
                +--------+--------+         |
                |                 |         +-- Simetrik
                V                 V         |   Koru / Korumayı Kaldır
          PublicMessage    PrivateMessage -'
                |                 |
                |                 |  Welcome  KeyPackage  GroupInfo
                |                 |     |          |          |
                +-----------------+-----+----------+----------+
                                  |
                                  V
                              MLSMessage

                Şekil 12: MLS Nesneleri Arasındaki İlişkiler

6.1 İçerik Kimlik Doğrulaması

FramedContent, FramedContentAuthData yapısı kullanılarak kimlik doğrulamasından geçirilir.

struct {
       ProtocolVersion version = mls10;
       WireFormat wire_format;
       FramedContent content;
       select (FramedContentTBS.content.sender.sender_type) {
           case member:
           case new_member_commit:
               GroupContext context;
           case external:
           case new_member_proposal:
               struct{};
       };
} FramedContentTBS;

opaque MAC<V>;

struct {
       /* SignWithLabel(., "FramedContentTBS", FramedContentTBS) */
       opaque signature<V>;
       select (FramedContent.content_type) {
           case commit:
               /*
                 MAC(confirmation_key,
                     GroupContext.confirmed_transcript_hash)
               */
               MAC confirmation_tag;
           case application:
           case proposal:
               struct{};
       };
} FramedContentAuthData;

İmza, "FramedContentTBS" etiketiyle SignWithLabel kullanılarak ve mesaj içeriğini ve bu mesaj için kullanılacak wire format'ı kapsayan bir içerik üzerinden hesaplanır. Göndericinin sender_type değeri member ise içerik ayrıca geçerli epoch'a ait GroupContext'i de kapsar; böylece imzalar belirli bir grup ve epoch'a özgü olur.

Gönderici, sender_type değerine bağlı olarak aşağıdaki imza anahtarına karşılık gelen özel anahtarı kullanmalıdır (MUST):

Bir MLSMessage alan alıcılar, yukarıda açıklandığı gibi, göndericinin sender_type değerine bağlı olan anahtarla imzayı doğrulamalıdır (MUST).

Onay etiketi (confirmation_tag) değeri, grup üyelerinin grubun aynı durumuna ulaştığını teyit eder. Hem signature hem de confirmation_tag alanları geçerliyse bir FramedContentAuthData geçerli kabul edilir.

6.2 Bir Public Message'ın Kodlanması ve Çözümlenmesi

Kimliği doğrulanan ancak şifrelenmeyen mesajlar PublicMessage yapısı kullanılarak kodlanır.

struct {
       FramedContent content;
       FramedContentAuthData auth;
       select (PublicMessage.content.sender.sender_type) {
           case member:
               MAC membership_tag;
           case external:
           case new_member_commit:
           case new_member_proposal:
               struct{};
       };
} PublicMessage;

PublicMessage nesnesindeki membership_tag alanı, göndericinin gruba üyeliğini doğrular. Üyeler tarafından gönderilen mesajlarda bu alan aşağıdaki değere ayarlanmalıdır (MUST):

struct {
     FramedContentTBS content_tbs;
     FramedContentAuthData auth;
} AuthenticatedContentTBM;

membership_tag = MAC(membership_key, AuthenticatedContentTBM)

Bir PublicMessage, AuthenticatedContent nesnesine çözümlenirken uygulama membership_tag değerini denetlemelidir (MUST) ve FramedContentAuthData yapısının geçerli olduğunu da denetlemelidir (MUST).

6.3 Bir Private Message'ın Kodlanması ve Çözümlenmesi

Kimliği doğrulanan ve şifrelenen mesajlar PrivateMessage yapısı kullanılarak kodlanır.

struct {
       opaque group_id<V>;
       uint64 epoch;
       ContentType content_type;
       opaque authenticated_data<V>;
       opaque encrypted_sender_data<V>;
       opaque ciphertext<V>;
} PrivateMessage;

encrypted_sender_data ve ciphertext, kullanılan şifre takımı tarafından belirtilen AEAD işleviyle, girdi olarak SenderData ve PrivateMessageContent yapıları kullanılarak şifrelenir.

6.3.1 İçerik Şifreleme

Şifrelenecek içerik bir PrivateMessageContent yapısında kodlanır.

struct {
       select (PrivateMessage.content_type) {
           case application:
             opaque application_data<V>;

           case proposal:
             Proposal proposal;

           case commit:
             Commit commit;
       };

       FramedContentAuthData auth;
       opaque padding[length_of_padding];
} PrivateMessageContent;

padding alanı gönderici tarafından, önce içerik (select yoluyla) ve auth alanı kodlanıp, ardından seçilen sayıda sıfır baytı eklenerek ayarlanır. Bir alıcı, PrivateMessage.ciphertext içinden çözümlenmiş bir açık metindeki padding alanını, önce içerik ve auth alanını çözüp sonra açık metindeki kalan tüm sekizlikleri padding alanı kabul ederek belirler. padding alanı tamamen sıfır baytlarla doldurulmalıdır (MUST). Bir alıcı, padding alanında sıfır olmayan herhangi bir bayt bulunmadığını doğrulamalıdır (MUST); bu denetim başarısız olursa, çevreleyen PrivateMessage bozuk biçimli kabul edilip reddedilmelidir (MUST). Bu denetim, dolgu sürecinin belirlenimci olmasını sağlar; böylece örneğin dolgu, örtük bir kanal olarak kullanılamaz.

MLS anahtar çizelgesinde gönderici, grubun her üyesi için el sıkışma ve uygulama mesajlarına yönelik iki ayrı anahtar ratchet'ı oluşturur. Bir mesajı şifrelerken gönderici, kendi üyeliği için türettiği ratchet'lara bakar ve mesajın içerik türüne bağlı olarak ya el sıkışma ratchet'ından ya da uygulama ratchet'ından kullanılmamış bir üretim seçer. Ratchet'ın bu üretimi, geçici bir nonce ve anahtar türetmek için kullanılır.

Şifreleme işleminde kullanılmadan önce nonce, yeniden kullanımına karşı koruma sağlamak amacıyla yeni üretilmiş rastgele bir değerle XOR'lanır. Anahtar çizelgesi nonce'ları belirlenimci biçimde ürettiğinden, bir istemci anahtar çizelgesinde nerede bulunduğuna ilişkin kalıcı durumu saklamak zorundadır (MUST); bu kalıcı durum kaybolur veya bozulursa, istemci daha önce kullanılmış bir üretimi yeniden kullanabilir ve bu da aynı anahtar/nonce çiftinin yeniden kullanımına yol açabilir.

Bu durumdan kaçınmak için, mesajın göndericisi yeni üretilmiş rastgele dört baytlık bir "yeniden kullanım koruması" (reuse guard) değeri oluşturmalı (MUST) ve şifreleme için nonce'ı kullanmadan önce bunu anahtar çizelgesinden gelen nonce'ın ilk dört baytıyla XOR'lamalıdır (MUST). Gönderici, alıcının şifre çözmede kullanacağı nonce'ı hesaplayabilmesi için reuse guard değerini gönderici verisi nesnesindeki reuse_guard alanına dahil etmelidir (MUST).

+-+-+-+-+---------...---+
|   Anahtar Çizelgesi   |
|        Nonce'ı        |
+-+-+-+-+---------...---+
              XOR
+-+-+-+-+---------...---+
| Guard |       0       |
+-+-+-+-+---------...---+
              ===
+-+-+-+-+---------...---+
| Şifreleme/Şifre Çözme |
|        Nonce'ı        |
+-+-+-+-+---------...---+

Şifrelemenin Additional Authenticated Data (AAD) girdisi, anahtar ile nonce'ı tanımlamak için kullanılan değerlere sahip aşağıdaki biçimde bir nesne içerir:

struct {
       opaque group_id<V>;
       uint64 epoch;
       ContentType content_type;
       opaque authenticated_data<V>;
} PrivateContentAAD;

Bir PrivateMessageContent çözümlenirken uygulama, FramedContentAuthData yapısının geçerli olduğunu denetlemelidir (MUST).

Hangi authenticated_data değerinin sağlanacağına ve belirli bir mesaja ne kadar dolgu ekleneceğine (varsa) karar vermek uygulamaya kalır. AAD ile şifreli metnin toplam boyutu, [CFRG-AEAD-LIMITS]'te grubun AEAD algoritması için belirlenen sınırlar içinde kalmalıdır (MUST).

6.3.2 Gönderici Verisinin Şifrelenmesi

İçerik şifreleme için anahtar bulmakta kullanılan "gönderici verisi", şifre takımının AEAD'i ile, hem sender_data_secret hem de şifrelenmiş içeriğin bir örneğinden türetilen anahtar ve nonce kullanılarak şifrelenir. Şifrelenmeden önce gönderici verisi aşağıdaki biçimde bir nesne olarak kodlanır:

struct {
       uint32 leaf_index;
       uint32 generation;
       opaque reuse_guard[4];
} SenderData;

Bir Sender nesnesinden SenderData nesnesi oluşturulurken gönderici, Sender.sender_type değerinin member olduğunu doğrulamalı ve SenderData.leaf_index için Sender.leaf_index değerini kullanmalıdır (MUST).

reuse_guard alanı, Bölüm 6.3.1'de açıklandığı gibi, durum kaybı veya bozulması halinde nonce'ın yeniden kullanılmasını önlemek için kullanılan yeni rastgele değeri içerir.

AEAD'e sağlanan anahtar ve nonce, önceki bölümde üretilen şifreli metnin ilk KDF.Nh baytının KDF'si olarak hesaplanır. Şifreli metnin uzunluğu KDF.Nh'den kısa ise, şifreli metnin tamamı kullanılır. Sözde kod olarak anahtar ve nonce şu şekilde türetilir:

ciphertext_sample = ciphertext[0..KDF.Nh-1]

sender_data_key = ExpandWithLabel(sender_data_secret, "key",
                         ciphertext_sample, AEAD.Nk)
sender_data_nonce = ExpandWithLabel(sender_data_secret, "nonce",
                         ciphertext_sample, AEAD.Nn)

SenderData şifreli metni için AAD, PrivateMessage'ın ilk üç alanıdır:

struct {
       opaque group_id<V>;
       uint64 epoch;
       ContentType content_type;
} SenderDataAAD;

Mesaj şifre çözmenin bir parçası olarak SenderData struct'ı ayrıştırılırken alıcı, leaf_index alanında belirtilen yaprak indisinin boş olmayan bir düğümü tanımladığını doğrulamalıdır (MUST).