From 671970005bab77998c76627a7b9b2168a725ee17 Mon Sep 17 00:00:00 2001 From: cypherkitty Date: Sat, 28 Dec 2024 20:01:42 -0800 Subject: [PATCH] Migrate to age encryption --- meta-secret/Cargo.toml | 2 +- meta-secret/core-swift-lib/Cargo.toml | 1 - meta-secret/core/Cargo.toml | 2 +- meta-secret/core/src/crypto/encoding.rs | 51 ++---- meta-secret/core/src/crypto/key_pair.rs | 37 ++-- meta-secret/core/src/crypto/keys.rs | 46 ++--- meta-secret/core/src/errors/mod.rs | 7 +- .../core/src/node/app/virtual_device.rs | 7 +- .../core/src/node/common/model/crypto/aead.rs | 164 ++++-------------- .../src/node/common/model/crypto/channel.rs | 25 ++- meta-secret/core/src/secret/mod.rs | 7 +- 11 files changed, 121 insertions(+), 228 deletions(-) diff --git a/meta-secret/Cargo.toml b/meta-secret/Cargo.toml index 6b6a837e..7a4ce1c0 100644 --- a/meta-secret/Cargo.toml +++ b/meta-secret/Cargo.toml @@ -38,7 +38,6 @@ async-mutex = "1.4.0" # Cryptography ed25519-dalek = "2.1.1" -crypto_box = { version = "0.8.2", features = ["std"] } rand = "0.8.5" getrandom = { version = "0.2.15", features = ["js"] } sha2 = { version = "0.10.8", features = ["oid"] } @@ -46,6 +45,7 @@ base64 = "0.20.0" hex = "0.4.3" #https://github.com/dsprenkels/sss-rs shamirsecretsharing = "0.1.5" +age = { version = "0.11.1", features = ["curve25519-dalek", "armor", "cli-common"] } # Networking axum = "0.7.9" diff --git a/meta-secret/core-swift-lib/Cargo.toml b/meta-secret/core-swift-lib/Cargo.toml index 9d296bd2..884197f8 100644 --- a/meta-secret/core-swift-lib/Cargo.toml +++ b/meta-secret/core-swift-lib/Cargo.toml @@ -17,7 +17,6 @@ serde_json.workspace = true serde_derive.workspace = true ed25519-dalek.workspace = true -crypto_box.workspace = true base64.workspace = true sha2.workspace = true hex.workspace = true diff --git a/meta-secret/core/Cargo.toml b/meta-secret/core/Cargo.toml index 1c8b4d33..47c7fff5 100644 --- a/meta-secret/core/Cargo.toml +++ b/meta-secret/core/Cargo.toml @@ -38,7 +38,6 @@ tracing-attributes = "0.1.27" ed25519-dalek.workspace = true -crypto_box.workspace = true rand.workspace = true getrandom.workspace = true sha2.workspace = true @@ -46,6 +45,7 @@ base64.workspace = true hex.workspace = true #https://github.com/dsprenkels/sss-rs shamirsecretsharing.workspace = true +age.workspace = true serde_bytes = "0.11" serde-big-array = "0.4" diff --git a/meta-secret/core/src/crypto/encoding.rs b/meta-secret/core/src/crypto/encoding.rs index 97d5eff2..9aa5a16e 100644 --- a/meta-secret/core/src/crypto/encoding.rs +++ b/meta-secret/core/src/crypto/encoding.rs @@ -1,4 +1,4 @@ -use crypto_box::KEY_SIZE as KEY_SIZE_32_BYTES; +const KEY_SIZE_32_BYTES: usize = 32; pub type Array256Bit = [u8; KEY_SIZE_32_BYTES]; pub type Base64String = String; @@ -217,13 +217,14 @@ pub mod serialized_key_manager { use crate::crypto::encoding::base64::Base64Text; use crate::crypto::encoding::Array256Bit; use crate::crypto::key_pair::{ - CryptoBoxSecretKey, DalekKeyPair, DalekPublicKey, DalekSignature, DsaKeyPair, - TransportDsaKeyPair, + DalekKeyPair, DalekPublicKey, DalekSignature, DsaKeyPair, TransportDsaKeyPair, }; use crate::crypto::keys::{ KeyManager, SecretBox, SerializedDsaKeyPair, SerializedTransportKeyPair, }; use crate::errors::CoreError; + use age::x25519::Identity; + use std::str::FromStr; impl TryFrom<&SerializedDsaKeyPair> for DsaKeyPair { type Error = CoreError; @@ -261,11 +262,15 @@ pub mod serialized_key_manager { fn try_from( serialized_transport: &SerializedTransportKeyPair, ) -> Result { - let sk_bytes = Array256Bit::try_from(&serialized_transport.sk.0)?; - let secret_key = CryptoBoxSecretKey::from(sk_bytes); - let key_pair = Self { secret_key }; - - Ok(key_pair) + let sk_bytes = String::try_from(&serialized_transport.sk.0)?; + let sk_res = Identity::from_str(sk_bytes.as_str()); + + match sk_res { + Ok(secret_key) => Ok(Self { secret_key }), + Err(err_str) => Err(CoreError::InvalidSizeEncryptionError { + err_msg: err_str.to_string(), + }), + } } } @@ -313,33 +318,3 @@ pub mod serialized_key_manager { } } } - -pub mod cryptobox { - pub mod decoder { - use crypto_box::Nonce; - - use crate::crypto::encoding::base64::Base64Text; - use crate::crypto::encoding::Array256Bit; - use crate::crypto::key_pair::CryptoBoxSecretKey; - use crate::errors::CoreError; - - impl TryFrom<&Base64Text> for CryptoBoxSecretKey { - type Error = CoreError; - - fn try_from(encoded: &Base64Text) -> Result { - let byte_array = Array256Bit::try_from(encoded)?; - Ok(CryptoBoxSecretKey::from(byte_array)) - } - } - - impl TryFrom<&Base64Text> for Nonce { - type Error = CoreError; - - fn try_from(encoded: &Base64Text) -> Result { - let vec = Vec::try_from(encoded)?; - let byte_array: [u8; 24] = vec.as_slice().try_into()?; - Ok(Nonce::from(byte_array)) - } - } - } -} diff --git a/meta-secret/core/src/crypto/key_pair.rs b/meta-secret/core/src/crypto/key_pair.rs index f1319502..b82a9447 100644 --- a/meta-secret/core/src/crypto/key_pair.rs +++ b/meta-secret/core/src/crypto/key_pair.rs @@ -1,18 +1,16 @@ -use crypto_box::aead::OsRng as CryptoBoxOsRng; +use age::secrecy::ExposeSecret; +use age::x25519::Identity; use ed25519_dalek::{SecretKey, Signer, SigningKey}; use rand::rngs::OsRng as RandOsRng; use rand::RngCore; use crate::crypto::encoding::base64::Base64Text; use crate::crypto::keys::{DsaPk, DsaSk, TransportPk, TransportSk}; -use crate::node::common::model::crypto::aead::{AeadAuthData, AeadCipherText, AeadPlainText}; +use crate::node::common::model::crypto::aead::{AeadCipherText, AeadPlainText}; use crate::node::common::model::crypto::channel::CommunicationChannel; use crate::secret::shared_secret::PlainText; use crate::CoreResult; -pub type CryptoBoxPublicKey = crypto_box::PublicKey; -pub type CryptoBoxSecretKey = crypto_box::SecretKey; - pub type DalekKeyPair = SigningKey; pub type DalekPublicKey = ed25519_dalek::VerifyingKey; pub type DalekSecretKey = SecretKey; @@ -71,28 +69,29 @@ impl KeyPair for DsaKeyPair { } pub struct TransportDsaKeyPair { - pub secret_key: CryptoBoxSecretKey, + pub secret_key: Identity, } impl TransportDsaKeyPair { pub fn sk(&self) -> TransportSk { - let raw_sk = Base64Text::from(self.secret_key.as_bytes()); + let raw_sk = Base64Text::from(self.secret_key.to_string().expose_secret()); TransportSk(raw_sk) } } impl KeyPair for TransportDsaKeyPair { fn generate() -> Self { - let secret_key = CryptoBoxSecretKey::generate(&mut CryptoBoxOsRng); + let secret_key = Identity::generate(); Self { secret_key } } fn pk(&self) -> TransportPk { - TransportPk::from(&self.secret_key.public_key()) + let base64 = Base64Text::from(self.secret_key.to_public().to_string()); + TransportPk::from(base64) } fn sk(&self) -> TransportSk { - let raw_sk = Base64Text::from(self.secret_key.as_bytes()); + let raw_sk = Base64Text::from(self.secret_key.to_string().expose_secret()); TransportSk(raw_sk) } } @@ -108,14 +107,14 @@ impl TransportDsaKeyPair { plain_text: PlainText, receiver_pk: &TransportPk, ) -> anyhow::Result { - let channel = CommunicationChannel::build(self.pk(), receiver_pk.clone()); + let channel = CommunicationChannel::end_to_end(self.pk(), receiver_pk.clone()); let plain_text = AeadPlainText { msg: Base64Text::from(plain_text), - auth_data: AeadAuthData::from(channel), + channel, }; - plain_text.encrypt(&self.secret_key) + plain_text.encrypt() } } @@ -124,7 +123,7 @@ pub mod test { use crate::crypto::encoding::base64::Base64Text; use crate::crypto::key_pair::KeyPair; use crate::crypto::keys::KeyManager; - use crate::node::common::model::crypto::aead::{AeadAuthData, AeadCipherText, AeadPlainText}; + use crate::node::common::model::crypto::aead::{AeadCipherText, AeadPlainText}; use crate::node::common::model::crypto::channel::CommunicationChannel; use crate::secret::shared_secret::PlainText; @@ -148,17 +147,17 @@ pub mod test { let alice_km = KeyManager::generate(); let bob_km = KeyManager::generate(); - let channel = CommunicationChannel::build(alice_km.transport.pk(), bob_km.transport.pk()); + let channel = + CommunicationChannel::end_to_end(alice_km.transport.pk(), bob_km.transport.pk()); let plain_text = { - let auth_data = AeadAuthData::from(channel); AeadPlainText { msg: Base64Text::from("t0p$3cr3t"), - auth_data, + channel, } }; - let cipher_text = plain_text.encrypt(&alice_km.transport.secret_key)?; + let cipher_text = plain_text.encrypt()?; let decrypted_text = cipher_text.decrypt(&bob_km.transport.sk())?; assert_eq!(plain_text, decrypted_text); @@ -168,7 +167,7 @@ pub mod test { let cipher_text = AeadCipherText { msg: cipher_text.msg, - auth_data: cipher_text.auth_data.with_inverse_channel(), + channel: cipher_text.channel.inverse(), }; let decrypted_text = cipher_text.decrypt(&bob_km.transport.sk())?; diff --git a/meta-secret/core/src/crypto/keys.rs b/meta-secret/core/src/crypto/keys.rs index 2df282aa..a3f7b137 100644 --- a/meta-secret/core/src/crypto/keys.rs +++ b/meta-secret/core/src/crypto/keys.rs @@ -1,14 +1,13 @@ use crate::crypto::encoding::base64::Base64Text; -use crate::crypto::encoding::Array256Bit; -use crate::crypto::key_pair::{ - CryptoBoxPublicKey, CryptoBoxSecretKey, DsaKeyPair, KeyPair, TransportDsaKeyPair, -}; +use crate::crypto::key_pair::{DsaKeyPair, KeyPair, TransportDsaKeyPair}; use crate::crypto::utils::U64IdUrlEnc; use crate::node::common::model::crypto::aead::{AeadPlainText, EncryptedMessage}; use crate::node::common::model::crypto::channel::{CommunicationChannel, LoopbackChannel}; use crate::node::common::model::device::common::DeviceId; use crate::secret::shared_secret::PlainText; -use anyhow::Result; +use age::x25519::{Identity, Recipient}; +use anyhow::{anyhow, bail, Result}; +use std::str::FromStr; use wasm_bindgen::prelude::wasm_bindgen; pub struct KeyManager { @@ -34,17 +33,12 @@ pub struct DsaPk(pub Base64Text); #[wasm_bindgen(getter_with_clone)] pub struct DsaSk(pub Base64Text); -#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] #[wasm_bindgen(getter_with_clone)] pub struct TransportPk(Base64Text); impl TransportPk { - pub fn as_crypto_box_pk(&self) -> Result { - let byte_array = Array256Bit::try_from(&self.0)?; - Ok(CryptoBoxPublicKey::from(byte_array)) - } - pub fn to_device_id(&self) -> DeviceId { let pk_id = U64IdUrlEnc::from(self.0.base64_str()); DeviceId(pk_id) @@ -53,12 +47,17 @@ impl TransportPk { pub fn to_loopback_channel(self) -> LoopbackChannel { CommunicationChannel::single_device(self) } + + pub fn as_recipient(&self) -> Result { + let pk_base64 = &self.0; + let pk_str = String::try_from(pk_base64)?; + Recipient::from_str(pk_str.as_str()).map_err(|err_str| anyhow!(err_str)) + } } -impl From<&CryptoBoxPublicKey> for TransportPk { - fn from(pk: &CryptoBoxPublicKey) -> Self { - let pk_url_enc = Base64Text::from(pk.as_bytes()); - Self(pk_url_enc) +impl From for TransportPk { + fn from(pk_b64: Base64Text) -> Self { + Self(pk_b64) } } @@ -69,13 +68,20 @@ pub struct TransportSk(pub Base64Text); impl TransportSk { pub fn pk(&self) -> Result { - let sk = self.as_crypto_box_sk()?; - Ok(TransportPk::from(&sk.public_key())) + let sk = self.as_age()?; + let pk = Base64Text::from(sk.to_public().to_string()); + Ok(TransportPk::from(pk)) } - pub fn as_crypto_box_sk(&self) -> Result { - let sk = CryptoBoxSecretKey::try_from(&self.0)?; - Ok(sk) + pub fn as_age(&self) -> Result { + let decoded_sk = String::try_from(&self.0)?; + let sk_result = Identity::from_str(decoded_sk.as_str()); + match sk_result { + Ok(sk) => Ok(sk), + Err(err_str) => { + bail!(err_str) + } + } } } diff --git a/meta-secret/core/src/errors/mod.rs b/meta-secret/core/src/errors/mod.rs index 4f01315d..b3733c25 100644 --- a/meta-secret/core/src/errors/mod.rs +++ b/meta-secret/core/src/errors/mod.rs @@ -38,11 +38,8 @@ pub enum CoreError { source: std::str::Utf8Error, }, - #[error(transparent)] - EncryptionError { - #[from] - source: crypto_box::aead::Error, - }, + #[error("Invalid key size")] + InvalidSizeEncryptionError { err_msg: String }, #[error("The key manager: {key_manager_pk:?} is not a component of the secure communication channel: {channel:?}")] ThirdPartyEncryptionError { diff --git a/meta-secret/core/src/node/app/virtual_device.rs b/meta-secret/core/src/node/app/virtual_device.rs index 767d95ba..61a5647f 100644 --- a/meta-secret/core/src/node/app/virtual_device.rs +++ b/meta-secret/core/src/node/app/virtual_device.rs @@ -164,12 +164,7 @@ impl VirtualDevice { let KvLogEvent { value: share, .. } = dist_event; // re encrypt message? - let msg_receiver = share - .secret_message - .cipher_text() - .auth_data - .channel() - .receiver(); + let msg_receiver = share.secret_message.cipher_text().channel.receiver(); let msg_receiver_device = msg_receiver.to_device_id(); let msg = if msg_receiver_device.eq(&claim.sender) { diff --git a/meta-secret/core/src/node/common/model/crypto/aead.rs b/meta-secret/core/src/node/common/model/crypto/aead.rs index 1f2406d0..8c208ab6 100644 --- a/meta-secret/core/src/node/common/model/crypto/aead.rs +++ b/meta-secret/core/src/node/common/model/crypto/aead.rs @@ -1,93 +1,33 @@ -use crypto_box::aead::{Aead, AeadCore}; -use crypto_box::{ - aead::{OsRng as CryptoBoxOsRng, Payload}, - ChaChaBox, Nonce, -}; -use image::EncodableLayout; +use age::armor::{ArmoredWriter, Format}; +use std::io::Write; use crate::crypto::encoding::base64::Base64Text; -use crate::crypto::key_pair::CryptoBoxSecretKey; -use crate::crypto::keys::{TransportPk, TransportSk}; -use crate::errors::CoreError; +use crate::crypto::keys::TransportSk; use crate::node::common::model::crypto::channel::CommunicationChannel; -use anyhow::Result; - -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct AeadAuthData { - associated_data: String, - channel: CommunicationChannel, - nonce: Base64Text, -} - -impl AeadAuthData { - pub fn with_inverse_channel(&self) -> Self { - Self { - associated_data: self.associated_data.clone(), - channel: self.channel.clone().inverse(), - nonce: self.nonce.clone(), - } - } - - pub fn channel(&self) -> &CommunicationChannel { - &self.channel - } - - pub fn generate_nonce() -> Base64Text { - let nonce: Nonce = ChaChaBox::generate_nonce(&mut CryptoBoxOsRng); - Base64Text::from(nonce.as_slice()) - } - - pub fn receiver(&self) -> &TransportPk { - self.channel.receiver() - } - - pub fn nonce(&self) -> Result { - Nonce::try_from(&self.nonce) - } -} - -impl From for AeadAuthData { - fn from(channel: CommunicationChannel) -> Self { - Self { - associated_data: String::from("checksum"), - channel, - nonce: AeadAuthData::generate_nonce(), - } - } -} +use anyhow::{bail, Result}; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AeadCipherText { pub msg: Base64Text, - pub auth_data: AeadAuthData, + pub channel: CommunicationChannel, } impl AeadCipherText { /// Decrypt this secret message using the secret key - pub fn decrypt(&self, secret_key: &TransportSk) -> Result { - let auth_data = &self.auth_data; - - let their_pk = &auth_data.channel().peer(&secret_key.pk()?)?; - - let plain_bytes = { - let crypto_box_sk = &secret_key.as_crypto_box_sk()?; - let crypto_box = ChaChaBox::new(&their_pk.as_crypto_box_pk()?, crypto_box_sk); - - let msg_data = Vec::try_from(&self.msg)?; - let payload = Payload { - msg: msg_data.as_bytes(), - aad: self.auth_data.associated_data.as_bytes(), - }; - let nonce = auth_data.nonce()?; + pub fn decrypt(&self, sk: &TransportSk) -> Result { + if !self.channel.contains(&sk.pk()?) { + bail!("Invalid recipient") + } - crypto_box.decrypt(&nonce, payload)? + let decrypted_vec = { + let encrypted = Vec::try_from(&self.msg)?; + age::decrypt(&sk.as_age()?, encrypted.as_slice())? }; let plain_text = AeadPlainText { - msg: Base64Text::from(plain_bytes), - auth_data: self.auth_data.clone(), + msg: Base64Text::from(decrypted_vec), + channel: self.channel.clone(), }; Ok(plain_text) @@ -98,31 +38,30 @@ impl AeadCipherText { #[serde(rename_all = "camelCase")] pub struct AeadPlainText { pub msg: Base64Text, - pub auth_data: AeadAuthData, + pub channel: CommunicationChannel, } impl AeadPlainText { - pub fn encrypt(&self, sk: &CryptoBoxSecretKey) -> Result { - let auth_data = &self.auth_data; - - let cipher_text = { - let msg_data = Vec::try_from(&self.msg)?; - let payload = Payload { - msg: msg_data.as_bytes(), // your message to encrypt - aad: auth_data.associated_data.as_bytes(), // not encrypted, but authenticated in tag - }; - let nonce = auth_data.nonce()?; - - let crypto_box = { - let their_pk = auth_data.receiver(); - ChaChaBox::new(&their_pk.as_crypto_box_pk()?, sk) - }; - crypto_box.encrypt(&nonce, payload)? + pub fn encrypt(&self) -> Result { + let encryptor = { + let recipients = self.channel.recipients()?; + age::Encryptor::with_recipients(recipients.iter().map(|r| r.as_ref() as _))? }; + let mut ciphertext = vec![]; + + let armored_writer = ArmoredWriter::wrap_output(&mut ciphertext, Format::AsciiArmor)?; + let mut writer = encryptor.wrap_output(armored_writer)?; + + let plaintext = String::try_from(&self.msg)?; + writer.write_all(plaintext.as_bytes())?; + writer.finish()?.finish()?; + + let msg = Base64Text::from(ciphertext); + let cipher_text = AeadCipherText { - msg: Base64Text::from(cipher_text), - auth_data: self.auth_data.clone(), + msg, + channel: self.channel.clone(), }; Ok(cipher_text) @@ -149,44 +88,9 @@ impl EncryptedMessage { #[cfg(test)] mod test { use crate::crypto::key_pair::KeyPair; - use crate::crypto::keys::{KeyManager, SecretBox}; - use crate::node::common::model::crypto::aead::{ - AeadAuthData, AeadCipherText, CommunicationChannel, - }; + use crate::crypto::keys::KeyManager; + use crate::node::common::model::crypto::aead::AeadCipherText; use crate::secret::shared_secret::PlainText; - use crypto_box::aead::{Aead, Payload}; - use crypto_box::ChaChaBox; - - #[test] - fn crypto_box_encryption_test() -> anyhow::Result<()> { - let alice_km = KeyManager::generate(); - let bob_km = KeyManager::generate(); - - let channel = CommunicationChannel::build(alice_km.transport.pk(), bob_km.transport.pk()); - - let auth_data = AeadAuthData::from(channel); - let nonce = auth_data.nonce()?; - - let alice_sk = { - let alice_secret_box = SecretBox::from(&alice_km); - KeyManager::try_from(&alice_secret_box)? - .transport - .secret_key - .clone() - }; - - let alice_box = ChaChaBox::new(&alice_sk.public_key(), &alice_sk); - - let checksum = String::from("tag"); - let payload = Payload { - msg: b"Top secret message we're encrypting".as_ref(), - aad: checksum.as_bytes(), - }; - - let _ = alice_box.encrypt(&nonce, payload)?; - - Ok(()) - } #[test] fn encryption_test() -> anyhow::Result<()> { diff --git a/meta-secret/core/src/node/common/model/crypto/channel.rs b/meta-secret/core/src/node/common/model/crypto/channel.rs index 9107c6f2..16bcf30f 100644 --- a/meta-secret/core/src/node/common/model/crypto/channel.rs +++ b/meta-secret/core/src/node/common/model/crypto/channel.rs @@ -2,6 +2,7 @@ use crate::crypto::keys::TransportPk; use crate::errors::CoreError; use crate::CoreResult; use anyhow::{bail, Result}; +use std::collections::HashSet; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -10,6 +11,19 @@ pub enum CommunicationChannel { SingleDevice(LoopbackChannel), } +impl CommunicationChannel { + pub fn recipients(&self) -> Result>> { + let mut recipients: Vec> = vec![]; + + let pks = HashSet::from([self.sender(), self.receiver()]); + for pk in pks { + recipients.push(Box::new(pk.as_recipient()?)); + } + + Ok(recipients) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct End2EndChannel { @@ -49,7 +63,7 @@ impl End2EndChannel { } impl CommunicationChannel { - pub fn build(sender: TransportPk, receiver: TransportPk) -> CommunicationChannel { + pub fn end_to_end(sender: TransportPk, receiver: TransportPk) -> CommunicationChannel { if sender == receiver { CommunicationChannel::SingleDevice(LoopbackChannel { device: sender }) } else { @@ -101,4 +115,13 @@ impl CommunicationChannel { }), } } + + pub fn contains(&self, pk: &TransportPk) -> bool { + match self { + CommunicationChannel::End2End(channel) => { + channel.sender.eq(pk) || channel.receiver.eq(pk) + } + CommunicationChannel::SingleDevice(channel) => channel.device.eq(pk), + } + } } diff --git a/meta-secret/core/src/secret/mod.rs b/meta-secret/core/src/secret/mod.rs index 817bec10..27514f68 100644 --- a/meta-secret/core/src/secret/mod.rs +++ b/meta-secret/core/src/secret/mod.rs @@ -128,12 +128,7 @@ impl MetaDistributor { }; let dist_id = { - let receiver = secret_share - .cipher_text() - .auth_data - .channel() - .receiver() - .to_device_id(); + let receiver = secret_share.cipher_text().channel.receiver().to_device_id(); SsDistributionId { pass_id: claim.id.pass_id.clone(), receiver,