Commit 43c5ff3f864fddfde8a4ce4d130635c8110d8ccb
- Diff rendering mode:
- inline
- side by side
KSW.py
(167 / 35)
|   | |||
| 29 | 29 | ||
| 30 | 30 | ############################################# | |
| 31 | 31 | # Cryptosystem # | |
| 32 | ############################################# | ||
| 32 | ############################################# | ||
| 33 | 33 | ||
| 34 | class Cryptosystem: | ||
| 35 | |||
| 36 | params = None | ||
| 37 | pairing = None | ||
| 38 | # generates G | ||
| 39 | g_G = None | ||
| 40 | # generates G_p | ||
| 41 | g_G_p = None | ||
| 42 | # generates G_q | ||
| 43 | g_G_q = None | ||
| 44 | # generates G_r | ||
| 34 | class PublicKey: | ||
| 35 | g_G_p = None | ||
| 45 | 36 | g_G_r = None | |
| 46 | # random element of G_r | ||
| 47 | R0 = None | ||
| 48 | # Rs[] = ((Ri,0), (Ri, 1)) * n, R e G_r | ||
| 49 | Rs = None | ||
| 50 | # Hs[] = ((Hi,0), (Hi, 1)) * n, H e G_p | ||
| 37 | Q = None | ||
| 38 | vector = None | ||
| 39 | def __init__(self, gen_p, gen_r, Q, vector): | ||
| 40 | self.g_G_p = gen_p | ||
| 41 | self.g_G_r = gen_r | ||
| 42 | self.Q = Q | ||
| 43 | self.vector = vector | ||
| 44 | |||
| 45 | class MasterSecretKey: | ||
| 46 | p = None | ||
| 47 | q = None | ||
| 48 | r = None | ||
| 49 | g_G_q = None | ||
| 51 | 50 | Hs = None | |
| 51 | def __init__(self, p, q, r, g_G_q, Hs): | ||
| 52 | self.p = p | ||
| 53 | self.q = q | ||
| 54 | self.r = r | ||
| 55 | self.g_G_q = g_G_q | ||
| 56 | self.Hs = Hs | ||
| 57 | |||
| 58 | |||
| 59 | class Cryptosystem: | ||
| 52 | 60 | ||
| 53 | def __init__(self, i) -> "(PK, SK)": | ||
| 61 | def __init__(self, security) -> "(PK, SK)": | ||
| 62 | self.security = security | ||
| 54 | 63 | # select p, q, r | |
| 55 | 64 | p = get_random_prime(200) | |
| 56 | 65 | q = get_random_prime(200) | |
| 57 | 66 | r = get_random_prime(200) | |
| 58 | 67 | # make n | |
| 59 | n = p*q*r | ||
| 68 | self.n = p*q*r | ||
| 60 | 69 | # build the params | |
| 61 | self.params = Parameters(n=n) | ||
| 70 | params = Parameters(n=self.n) | ||
| 62 | 71 | # build the pairing | |
| 63 | 72 | self.pairing = Pairing(params) | |
| 64 | 73 | # find the generators for the G_p, G_q, and G_r subgroups | |
| 65 | self.g_G = Element.random(pairing, G1)**n | ||
| 66 | self.g_G_p = Element.random(pairing, G1)**(q*r) | ||
| 67 | self.g_G_r = Element.random(pairing, G1)**(p*q) | ||
| 68 | self.g_G_q = Element.random(pairing, G1)**(p*r) | ||
| 74 | g_G = Element.random(self.pairing, G1)**self.n | ||
| 75 | g_G_p = Element.random(self.pairing, G1)**(q*r) | ||
| 76 | g_G_r = Element.random(self.pairing, G1)**(p*q) | ||
| 77 | g_G_q = Element.random(self.pairing, G1)**(p*r) | ||
| 69 | 78 | # choose R0 | |
| 70 | self.R0 = self.g_G_r ** get_random(r) | ||
| 79 | R0 = g_G_r ** Element.random(self.pairing, Zr) | ||
| 71 | 80 | # choose the random R's | |
| 81 | Rs = [] | ||
| 82 | for i in range(security): | ||
| 83 | ri1 = g_G_r**Element.random(self.pairing, Zr) | ||
| 84 | ri2 = g_G_r**Element.random(self.pairing, Zr) | ||
| 85 | Rs.append((ri1, ri2)) | ||
| 72 | 86 | # choose the random H's | |
| 87 | Hs = [] | ||
| 88 | for i in range(security): | ||
| 89 | hi1 = g_G_p**get_random(p) | ||
| 90 | hi2 = g_G_p**get_random(p) | ||
| 91 | Hs.append((hi1, hi2)) | ||
| 73 | 92 | # calculate Q | |
| 74 | pass | ||
| 93 | Q = g_G_q * R0 | ||
| 94 | # build the vector | ||
| 95 | vector = [] | ||
| 96 | for pos, h in enumerate(Hs): | ||
| 97 | Ri = Rs[pos] | ||
| 98 | vi = (Ri[0]*h[0], Ri[1]*h[0]) | ||
| 99 | vector.append(vi) | ||
| 100 | # build the public and master secret keys | ||
| 101 | self.pk = PublicKey(g_G_p, g_G_r, Q, vector) | ||
| 102 | self.sk = MasterSecretKey(p, q, r, g_G_q, Hs) | ||
| 103 | |||
| 104 | |||
| 105 | def keygen(self, v: "description of a predicate") -> "SK_f": | ||
| 106 | R5 = self.pk.g_G_r**Element.random(self.pairing, Zr) | ||
| 107 | Q6 = self.sk.g_G_q**Element.random(self.pairing, Zr) | ||
| 108 | Rs = [] | ||
| 109 | for i in range(self.security): | ||
| 110 | # build r1 | ||
| 111 | r1 = get_random(self.sk.p) | ||
| 112 | # build r2 | ||
| 113 | r2 = get_random(self.sk.p) | ||
| 114 | Rs.append((r1, r2)) | ||
| 115 | f1 = get_random(self.sk.q) | ||
| 116 | f2 = get_random(self.sk.q) | ||
| 117 | K = R5*Q6 | ||
| 118 | for pos in range(self.security): | ||
| 119 | # get h1, h2 | ||
| 120 | h1, h2 = self.sk.Hs[pos] | ||
| 121 | # get r1, r2 | ||
| 122 | r1, r2 = Rs[pos] | ||
| 123 | # form the intermediate value | ||
| 124 | ir1 = -r1 | ||
| 125 | ir2 = -r2 | ||
| 126 | i = (h1**(-r1)) * (h2**(-r2)) | ||
| 127 | K = K * i | ||
| 128 | Ks = [] | ||
| 129 | for pos in range(self.security): | ||
| 130 | r1, r2 = Rs[pos] | ||
| 131 | K1 = (self.pk.g_G_p**r1) * (self.sk.g_G_q**(f1*v[pos])) | ||
| 132 | K2 = (self.pk.g_G_p**r2) * (self.sk.g_G_q**(f2*v[pos])) | ||
| 133 | Ks.append((K1, K2)) | ||
| 134 | return (K, Ks) | ||
| 135 | |||
| 75 | 136 | ||
| 76 | def keygen(sk: "master secret key", f: "description of a predicate") -> "SK_f": | ||
| 77 | pass | ||
| 137 | def encrypt(self, x: "vector of elements in Zr") -> "ciphertext": | ||
| 138 | s = Element.random(self.pairing, Zr) | ||
| 139 | a = Element.random(self.pairing, Zr) | ||
| 140 | b = Element.random(self.pairing, Zr) | ||
| 141 | Rs = [] | ||
| 142 | for i in range(self.security): | ||
| 143 | r1 = self.pk.g_G_r**Element.random(self.pairing, Zr) | ||
| 144 | r2 = self.pk.g_G_r**Element.random(self.pairing, Zr) | ||
| 145 | Rs.append((r1, r2)) | ||
| 146 | C0 = self.pk.g_G_p**s | ||
| 147 | Cs = [] | ||
| 148 | for i in range(self.security): | ||
| 149 | c1i = (self.pk.vector[i][0]**s) | ||
| 150 | c1i2 = (self.pk.Q**(a*x[i]))*Rs[i][0] | ||
| 151 | c1 = c1i*c1i2 | ||
| 152 | c2i = (self.pk.vector[i][1]**s) | ||
| 153 | c2i2 = (self.pk.Q**(b*x[i]))*Rs[i][1] | ||
| 154 | c2 = c2i*c2i2 | ||
| 155 | Cs.append((c1, c2)) | ||
| 156 | return (C0, Cs) | ||
| 78 | 157 | ||
| 79 | def encrypt(pk: "public key", i: "attribute", m: "message") -> "ciphertext": | ||
| 80 | pass | ||
| 81 | |||
| 82 | def decrypt(c: "ciphertext", sk_f: "secret key corresponding to predicate f") -> "message or T": | ||
| 83 | pass | ||
| 158 | def decrypt(self, c: "ciphertext", sk_f: "secret key corresponding to predicate f") -> "message or T": | ||
| 159 | output = self.pairing.apply(c[0], sk_f[0]) | ||
| 160 | for i in range(self.security): | ||
| 161 | j = self.pairing.apply(c[1][i][0], sk_f[1][i][0]) | ||
| 162 | k = self.pairing.apply(c[1][i][1], sk_f[1][i][1]) | ||
| 163 | output = output * j * k | ||
| 164 | return output | ||
| 84 | 165 | ||
| 85 | 166 | ############################################# | |
| 86 | 167 | # Test logic # | |
| 87 | 168 | ############################################# | |
| 88 | 169 | ||
| 89 | if __name__ == "__main__": | ||
| 170 | def test(): | ||
| 171 | # we're testing the ability to evaluate a polynomial, | ||
| 172 | # specifically: | ||
| 173 | # X^2 + 27X + 152 | ||
| 174 | c = Cryptosystem(3) | ||
| 175 | # build the secret key corresponding to the above polynomial | ||
| 176 | skf = c.keygen([0, 27, 152]) | ||
| 177 | print(skf) | ||
| 178 | # we now build the vector corresponding to 19, a solution to | ||
| 179 | # the above | ||
| 180 | d0 = Element(c.pairing, Zr, 19**2 % c.n) | ||
| 181 | d1 = Element(c.pairing, Zr, 19 % c.n) | ||
| 182 | d2 = Element(c.pairing, Zr, 1 % c.n) | ||
| 183 | v = [d0, d1, d2] | ||
| 184 | e = c.encrypt(v) | ||
| 185 | print(e) | ||
| 186 | # decrypt- should be 0 | ||
| 187 | print("output: ", c.decrypt(e, skf)) | ||
| 188 | |||
| 189 | def test2(): | ||
| 190 | # build the polynomial vector | ||
| 191 | Pv = [1, -27, 152] # = X^2 - 27X + 152 = (X - 8)(X - 19) | ||
| 192 | # build the X vector | ||
| 193 | Xv = [19**3, 19**2, 19**1] | ||
| 194 | # build the random primes | ||
| 195 | p = get_random_prime(100) | ||
| 196 | q = get_random_prime(100) | ||
| 197 | r = get_random_prime(100) | ||
| 198 | n = p*q*r | ||
| 199 | # build the parameters | ||
| 200 | params = Parameters(n=n) | ||
| 201 | # build the pairing | ||
| 202 | pairing = Pairing(params) | ||
| 203 | # get the generators for G_p, G_q, G_r | ||
| 204 | g_G_p = Element.random(pairing, G1)**q*r | ||
| 205 | g_G_q = Element.random(pairing, G1)**p*r | ||
| 206 | g_G_r = Element.random(pairing, G1)**p*q | ||
| 207 | # test the generators | ||
| 208 | assert(pairing.apply(g_G_p, g_G_r) == 1) | ||
| 209 | assert(pairing.apply(g_G_r, g_G_q) == 1) | ||
| 210 | # select the random integers modulo n | ||
| 211 | a = Element.random(pairing, Zr) | ||
| 212 | b = Element.random(pairing, Zr) | ||
| 213 | # get random integers modulo q | ||
| 214 | f1 = Element.random(pairing, Zr) | ||
| 215 | f2 = Element.random(pairing, Zr) | ||
| 216 | # perform the check | ||
| 217 | result = Element.zero(pairing, GT) | ||
| 218 | for pos, i in enumerate(Pv): | ||
| 219 | result += pairing.apply(g_G_q, g_G_q)**(((a*f1+b*f2)) * Xv[pos]*i) | ||
| 220 | return result | ||
| 90 | 221 | ||
| 91 | import sys | ||
| 222 | if __name__ == "__main__": | ||
| 223 | test() |
Makefile
(2 / 1)
|   | |||
| 14 | 14 | ||
| 15 | 15 | play: | |
| 16 | 16 | $(BUILD) | |
| 17 | cd $(BUILD_DIR); python3 -i -c "from pypbc import *" | ||
| 17 | cd $(BUILD_DIR); python3 -i -c "from pypbc import *; from KSW import *" | ||
| 18 | 18 | $(CLEAN) | |
| 19 | 19 | ||
| 20 | 20 | test: | |
| 21 | 21 | $(BUILD) | |
| 22 | 22 | chmod +x build/lib.linux-i686-3.0/test.py | |
| 23 | 23 | $(BUILD_DIR)/test.py -v | |
| 24 | python3 $(BUILD_DIR)/KSW.py | ||
| 24 | 25 | $(CLEAN) | |
| 25 | 26 | ||
| 26 | 27 | commit: |
pypbc.c
(39 / 12)
|   | |||
| 354 | 354 | // incref the pairing we depend on | |
| 355 | 355 | Py_INCREF(p); | |
| 356 | 356 | ||
| 357 | // set the pairing | ||
| 358 | e3->pairing = e1->pairing; | ||
| 359 | |||
| 357 | 360 | // mark it ready | |
| 358 | 361 | e3->ready = 1; | |
| 359 | 362 | ||
| … | … | ||
| 768 | 768 | // multiplies two elements | |
| 769 | 769 | // note that elements from any ring can be multiplied by those in Zr. | |
| 770 | 770 | PyObject *Element_mult(PyObject* a, PyObject *b) { | |
| 771 | // convert both objects to Elements | ||
| 771 | // convert a to an element | ||
| 772 | 772 | Element *e1 = (Element*)a; | |
| 773 | Element *e2 = (Element*)b; | ||
| 774 | // make sure they're in the same ring | ||
| 775 | if (e1->group != e2->group && e2->group != Zr) { | ||
| 776 | PyErr_SetString(PyExc_ValueError, "elements must be in the same group or Zr."); | ||
| 777 | return NULL; | ||
| 778 | } | ||
| 773 | |||
| 779 | 774 | // build the result element | |
| 780 | 775 | Element *e3 = (Element *)ElementType.tp_alloc(&ElementType, 0); | |
| 776 | |||
| 781 | 777 | // note that the result is in the same ring *and pairing* | |
| 782 | 778 | element_init_same_as(e3->pbc_element, e1->pbc_element); | |
| 783 | 779 | e3->group = e1->group; | |
| 784 | 780 | Py_INCREF(e1->pairing); | |
| 785 | 781 | e3->pairing = e1->pairing; | |
| 786 | // add the elements and store the result in e3 | ||
| 787 | if (e2->group != Zr) { | ||
| 788 | element_mul(e3->pbc_element, e1->pbc_element, e2->pbc_element); | ||
| 789 | } else { | ||
| 790 | element_mul_zn(e3->pbc_element, e1->pbc_element, e2->pbc_element); | ||
| 782 | |||
| 783 | // check to see if b is an integer | ||
| 784 | if(PyLong_Check(b)) { | ||
| 785 | // cast it to an MPZ | ||
| 786 | mpz_t i; | ||
| 787 | mpz_init(i); | ||
| 788 | pynum_to_mpz(b, i); | ||
| 789 | element_mul_mpz(e3->pbc_element, e1->pbc_element, i); | ||
| 790 | mpz_clear(i); | ||
| 791 | } else if (PyObject_TypeCheck(b, &ElementType)) { | ||
| 792 | Element *e2 = (Element*)b; | ||
| 793 | // make sure they're in the same group | ||
| 794 | if (e1->group != e2->group && e2->group != Zr) { | ||
| 795 | PyErr_SetString(PyExc_ValueError, "elements must be in the same group or Zr."); | ||
| 796 | return NULL; | ||
| 797 | } | ||
| 798 | // add the elements and store the result in e3 | ||
| 799 | if (e2->group != Zr) { | ||
| 800 | element_mul(e3->pbc_element, e1->pbc_element, e2->pbc_element); | ||
| 801 | } else { | ||
| 802 | element_mul_zn(e3->pbc_element, e1->pbc_element, e2->pbc_element); | ||
| 803 | } | ||
| 791 | 804 | } | |
| 792 | 805 | // cast and return | |
| 793 | 806 | e3->ready = 1; | |
| … | … | ||
| 834 | 834 | // raises element a to the power of b | |
| 835 | 835 | // b can be either an element or an integer | |
| 836 | 836 | PyObject *Element_pow(PyObject* a, PyObject *b, PyObject *c) { | |
| 837 | |||
| 838 | // check the types | ||
| 839 | if (!PyObject_TypeCheck(a, &ElementType)) { | ||
| 840 | PyErr_SetString(PyExc_TypeError, "Argument 1 must be an element."); | ||
| 841 | return NULL; | ||
| 842 | } | ||
| 843 | |||
| 837 | 844 | // convert a to a pbc type | |
| 838 | 845 | Element *e1 = (Element*)a; | |
| 839 | 846 | ||
| … | … | ||
| 867 | 867 | return NULL; | |
| 868 | 868 | } | |
| 869 | 869 | element_pow_zn(e3->pbc_element, e1->pbc_element, e2->pbc_element); | |
| 870 | } else { | ||
| 871 | PyErr_SetString(PyExc_TypeError, "Argument 2 must be an integer or element."); | ||
| 872 | return NULL; | ||
| 870 | 873 | } | |
| 874 | |||
| 871 | 875 | // cast and return | |
| 872 | 876 | e3->ready = 1; | |
| 873 | 877 | return (PyObject*)e3; |
setup.py
(1 / 1)
|   | |||
| 13 | 13 | author="Geremy Condra", | |
| 14 | 14 | author_email="debatem1@gmail.com", | |
| 15 | 15 | url="geremycondra.net", | |
| 16 | py_modules=["test"], | ||
| 16 | py_modules=["test", "KSW"], | ||
| 17 | 17 | ext_modules=[pbc] | |
| 18 | 18 | ) |
test.py
(31 / 0)
|   | |||
| 151 | 151 | self.e2 = Element(self.pairing, Zr, value=5) | |
| 152 | 152 | self.e3 = self.e1 * self.e2 | |
| 153 | 153 | self.failUnlessEqual(str(self.e3), "15") | |
| 154 | try: self.e3 * 5 | ||
| 155 | except: self.fail() | ||
| 156 | self.e4 = self.pairing.apply(Element.random(self.pairing, G1), Element.random(self.pairing, G2)) | ||
| 157 | self.e5 = self.pairing.apply(Element.random(self.pairing, G1), Element.random(self.pairing, G2)) | ||
| 158 | try: self.e4 * self.e5 | ||
| 159 | except: self.fail() | ||
| 154 | 160 | ||
| 155 | 161 | def test_pow(self): | |
| 156 | 162 | self.e1 = Element(self.pairing, Zr, value=3) | |
| 157 | 163 | self.e2 = Element(self.pairing, Zr, value=2) | |
| 158 | 164 | self.e3 = pow(self.e1, self.e2) | |
| 159 | 165 | self.failUnlessEqual(str(self.e3), "9") | |
| 166 | try: | ||
| 167 | self.e1**(1,2) | ||
| 168 | self.fail() | ||
| 169 | except: | ||
| 170 | pass | ||
| 160 | 171 | ||
| 161 | 172 | def test_cmp(self): | |
| 162 | 173 | self.e1 = Element.random(self.pairing, G1) | |
| … | … | ||
| 258 | 258 | ||
| 259 | 259 | # compare | |
| 260 | 260 | self.failIfEqual(temp1, temp2) | |
| 261 | |||
| 262 | def test_auth(self): | ||
| 263 | # taken from paul miller's PBC::Crypt module tutorial | ||
| 264 | params = Parameters(qbits=512, rbits=160) | ||
| 265 | pairing = Pairing(params) | ||
| 266 | p = Element.random(pairing, G2) | ||
| 267 | s = Element.random(pairing, Zr) | ||
| 268 | public_key = p**s | ||
| 269 | # not actually from a hash. I don't really care. | ||
| 270 | Q_0 = Element.from_hash(pairing, G1, "node_id=22609") | ||
| 271 | # ditto | ||
| 272 | Q_1 = Element.from_hash(pairing, G1, "node_id=9073") | ||
| 273 | d_0 = Q_0**s | ||
| 274 | d_1 = Q_1**s | ||
| 275 | k_01_a = pairing.apply(Q_0, d_1) | ||
| 276 | k_01_b = pairing.apply(d_0, Q_1) | ||
| 277 | self.failUnlessEqual(k_01_a, k_01_b) | ||
| 278 | k_10_a = pairing.apply(Q_1, d_0) | ||
| 279 | k_10_b = pairing.apply(d_1, Q_0) | ||
| 280 | self.failUnlessEqual(k_10_a, k_10_b) | ||
| 261 | 281 | ||
| 262 | 282 | ||
| 263 | 283 | if __name__ == '__main__': |

