use crate::asn1::OctetString;
use crate::cms::enveloped_data::EnvelopedData;
use crate::der::Sequence;
use crate::spki::SubjectPublicKeyInfoOwned;
use crate::Beamable;
#[derive(Sequence, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "derive", derive(Beamable))]
pub struct PrekeyBundle {
pub identity_key: SubjectPublicKeyInfoOwned,
pub signed_prekey: SubjectPublicKeyInfoOwned,
pub signed_prekey_signature: OctetString,
#[asn1(optional = "true")]
pub onetime_prekey: Option<SubjectPublicKeyInfoOwned>,
#[cfg(feature = "kem")]
#[asn1(optional = "true")]
pub pq_prekey: Option<OctetString>,
pub prekey_ids: PrekeyIdentifiers,
}
#[derive(Sequence, Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "derive", derive(Beamable))]
pub struct PrekeyIdentifiers {
pub signed_prekey_id: u32,
#[asn1(optional = "true")]
pub onetime_prekey_id: Option<u32>,
#[cfg(feature = "kem")]
#[asn1(optional = "true")]
pub pq_prekey_id: Option<u32>,
}
#[derive(Sequence, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "derive", derive(Beamable))]
pub struct PrekeyInitialMessage {
pub sender_identity: SubjectPublicKeyInfoOwned,
pub sender_ephemeral: SubjectPublicKeyInfoOwned,
pub used_prekeys: PrekeyIdentifiers,
#[cfg(feature = "kem")]
#[asn1(optional = "true")]
pub kem_ciphertext: Option<OctetString>,
pub encrypted_payload: EnvelopedData,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::der::asn1::{BitString, ObjectIdentifier};
use crate::der::{Decode, Encode};
use crate::spki::AlgorithmIdentifierOwned;
fn create_test_spki() -> SubjectPublicKeyInfoOwned {
SubjectPublicKeyInfoOwned {
algorithm: AlgorithmIdentifierOwned {
oid: ObjectIdentifier::new_unwrap("1.2.840.10045.2.1"),
parameters: None,
},
subject_public_key: BitString::from_bytes(&[0x04, 0x01, 0x02])
.expect("fixed point bytes form a valid BitString"),
}
}
#[test]
fn test_prekey_identifiers_encode_decode() -> Result<(), Box<dyn std::error::Error>> {
let ids = PrekeyIdentifiers {
signed_prekey_id: 42,
onetime_prekey_id: Some(123),
#[cfg(feature = "kem")]
pq_prekey_id: Some(999),
};
let encoded = ids.to_der()?;
let decoded = PrekeyIdentifiers::from_der(&encoded)?;
assert_eq!(ids.signed_prekey_id, decoded.signed_prekey_id);
assert_eq!(ids.onetime_prekey_id, decoded.onetime_prekey_id);
#[cfg(feature = "kem")]
assert_eq!(ids.pq_prekey_id, decoded.pq_prekey_id);
Ok(())
}
#[test]
#[ignore = "SPKI encoding needs proper EC parameters"]
fn test_prekey_bundle_minimal() -> Result<(), Box<dyn std::error::Error>> {
let bundle = PrekeyBundle {
identity_key: create_test_spki(),
signed_prekey: create_test_spki(),
signed_prekey_signature: OctetString::new([0x01, 0x02, 0x03])?,
onetime_prekey: None,
#[cfg(feature = "kem")]
pq_prekey: None,
prekey_ids: PrekeyIdentifiers {
signed_prekey_id: 1,
onetime_prekey_id: None,
#[cfg(feature = "kem")]
pq_prekey_id: None,
},
};
let encoded = bundle.to_der()?;
let decoded = PrekeyBundle::from_der(&encoded)?;
assert_eq!(bundle.prekey_ids.signed_prekey_id, decoded.prekey_ids.signed_prekey_id);
Ok(())
}
}