Identity-based Encryption¶
CrowdNotifier uses a specific identity-based encryption scheme, to ensure all security and privacy properties. In particular, CrowdNotifier uses a slight modification of the FullIdent Boneh-Franklin scheme [BF01] given by the following algorithms. (The only modification is that the randomness \(r\) now also depends on the identity \(\id\), which is passed to \(\ibedec\) for verification purposes.)
Mathematical description¶
\(\pp \gets \ibecommonsetup(1^\secpar)\). On input of security parameter \(\secpar\), generate a type III set of bilinear groups \(\group_1, \group_2, \group_T\) generated by respectively \(\generator_1, \generator_2, \generator_T\) all of prime order \(\grouporder\) and let \(\pairsym: \group_1 \times \group_2 \to \group_T\) be the corresponding pairing. Generate the following hash-functions (modeled as random oracles): \(\hash_1: \{0,1\}^* \to \group_1^*\) a hash function mapping points to the group \(\group_1^*\), \(\hash_T : \group_T \to \{0,1\}^{2\secpar}\) mapping group elements from the target group, \(\hash_3: \{0,1\}^{2\secpar} \times \bins \times \bins \to \{0,1\}^{2\secpar}\), and \(\hash_4: \{0,1\}^{2\secpar} \to \mathcal{K}\) mapping into the key-space of the authenticated encryption scheme. Setup outputs \(\pp = ((\group_1, \group_2, \group_T, \generator_1, \generator_2, \generator_T, \grouporder, \pairsym), \hash_1, \hash_T, \hash_3, \hash_4)\).
\((\masterpk, \mastersk) \gets \ibekeygen(\pp)\). Pick random \(\mastersk \gets \Zp\) and set \(\masterpk = g_2^{\mastersk} \in \group_2.\) Return \((\masterpk, \mastersk)\).
\(\skid \gets \ibekeyder(\masterpk, \mastersk, \id)\). On input of a master public key \(\masterpk\), a master private key \(\mastersk\), and an identity \(\id \in \{0, 1\}^*\); outputs private key \(\skid = \hash_1(\id)^{\mastersk} \in \group_1\).
\(\ctxt \gets \ibeenc(\masterpk, \id, m)\). On input of a master public key \(\masterpk\), an identity \(\id \in \bins\), and a message \(m\), proceed as follows. Check that \(\masterpk \in \group_2^*\). Pick a random key \(x \gets \{0, 1\}^{2\secpar}\) and compute
\[ \begin{align}\begin{aligned}c_1 &= g_2^r,\\c_2 &= x \oplus \hash_T( \pairsym(\hash_1(\id), \masterpk)^r),\\c_3 &= \aeenc(H_4(x), m)\end{aligned}\end{align} \]where \(r = \hash_3(x, m, \id)\). Return \(\ctxt = (c_1, c_2, c_3)\).
\(m \gets \ibedec(\id, \skid, \ctxt)\). On input of an identity \(\id\), a private key \(\skid\), and a ciphertext \(\ctxt\), proceed as follows. Parse \(\ctxt\) as \((c_1, c_2, c_3)\) and return \(\bot\) if parsing fails. Check that \(\skid \in \group_1^*\), and compute \(x' = c_2 \oplus \hash_T( \pairsym(\skid, c_1) )\) and \(m' = \aedec(H_4(x'), c_3)\). Return \(\bot\) if \(m' = \bot\). Finally, compute \(r' = \hash_3(x', m', \id)\) and check that \(c_1 = g_2^{r'}\). If this check fails, return \(\bot\), otherwise, return \(m'\).
Implementation of IBE in CrowdNotifier¶
The following is a list of pseudo-codes describing how the above methods can be implemented:
IBE.CommonSetup
using mcl.init:mcl.init(mcl.BLS12_381)
IBE.KeyGen
:msk = new mcl.Fr(); msk.setByCSPRNG(); mpk = mcl.mul(baseG2, msk);
IBE.KeyDer(msk, id)
:skid = mcl.mul(h1(id), msk)
IBE.Enc(mpk, id, m)
:x = randombytes_buf(NONCE_LENGTH); r = h3(x, id, m); c1 = mcl.mul(baseG2, r); c2_pair = ht(mcl.pow(mcl.pairing(h1(id), mpk), r)); c2 = xor(x, c2_pair); nonce = randombytes_buf(crypto_secretbox_NONCEBYTES); c3 = crypto_secretbox_easy(m, nonce, h4(x));
IBE.Dec(id, skid, ctxt = (c1, c2, c3))
:x_p = xor(c2, ht(mcl.pairing(skid, c1))); msg_p = crypto_secretbox_open_easy(c3, nonce, h4(x_p)); // or return _I_ on error r_p = h3(x_p, id, msg_p); c1_p = mcl.mul(baseG2, r_p); if (!c1.isEqual(c1_p)) { return _I_; } // Check that skid is in G1* if (!skid.isValidOrder() || skid.isZero()) { return _I_; } return msg_p;
With the following helper methods:
h1(id)
:h1 = mcl.hashAndMapToG1(id)
h3(x_p, id, msg_p)
:h3 = new mcl.Fr(); // The '+' concatenates the binary arrays h3.setHashOf(x_p + id + msg_p);
h4(id)
:h4 = crypto_hash_sha256(id)
ht(gt)
:ht = crypto_hash_sha256(gt.serialize())
xor(a, b)
:c[i] = a[i] ^ b[i]
baseG2
:baseG2 = new mcl.G2(); baseG2.setStr( '135270106958746661818713911601106014489002995279277524021990864' + '4239793785735715026873347600343865175952761926303160 ' + '305914434424421370997125981475378163698647032547664755865937320' + '6291635324768958432433509563104347017837885763365758 ' + '198515060228729193556805452117717163830086897821565573085937866' + '5066344726373823718423869104263333984641494340347905 ' + '927553665492332455747201965776037880757740193453592970025027978' + '793976877002675564980949289727957565575433344219582');
Serialization of Keys¶
The master public key \(\masterpk\) consists of a single element in \(\group_2\). We serialize it using the mcl
serialization function.