blob: efd991d8aa97d17a1848761cedd337c2ed31f866 [file] [log] [blame]
#!/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
# WCC Group Size
PGS = 32
# WCC Field Size
PFS = 32
G1 = 2*PFS + 1
G2 = 4*PFS
# Length of hash
HASH_BYTES = 32
# AES-GCM IV length
IVL = 12
# AES Key length
PAS = 16
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 int WCC_RANDOM_GENERATE(csprng *RNG,octet* S);
extern void WCC_Hq(octet *A,octet *B,octet *C,octet *D,octet *h);
extern int WCC_GET_G2_MULTIPLE(int hashDone,octet *S,octet *ID,octet *VG2);
extern int WCC_GET_G1_MULTIPLE(int hashDone,octet *S,octet *ID,octet *VG1);
extern int WCC_GET_G1_TPMULT(int date, octet *S,octet *ID,octet *VG1);
extern int WCC_GET_G2_TPMULT(int date, octet *S,octet *ID,octet *VG2);
extern int WCC_GET_G1_PERMIT(int date,octet *S,octet *HID,octet *G1TP);
extern int WCC_GET_G2_PERMIT(int date,octet *S,octet *HID,octet *G2TP);
extern int WCC_SENDER_KEY(int date, octet *xOct, octet *piaOct, octet *pibOct, octet *PbG2Oct, octet *PgG1Oct, octet *AKeyG1Oct, octet *ATPG1Oct, octet *IdBOct, octet *AESKeyOct);
extern int WCC_RECEIVER_KEY(int date, octet *yOct, octet *wOct, octet *piaOct, octet *pibOct, octet *PaG1Oct, octet *PgG1Oct, octet *BKeyG2Oct,octet *BTPG2Oct, octet *IdAOct, octet *AESKeyOct);
extern void WCC_AES_GCM_ENCRYPT(octet *K,octet *IV,octet *H,octet *P,octet *C,octet *T);
extern void WCC_AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T);
extern void WCC_HASH_ID(octet *,octet *);
extern int WCC_RECOMBINE_G1(octet *,octet *,octet *);
extern int WCC_RECOMBINE_G2(octet *,octet *,octet *);
extern unsigned int WCC_today(void);
extern void WCC_CREATE_CSPRNG(csprng *,octet *);
extern void WCC_KILL_CSPRNG(csprng *RNG);
extern void version(char* info);
""")
if (platform.system() == 'Windows'):
libwcc = ffi.dlopen("libwcc.dll")
elif (platform.system() == 'Darwin'):
libwcc = ffi.dlopen("libwcc.dylib")
else:
libwcc = ffi.dlopen("libwcc.so")
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
build_version = ffi.new("char []", 256)
libwcc.version(build_version)
print ffi.string(build_version)
# 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
AHV = ffi.new("octet*")
AHVval = ffi.new("char []", HASH_BYTES)
AHV[0].val = AHVval
AHV[0].max = HASH_BYTES
AHV[0].len = HASH_BYTES
# 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
BHV = ffi.new("octet*")
BHVval = ffi.new("char []", HASH_BYTES)
BHV[0].val = BHVval
BHV[0].max = HASH_BYTES
BHV[0].len = HASH_BYTES
# 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
# Sender time permits
A1TPG1 = ffi.new("octet*")
A1TPG1val = ffi.new("char []", G1)
A1TPG1[0].val = A1TPG1val
A1TPG1[0].max = G1
A1TPG1[0].len = G1
A2TPG1 = ffi.new("octet*")
A2TPG1val = ffi.new("char []", G1)
A2TPG1[0].val = A2TPG1val
A2TPG1[0].max = G1
A2TPG1[0].len = G1
ATPG1 = ffi.new("octet*")
ATPG1val = ffi.new("char []", G1)
ATPG1[0].val = ATPG1val
ATPG1[0].max = G1
ATPG1[0].len = G1
# Receiver time permits
B1TPG2 = ffi.new("octet*")
B1TPG2val = ffi.new("char []", G2)
B1TPG2[0].val = B1TPG2val
B1TPG2[0].max = G2
B1TPG2[0].len = G2
B2TPG2 = ffi.new("octet*")
B2TPG2val = ffi.new("char []", G2)
B2TPG2[0].val = B2TPG2val
B2TPG2[0].max = G2
B2TPG2[0].len = G2
BTPG2 = ffi.new("octet*")
BTPG2val = ffi.new("char []", G2)
BTPG2[0].val = BTPG2val
BTPG2[0].max = G2
BTPG2[0].len = G2
# AES Keys
KEY1 = ffi.new("octet*")
KEY1val = ffi.new("char []", PAS)
KEY1[0].val = KEY1val
KEY1[0].max = PAS
KEY1[0].len = PAS
KEY2 = ffi.new("octet*")
KEY2val = ffi.new("char []", PAS)
KEY2[0].val = KEY2val
KEY2[0].max = PAS
KEY2[0].len = PAS
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
RAW = ffi.new("octet*")
RAWval = ffi.new("char [%s]" % len(seed), seed)
RAW[0].val = RAWval
RAW[0].len = len(seed)
RAW[0].max = len(seed)
if DEBUG:
print "RAW: %s" % toHex(RAW)
# random number generator
RNG = ffi.new("csprng*")
libwcc.WCC_CREATE_CSPRNG(RNG, RAW)
# Today's date in epoch days
date = libwcc.WCC_today()
if DEBUG:
print "Date %s" % date
# Hash IdA
libwcc.WCC_HASH_ID(IdA, AHV)
if DEBUG:
print "IdA: %s" % toHex(IdA)
print "AHV: %s" % toHex(AHV)
# Hash IdB
libwcc.WCC_HASH_ID(IdB, BHV)
if DEBUG:
print "IdB: %s" % toHex(IdB)
print "BHV: %s" % toHex(BHV)
# Generate master secret for MIRACL and Customer
rtn = libwcc.WCC_RANDOM_GENERATE(RNG, MS1)
if rtn != 0:
print "libwcc.WCC_RANDOM_GENERATE(RNG,MS1) Error %s", rtn
rtn = libwcc.WCC_RANDOM_GENERATE(RNG, MS2)
if rtn != 0:
print "libwcc.WCC_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 = libwcc.WCC_GET_G1_MULTIPLE(1,MS1, AHV, A1KeyG1)
if rtn != 0:
print "libwcc.WCC_GET_G1_MULTIPLE(MS1,AHV,A1KeyG1) Error %s" % rtn
rtn = libwcc.WCC_GET_G1_MULTIPLE(1,MS2, AHV, A2KeyG1)
if rtn != 0:
print "libwcc.WCC_GET_G1_MULTIPLE(MS2,AHV,A2KeyG1) Error %s" % rtn
if DEBUG:
print "A1KeyG1: %s" % toHex(A1KeyG1)
print "A2KeyG1: %s" % toHex(A2KeyG1)
# Combine Alices's sender key shares
rtn = libwcc.WCC_RECOMBINE_G1(A1KeyG1, A2KeyG1, AKeyG1)
if rtn != 0:
print "libwcc.WCC_RECOMBINE_G1(A1KeyG1, A2KeyG1, AKeyG1) Error %s" % rtn
print "AKeyG1: %s" % toHex(AKeyG1)
# Generate Alice's sender time permit shares
rtn = libwcc.WCC_GET_G1_PERMIT(date, MS1, AHV, A1TPG1)
if rtn != 0:
print "libwcc.WCC_GET_G1_PERMIT(date,MS1,AHV,A1TPG1) Error %s" % rtn
rtn = libwcc.WCC_GET_G1_PERMIT(date, MS2, AHV, A2TPG1)
if rtn != 0:
print "libwcc.WCC_GET_G1_PERMIT(date,MS2,AHV,A2TPG1) Error %s" % rtn
if DEBUG:
print "A1TPG1: %s" % toHex(A1TPG1)
print "A2TPG1: %s" % toHex(A2TPG1)
# Combine Alice's sender Time Permit shares
rtn = libwcc.WCC_RECOMBINE_G1(A1TPG1, A2TPG1, ATPG1)
if rtn != 0:
print "libwcc.WCC_RECOMBINE_G1(A1TPG1, A2TPG1, ATPG1) Error %s" % rtn
print "ATPG1: %s" % toHex(ATPG1)
# Generate Bob's receiver secret key shares
rtn = libwcc.WCC_GET_G2_MULTIPLE(1,MS1, BHV, B1KeyG2)
if rtn != 0:
print "libwcc.WCC_GET_G2_MULTIPLE(MS1,BHV,B1KeyG2) Error %s" % rtn
rtn = libwcc.WCC_GET_G2_MULTIPLE(1,MS2, BHV, B2KeyG2)
if rtn != 0:
print "libwcc.WCC_GET_G2_MULTIPLE(MS2,BHV,B2KeyG2) Error %s" % rtn
if DEBUG:
print "B1KeyG2: %s" % toHex(B1KeyG2)
print "B2KeyG2: %s" % toHex(B2KeyG2)
# Combine Bobs's receiver secret key shares
rtn = libwcc.WCC_RECOMBINE_G2(B1KeyG2, B2KeyG2, BKeyG2)
if rtn != 0:
print "libwcc.WCC_RECOMBINE_G2(B1KeyG2, B2KeyG2, BKeyG2) Error %s" % rtn
print "BKeyG2: %s" % toHex(BKeyG2)
# Generate Bob's receiver time permit shares
rtn = libwcc.WCC_GET_G2_PERMIT(date, MS1, BHV, B1TPG2)
if rtn != 0:
print "libwcc.WCC_GET_G2_PERMIT(date,MS1,BHV,B1TPG2) Error %s" % rtn
rtn = libwcc.WCC_GET_G2_PERMIT(date, MS2, BHV, B2TPG2)
if rtn != 0:
print "libwcc.WCC_GET_G2_PERMIT(date,MS2,BHV,B2TPG2) Error %s" % rtn
if DEBUG:
print "B1TPG2: %s" % toHex(B1TPG2)
print "B2TPG2: %s" % toHex(B2TPG2)
# Combine Bob's receiver time permit shares
rtn = libwcc.WCC_RECOMBINE_G2(B1TPG2, B2TPG2, BTPG2)
if rtn != 0:
print "libwcc.WCC_RECOMBINE_G2(B1TPG2, B2TPG2, BTPG2) Error %s" % rtn
print "BTPG2: %s" % toHex(BTPG2)
rtn = libwcc.WCC_RANDOM_GENERATE(RNG, X)
if rtn != 0:
print "libwcc.WCC_RANDOM_GENERATE(RNG,X) Error %s", rtn
if DEBUG:
print "X: %s" % toHex(X)
rtn = libwcc.WCC_GET_G1_TPMULT(date,X,IdA,PaG1);
if rtn != 0:
print "libwcc.WCC_GET_G1_TPMULT(date,X,IdA,PaG1) Error %s", rtn
if DEBUG:
print "PaG1: %s" % toHex(PaG1)
rtn = libwcc.WCC_RANDOM_GENERATE(RNG, W)
if rtn != 0:
print "libwcc.WCC_RANDOM_GENERATE(RNG,W) Error %s", rtn
if DEBUG:
print "W: %s" % toHex(W)
rtn = libwcc.WCC_GET_G1_TPMULT(date,W,IdA,PgG1);
if rtn != 0:
print "libwcc.WCC_GET_G1_TPMULT(date,W,IdA,PgG1) Error %s", rtn
if DEBUG:
print "PgG1: %s" % toHex(PgG1)
rtn = libwcc.WCC_RANDOM_GENERATE(RNG, Y)
if rtn != 0:
print "libwcc.WCC_RANDOM_GENERATE(RNG,Y) Error %s", rtn
if DEBUG:
print "Y: %s" % toHex(Y)
rtn = libwcc.WCC_GET_G2_TPMULT(date,Y,IdB,PbG2);
if rtn != 0:
print "libwcc.WCC_GET_G1_TPMULT(date,Y,IdB,PbG2) Error %s", rtn
if DEBUG:
print "PbG2: %s" % toHex(PbG2)
# PIA = Hq(PaG1,PbG2,PgG1,IdB)
libwcc.WCC_Hq(PaG1,PbG2,PgG1,IdB,PIA);
if DEBUG:
print "PIA: %s" % toHex(PIA)
# PIB = Hq(PbG2,PaG1,PgG1,IdA)
libwcc.WCC_Hq(PbG2,PaG1,PgG1,IdA,PIB);
if DEBUG:
print "PIB: %s" % toHex(PIB)
# Alice calculates AES Key
rtn = libwcc.WCC_SENDER_KEY(date, X, PIA, PIB, PbG2, PgG1, AKeyG1, ATPG1, IdB, KEY1)
if rtn != 0:
print "libwcc.WCC_SENDER_KEY(date, X, PIA, PIB, PbG2, PgG1, AKeyG1, ATPG1, IdB, KEY1) Error %s" % rtn
print "{0}'s AES Key: {1}".format(alice_id, toHex(KEY1))
# Bob calculates AES Key
rtn = libwcc.WCC_RECEIVER_KEY(date, Y, W, PIA, PIB, PaG1, PgG1, BKeyG2, BTPG2, IdA, KEY2)
if rtn != 0:
print "libwcc.WCC_RECEIVER_KEY(date, Y, W, PIA, PIB, PaG1, PgG1, BKeyG2, BTPG2, IdA, KEY2) Error %s" % rtn
print "{0}'s AES Key: {1}".format(bob_id, toHex(KEY2))
libwcc.WCC_KILL_CSPRNG(RNG)