| #!/usr/bin/env python |
| |
| """ |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| """ |
| |
| |
| """ |
| wcc |
| |
| This module use cffi to access the c functions in the WCC library. |
| |
| There is also an example usage program in this file. |
| |
| """ |
| import cffi |
| import platform |
| |
| ffi = cffi.FFI() |
| ffi.cdef(""" |
| typedef struct { |
| unsigned int ira[21]; /* random number... */ |
| int rndptr; /* ...array & pointer */ |
| unsigned int borrow; |
| int pool_ptr; |
| char pool[32]; /* random pool */ |
| } csprng; |
| |
| typedef struct |
| { |
| int len; |
| int max; |
| char *val; |
| } octet; |
| |
| extern void CREATE_CSPRNG(csprng *R,octet *S); |
| extern void KILL_CSPRNG(csprng *R); |
| |
| extern int WCC_ZZZ_RANDOM_GENERATE(csprng *RNG,octet* S); |
| extern void WCC_ZZZ_Hq(int sha, octet *A,octet *B,octet *C,octet *D,octet *h); |
| extern void HASH_ID(int sha, octet *,octet *); |
| extern int WCC_ZZZ_GET_G2_MULTIPLE(octet *S,octet *HID,octet *VG2); |
| extern int WCC_ZZZ_GET_G1_MULTIPLE(octet *S,octet *HID,octet *VG1); |
| extern int WCC_ZZZ_SENDER_KEY(int sha, octet *xOct, octet *piaOct, octet *pibOct, octet *PbG2Oct, octet *PgG1Oct, octet *AKeyG1Oct, octet *IdBOct, octet *AESKeyOct); |
| extern int WCC_ZZZ_RECEIVER_KEY(int sha, octet *yOct, octet *wOct, octet *piaOct, octet *pibOct, octet *PaG1Oct, octet *PgG1Oct, octet *BKeyG2Oct, octet *IdAOct, octet *AESKeyOct); |
| extern void AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T); |
| extern void AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T); |
| extern int WCC_ZZZ_RECOMBINE_G1(octet *,octet *,octet *); |
| extern int WCC_ZZZ_RECOMBINE_G2(octet *,octet *,octet *); |
| |
| """) |
| |
| if (platform.system() == 'Windows'): |
| libamcl_wcc_ZZZ = ffi.dlopen("libamcl_wcc_ZZZ.dll") |
| libamcl_core = ffi.dlopen("libamcl_core.dll") |
| elif (platform.system() == 'Darwin'): |
| libamcl_wcc_ZZZ = ffi.dlopen("libamcl_wcc_ZZZ.dylib") |
| libamcl_core = ffi.dlopen("libamcl_core.dylib") |
| else: |
| libamcl_wcc_ZZZ = ffi.dlopen("libamcl_wcc_ZZZ.so") |
| libamcl_core = ffi.dlopen("libamcl_core.so") |
| |
| # Group Size |
| PGS = @NB@ |
| # Field Size |
| PFS = @NB@ |
| |
| CURVE_SECURITY = @CS@ |
| |
| if CURVE_SECURITY == 128: |
| G2 = 4 * PFS |
| HASH_TYPE_ZZZ = 32 |
| AESKEY_ZZZ = 16 |
| |
| if CURVE_SECURITY == 192: |
| G2 = 8 * PFS |
| HASH_TYPE_ZZZ = 48 |
| AESKEY_ZZZ = 24 |
| |
| if CURVE_SECURITY == 256: |
| G2 = 16 * PFS |
| HASH_TYPE_ZZZ = 64 |
| AESKEY_ZZZ = 32 |
| |
| G1 = 2 * PFS + 1 |
| |
| # AES-GCM IV length |
| IVL = 12 |
| |
| |
| def toHex(octetValue): |
| """Converts an octet type into a string |
| |
| Add all the values in an octet into an array. This arrays is then |
| converted to a string and hex encoded. |
| |
| Args:: |
| |
| octetValue. An octet type |
| |
| Returns:: |
| |
| String |
| |
| Raises: |
| Exception |
| """ |
| i = 0 |
| val = [] |
| while i < octetValue[0].len: |
| val.append(octetValue[0].val[i]) |
| i = i + 1 |
| return ''.join(val).encode("hex") |
| |
| |
| if __name__ == "__main__": |
| # Print hex values |
| DEBUG = False |
| |
| # Seed |
| seedHex = "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20" |
| seed = seedHex.decode("hex") |
| |
| # Master Secret Shares |
| MS1 = ffi.new("octet*") |
| MS1val = ffi.new("char []", PGS) |
| MS1[0].val = MS1val |
| MS1[0].max = PGS |
| MS1[0].len = PGS |
| |
| MS2 = ffi.new("octet*") |
| MS2val = ffi.new("char []", PGS) |
| MS2[0].val = MS2val |
| MS2[0].max = PGS |
| MS2[0].len = PGS |
| |
| # Alice Identity |
| alice_id = raw_input("Please enter Alice's identity:") |
| IdA = ffi.new("octet*") |
| IdAval = ffi.new("char [%s]" % len(alice_id), alice_id) |
| IdA[0].val = IdAval |
| IdA[0].max = len(alice_id) |
| IdA[0].len = len(alice_id) |
| |
| # Hash value of IdA |
| HIdA = ffi.new("octet*") |
| HIdAval = ffi.new("char []", PFS) |
| HIdA[0].val = HIdAval |
| HIdA[0].max = PFS |
| HIdA[0].len = PFS |
| |
| # Bob Identity |
| bob_id = raw_input("Please enter Bob's identity:") |
| IdB = ffi.new("octet*") |
| IdBval = ffi.new("char [%s]" % len(bob_id), bob_id) |
| IdB[0].val = IdBval |
| IdB[0].max = len(bob_id) |
| IdB[0].len = len(bob_id) |
| |
| # Hash value of IdB |
| HIdB = ffi.new("octet*") |
| HIdBval = ffi.new("char []", PFS) |
| HIdB[0].val = HIdBval |
| HIdB[0].max = PFS |
| HIdB[0].len = PFS |
| |
| # Sender keys |
| A1KeyG1 = ffi.new("octet*") |
| A1KeyG1val = ffi.new("char []", G1) |
| A1KeyG1[0].val = A1KeyG1val |
| A1KeyG1[0].max = G1 |
| A1KeyG1[0].len = G1 |
| |
| A2KeyG1 = ffi.new("octet*") |
| A2KeyG1val = ffi.new("char []", G1) |
| A2KeyG1[0].val = A2KeyG1val |
| A2KeyG1[0].max = G1 |
| A2KeyG1[0].len = G1 |
| |
| AKeyG1 = ffi.new("octet*") |
| AKeyG1val = ffi.new("char []", G1) |
| AKeyG1[0].val = AKeyG1val |
| AKeyG1[0].max = G1 |
| AKeyG1[0].len = G1 |
| |
| # Receiver keys |
| B1KeyG2 = ffi.new("octet*") |
| B1KeyG2val = ffi.new("char []", G2) |
| B1KeyG2[0].val = B1KeyG2val |
| B1KeyG2[0].max = G2 |
| B1KeyG2[0].len = G2 |
| |
| B2KeyG2 = ffi.new("octet*") |
| B2KeyG2val = ffi.new("char []", G2) |
| B2KeyG2[0].val = B2KeyG2val |
| B2KeyG2[0].max = G2 |
| B2KeyG2[0].len = G2 |
| |
| BKeyG2 = ffi.new("octet*") |
| BKeyG2val = ffi.new("char []", G2) |
| BKeyG2[0].val = BKeyG2val |
| BKeyG2[0].max = G2 |
| BKeyG2[0].len = G2 |
| |
| # AES Keys |
| KEY1 = ffi.new("octet*") |
| KEY1val = ffi.new("char []", AESKEY_ZZZ) |
| KEY1[0].val = KEY1val |
| KEY1[0].max = AESKEY_ZZZ |
| KEY1[0].len = AESKEY_ZZZ |
| |
| KEY2 = ffi.new("octet*") |
| KEY2val = ffi.new("char []", AESKEY_ZZZ) |
| KEY2[0].val = KEY2val |
| KEY2[0].max = AESKEY_ZZZ |
| KEY2[0].len = AESKEY_ZZZ |
| |
| X = ffi.new("octet*") |
| Xval = ffi.new("char []", PGS) |
| X[0].val = Xval |
| X[0].max = PGS |
| X[0].len = PGS |
| |
| Y = ffi.new("octet*") |
| Yval = ffi.new("char []", PGS) |
| Y[0].val = Yval |
| Y[0].max = PGS |
| Y[0].len = PGS |
| |
| W = ffi.new("octet*") |
| Wval = ffi.new("char []", PGS) |
| W[0].val = Wval |
| W[0].max = PGS |
| W[0].len = PGS |
| |
| PIA = ffi.new("octet*") |
| PIAval = ffi.new("char []", PGS) |
| PIA[0].val = PIAval |
| PIA[0].max = PGS |
| PIA[0].len = PGS |
| |
| PIB = ffi.new("octet*") |
| PIBval = ffi.new("char []", PGS) |
| PIB[0].val = PIBval |
| PIB[0].max = PGS |
| PIB[0].len = PGS |
| |
| PaG1 = ffi.new("octet*") |
| PaG1val = ffi.new("char []", G1) |
| PaG1[0].val = PaG1val |
| PaG1[0].max = G1 |
| PaG1[0].len = G1 |
| |
| PgG1 = ffi.new("octet*") |
| PgG1val = ffi.new("char []", G1) |
| PgG1[0].val = PgG1val |
| PgG1[0].max = G1 |
| PgG1[0].len = G1 |
| |
| PbG2 = ffi.new("octet*") |
| PbG2val = ffi.new("char []", G2) |
| PbG2[0].val = PbG2val |
| PbG2[0].max = G2 |
| PbG2[0].len = G2 |
| |
| # Assign a seed value |
| SEED = ffi.new("octet*") |
| SEEDval = ffi.new("char [%s]" % len(seed), seed) |
| SEED[0].val = SEEDval |
| SEED[0].len = len(seed) |
| SEED[0].max = len(seed) |
| if DEBUG: |
| print "SEED: %s" % toHex(SEED) |
| |
| # random number generator |
| RNG = ffi.new("csprng*") |
| libamcl_core.CREATE_CSPRNG(RNG, SEED) |
| |
| # Hash IdA |
| libamcl_core.HASH_ID(HASH_TYPE_ZZZ, IdA, HIdA) |
| if DEBUG: |
| print "IdA: %s" % toHex(IdA) |
| print "HIdA: %s" % toHex(HIdA) |
| |
| # Hash IdB |
| libamcl_core.HASH_ID(HASH_TYPE_ZZZ, IdB, HIdB) |
| if DEBUG: |
| print "IdB: %s" % toHex(IdB) |
| print "HIdB: %s" % toHex(HIdB) |
| |
| # Generate master secret for MILAGRO and Customer |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG, MS1) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG,MS1) Error %s", rtn |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG, MS2) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG,MS2) Error %s" % rtn |
| if DEBUG: |
| print "MS1: %s" % toHex(MS1) |
| print "MS2: %s" % toHex(MS2) |
| |
| # Generate Alice's sender key shares |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(MS1, HIdA, A1KeyG1) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(MS1,HIdA,A1KeyG1) Error %s" % rtn |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(MS2, HIdA, A2KeyG1) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(MS2,HIdA,A2KeyG1) Error %s" % rtn |
| if DEBUG: |
| print "A1KeyG1: %s" % toHex(A1KeyG1) |
| print "A2KeyG1: %s" % toHex(A2KeyG1) |
| |
| # Combine Alices's sender key shares |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RECOMBINE_G1(A1KeyG1, A2KeyG1, AKeyG1) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RECOMBINE_G1(A1KeyG1, A2KeyG1, AKeyG1) Error %s" % rtn |
| print "AKeyG1: %s" % toHex(AKeyG1) |
| |
| # Generate Bob's receiver secret key shares |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_GET_G2_MULTIPLE(MS1, HIdB, B1KeyG2) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_GET_G2_MULTIPLE(MS1,HIdB,B1KeyG2) Error %s" % rtn |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_GET_G2_MULTIPLE(MS2, HIdB, B2KeyG2) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_GET_G2_MULTIPLE(MS2,HIdB,B2KeyG2) Error %s" % rtn |
| if DEBUG: |
| print "B1KeyG2: %s" % toHex(B1KeyG2) |
| print "B2KeyG2: %s" % toHex(B2KeyG2) |
| |
| # Combine Bobs's receiver secret key shares |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RECOMBINE_G2(B1KeyG2, B2KeyG2, BKeyG2) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RECOMBINE_G2(B1KeyG2, B2KeyG2, BKeyG2) Error %s" % rtn |
| print "BKeyG2: %s" % toHex(BKeyG2) |
| |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG, X) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG,X) Error %s", rtn |
| if DEBUG: |
| print "X: %s" % toHex(X) |
| |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(X, HIdA, PaG1) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(X,HIdA,PaG1) Error %s", rtn |
| if DEBUG: |
| print "PaG1: %s" % toHex(PaG1) |
| |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG, W) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG,W) Error %s", rtn |
| if DEBUG: |
| print "W: %s" % toHex(W) |
| |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(W, HIdA, PgG1) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_GET_G1_MULTIPLE(W, HIdA, PgG1) Error %s", rtn |
| if DEBUG: |
| print "PgG1: %s" % toHex(PgG1) |
| |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG, Y) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RANDOM_GENERATE(RNG,Y) Error %s", rtn |
| if DEBUG: |
| print "Y: %s" % toHex(Y) |
| |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_GET_G2_MULTIPLE(Y, HIdB, PbG2) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_GET_G2_MULTIPLE(Y, HIdB, PbG2) Error %s", rtn |
| if DEBUG: |
| print "PbG2: %s" % toHex(PbG2) |
| |
| # PIA = Hq(PaG1,PbG2,PgG1,IdB) |
| libamcl_wcc_ZZZ.WCC_ZZZ_Hq(HASH_TYPE_ZZZ, PaG1, PbG2, PgG1, IdB, PIA) |
| if DEBUG: |
| print "PIA: %s" % toHex(PIA) |
| |
| # PIB = Hq(PbG2,PaG1,PgG1,IdA) |
| libamcl_wcc_ZZZ.WCC_ZZZ_Hq(HASH_TYPE_ZZZ, PbG2, PaG1, PgG1, IdA, PIB) |
| if DEBUG: |
| print "PIB: %s" % toHex(PIB) |
| |
| # Alice calculates AES Key |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_SENDER_KEY( |
| HASH_TYPE_ZZZ, |
| X, |
| PIA, |
| PIB, |
| PbG2, |
| PgG1, |
| AKeyG1, |
| IdB, |
| KEY1) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_SENDER_KEY(HASH_TYPE_ZZZ, X, PIA, PIB, PbG2, PgG1, AKeyG1, IdB, KEY1) Error %s" % rtn |
| print "{0}'s AES Key: {1}".format(alice_id, toHex(KEY1)) |
| |
| # Bob calculates AES Key |
| rtn = libamcl_wcc_ZZZ.WCC_ZZZ_RECEIVER_KEY( |
| HASH_TYPE_ZZZ, |
| Y, |
| W, |
| PIA, |
| PIB, |
| PaG1, |
| PgG1, |
| BKeyG2, |
| IdA, |
| KEY2) |
| if rtn != 0: |
| print "libamcl_wcc_ZZZ.WCC_ZZZ_RECEIVER_KEY(HASH_TYPE_ZZZ, Y, W, PIA, PIB, PaG1, PgG1, BKeyG2, IdA, KEY2) Error %s" % rtn |
| print "{0}'s AES Key: {1}".format(bob_id, toHex(KEY2)) |
| |
| libamcl_core.KILL_CSPRNG(RNG) |