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):
member: Ratchet ağacındaleaf_indexile belirtilen indistekiLeafNodeiçinde bulunan imza anahtarı.external:external_sendersgrup bağlamı uzantısındasender_indexile belirtilen indisteki imza anahtarı (bkz. Bölüm 12.1.8.1). Mesajıncontent_typedeğeriproposalolmalıdır (MUST) veproposal_typedeğeri harici göndericiler için izin verilen bir değer olmalıdır (MUST).new_member_commit: Commit'in yolundakiLeafNodeiçindeki imza anahtarı (bkz. Bölüm 12.4.3.2). Mesajıncontent_typedeğericommitolmalıdır (MUST).new_member_proposal: Harici bir Add teklifi içine gömülüKeyPackageiçindekiLeafNode'un imza anahtarı. Mesajıncontent_typedeğeriproposalolmalıdır (MUST) ve Proposal'ınproposal_typedeğeriaddolmalı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).