1use crate::{
4 api, attr,
5 common::{
6 elgamal, kem,
7 secret::{self, DigestibleSecret},
8 },
9 id,
10 misc::{crypto, jwt},
11 servers::constellation,
12};
13
14use curve25519_dalek::Scalar;
15use sha2::digest::Digest;
16
17pub fn combine_master_enc_key_parts(
19 public_part: &elgamal::PublicKey,
20 private_part: &elgamal::PrivateKey,
21) -> elgamal::PublicKey {
22 private_part.scale(public_part)
23}
24
25pub fn master_enc_key_part_hash(part: &elgamal::PublicKey) -> id::Id {
28 b"".as_slice().derive_id(
29 sha2::Sha256::new().chain_update(part),
30 "pubhubs-master-enc-key-part-hash",
31 )
32}
33
34pub fn pseud_factor_for_hub(pseud_factor_secret: impl DigestibleSecret, hub_id: id::Id) -> Scalar {
38 pseud_factor_secret.derive_scalar(
39 sha2::Sha512::new().chain_update(hub_id.as_slice()),
40 "pubhubs-pseud-factor",
41 )
42}
43
44pub fn t_encrypted_hub_pseudonym(
47 pp: elgamal::Triple,
48 pseud_factor_secret: impl DigestibleSecret,
49 master_enc_key_part_inv: &Scalar,
50 hub_id: id::Id,
51) -> elgamal::Triple {
52 let g_h = pseud_factor_for_hub(pseud_factor_secret, hub_id);
53 pp.rsk_with_s(&g_h).and_k(master_enc_key_part_inv)
54}
55
56pub fn kem_shared_secret(
58 ss_ml: &aws_lc_rs::kem::SharedSecret,
59 ss_ec: &elgamal::SharedSecret,
60) -> kem::SharedSecret {
61 let inner: [u8; 32] = ss_ml
62 .as_ref()
63 .update_digest(
64 sha2::Sha256::new()
65 .chain_update(secret::encode_usize(ss_ec.as_bytes().len()))
66 .chain_update(ss_ec.as_bytes()),
67 "pubhubs-kem-combinator",
68 )
69 .finalize()
70 .into();
71 inner.into()
72}
73
74pub fn attr_signing_key(shared_secret: &kem::SharedSecret) -> jwt::HS256 {
79 shared_secret.derive_hs256(sha2::Sha256::new(), "pubhubs-attr-signing")
80}
81
82pub fn sealing_secret(shared_secret: &kem::SharedSecret) -> crypto::SealingKey {
84 shared_secret.derive_sealing_key(sha2::Sha256::new(), "pubhubs-sealing-secret")
85}
86
87pub fn attr_id(attr: &attr::Attr, secret: impl secret::DigestibleSecret) -> crate::id::Id {
92 secret.derive_id(
93 sha2::Sha256::new()
94 .chain_update(attr.attr_type.as_slice())
95 .chain_update(secret::encode_usize(attr.value.len()))
96 .chain_update(attr.value.as_bytes()),
97 "pubhubs-attr-id",
98 )
99}
100
101pub fn constellation_id(c: &constellation::Inner) -> id::Id {
103 b"".as_slice()
104 .derive_id(c.sha256(), "pubhubs-constellation-id")
105}
106
107pub fn encap_key_id(ek: &kem::EncapKeyBytes) -> id::Id {
109 b"".as_slice().derive_id(
111 sha2::Sha256::new()
112 .chain_update(&ek.ml[..])
113 .chain_update(&ek.ec[..]),
114 "pubhubs-encap-key-id",
115 )
116}
117
118pub fn jwt_id(jwt: &jwt::JWT) -> id::Id {
120 b"".as_slice().derive_id(jwt.sha256(), "pubhubs-jwt-id")
121}
122
123pub fn phc_user_object_hmac(
127 object_id: crate::id::Id,
128 secret: impl secret::DigestibleSecret,
129) -> crate::id::Id {
130 secret.derive_id(
131 sha2::Sha256::new().chain_update(object_id.as_slice()),
132 "pubhubs-user-object-hmac",
133 )
134}
135
136pub fn auths_attr_keys(
138 attr: attr::Attr,
139 secret: impl secret::DigestibleSecret,
140 timestamps: impl IntoIterator<Item = api::NumericDate>,
141) -> Vec<Vec<u8>> {
142 let attr_secret = attr_id(&attr, secret);
143
144 timestamps
145 .into_iter()
146 .map(|ts| {
147 attr_secret.derive_bytes(
148 sha2::Sha256::new().chain_update(ts.timestamp().to_be_bytes()),
149 "pubhubs-attr-key",
150 )
151 })
152 .collect()
153}