def writeToFile(self, filename): assert len(self.solution) > 0, "BF solution is empty!" assert len(self.finalMapOfBFs) > 0, "sk BF solution is empty!" # strip the set from each value newDict = {} for i,j in self.finalMapOfBFs.items(): newDict[i] = list(j)[0] # assume just one element in list # pass information to keygenOut regarding whether to treat the 'bfNum' as one value # or a list of values as in 'bfNum#0' ... 'bfNum#N' # note that this is determined by the contents of isPartOfList list for k in self.isPartOfList: for i,j in self.constraintsDictVars.items(): if k in j: if newDict[ i ].find(hashtag) == -1: newDict[ i ] += hashtag if self.solution[ i ].find(hashtag) == -1: self.solution[ i ] += hashtag BFMapForProof = bfMapKeyword + " = " + str(self.solution) + "\n" SKMapForKeygen = skBfMapKeyword + " = " + str(newDict) + "\n" # finally, write the contents of the dictionary back to the config file and close f = open(filename, 'a') if self.verbose: myLog.info("BFSolver.writeToFile: ", BFMapForProof) f.write( BFMapForProof ) if self.verbose: myLog.info("BFSolver.writeToFile: ", SKMapForKeygen) f.write( SKMapForKeygen ) f.close() return
def readConfig(filename): myLog.info("Importing file: ", filename) file = filename.split('.')[0] fileVars = importlib.import_module(file) fileKeys = dir(fileVars) return _readConfig(fileVars, fileKeys)
def construct(self, mskVars, rndVars): # Standard code below keygenVars = mskVars + rndVars alphabet = 'bf' #string.ascii_lowercase factors = [] # determine all possible mappings of blinding factors to keygen variables # as a starting point, we choose an upper bound on the number blinding factors. # idea is to let Solver tell us the minimum required that satisfies our constraints for i in range(self.bfCount): factors.append(alphabet + str(i)) # factors.append(alphabet[i]) factors.append('nil') # no blinding factor myLog.info("selected factors :", factors) # select the blinding factors Factors, self.factorsList = EnumSort('Factors', factors) myLog.info("factorList :", self.factorsList) self.nil = nil = self.factorsList[-1] # nil represents that a variable does not need to be blinded # target variables self.theVarMap = {} self.varList = [] self.mskList = [] self.nonNilList = [] self.rndList = [] for i in keygenVars: i = clean(i) j = Const(i, Factors) self.varList.append( j ) self.theVarMap[ i ] = j if i in mskVars: self.mskList.append( j ) self.nonNilList.append( j != nil ) else: self.rndList.append( j ) # extract all possible mappings for mskList orObjs = [] for i in self.mskList: varMap = [] for j in self.factorsList: if str(j) != str(nil): varMap.append( i == j ) orObjs.append( Or(varMap) ) andObjVarMap = And(orObjs) s = Solver() # enable the unsatisfiable core tracking in the solver s.set(unsat_core=True) # add vars for possible blinding factor mappings for msk s.add(andObjVarMap) # R1. msk must be unique s.add( Distinct(self.mskList) ) # R2. none of the msk variables can be mapped to nil or no blinding factors s.add( And(self.nonNilList) ) return s
def checkMskListMix(usedVars, isPartOfList): if len(isPartOfList) > 0: resultVars = list(usedVars.difference(isPartOfList)) interVars = list(usedVars.intersection(isPartOfList)) if len(resultVars) > 0 and len(interVars) > 0: myLog.info("checkMskListMix: mixing msk list vars with non-msk: automatically give it a unique BF.") return True elif len(resultVars) == 0: myLog.info("good case: can continue as before and no need to do anything special.") return False
def __attrRule(self, data): """base rule: a ==> Or(a != nil). In other words, if attr is part of LEAF, then certainly needs to be blinded. We do not allow any sk element to go unblinded.""" orObjects = [] myLog.info("ATTR Rule: ", data) for i in data: self.usedVars = self.usedVars.union([ i ]) orObjects.append(self.varMap.get(i) != self.nil) # orObjects.append(self.varMap.get(i) == nil) myLog.info("Result:", Or(orObjects)) return [ Or(orObjects) ]
def __inputCleaner(self, exprList, exprDict): for i in exprList: if (ADD in i) or (MUL in i): if self.verbose: myLog.info("Process:", i, exprDict[i]) self.__inputCleaner(exprDict[i], exprDict) replaceWithChild = None for j in exprDict[i]: if self.__similar(i, j): replaceWithChild = j; break if replaceWithChild != None: exprDict[i].remove(replaceWithChild) exprDict[i].extend(exprDict[replaceWithChild])
def __mulRule(self, data, bindList): """base rule: a * b ==> Or(And(a != nil, b == nil), And(a == nil, b != nil))""" myLog.info("MUL Rule: ", data) index = 0 orObjects = [] for x in range(len(data)): objects = [] for i,j in enumerate(data): if index == i: objects.append(self.__handleNotEqualToNil(j)) else: objects.append(self.__handleEqualToNil(j)) orObjects.append( And(objects) ) index += 1 myLog.info("MUL Result: ", Or(orObjects)) return [ Or(orObjects) ]
def clean(self): for i in self.info[self.skVars]: if self.verbose: myLog.info("Key:", i) if self.info[i].get(root) != None: self.__inputPreprocessor(self.info[i][root], self.info[i]) self.__inputCleaner(self.info[i][root], self.info[i]) keys = [root] self.__cleanDict(keys, self.info[i][root], self.info[i]) for j in self.info[i].keys(): if j not in keys: del self.info[i][j] self.__removeSymbols(self.info[i]) if self.verbose: myLog.info("RESULT: ", self.info[i]) else: # if the original is empty, then create self.info[i] = {root:['LEAF0'], 'LEAF0':[ str(i) ]}
def searchForSolution(BFSolverObj, SolverRef, skipList): """description: flush out this algorithm better """ myLog.info("<=== START ===>") myLog.info("skipList: ", skipList) satisfied, skipList2 = BFSolverObj.run(SolverRef, skipList) if satisfied: myLog.info("FINAL unsat_core=", skipList) return (True, skipList) elif satisfied == False and len(skipList2) > 0: skipList3 = list(skipList2) myLog.error("FAILED: ", skipList3) # new list of identifiers then recurse while len(skipList3) > 0: pID = str(skipList3.pop()) satisfied, newList3 = BFSolverObj.run(SolverRef, skipList + [ pID ]) if satisfied: return (True, skipList + [ pID ]) # if all combinations failed above, then continue to the next level skipList3 = list(skipList2) while len(skipList3) > 0: pID = str(skipList3.pop()) satisfied, newList4 = searchForSolution(BFSolverObj, SolverRef, skipList + [ pID ]) if satisfied: return (True, newList4) # skipList + [ pID ]) return (satisfied, None) else: myLog.error("TODO: handle this scenario.") return (satisfied, skipList)
def __addRule(self, data, excludeList): """base rule: a + b ==> And(a == b), a + b + c ==> And(a == b, a == c, b == c), etc""" myLog.info("ADD Rule: ", data) varCheck = {} objects = [] for i in data: self.usedVars = self.usedVars.union([i]) for j in data: if i in excludeList and j in excludeList: continue ii = self.varMap.get(i) jj = self.varMap.get(j) if i != j and (j != varCheck.get(i) and i != varCheck.get(j)): varCheck[ i ] = j varCheck[ j ] = i myLog.info("DEBUG: ", i, "==", j) objects.append(ii == jj) myLog.info("ADD Result: ", And(objects)) return [ And(objects) ]
def isSubset(hashList, hashDict, unsatIDs): for i in hashDict.keys(): if set(hashList).issubset( hashDict[i] ): myLog.info("Found a subset. Existing reference = ", unsatIDs[i]) return unsatIDs[i] return
def run(self, theSolver, unsat_id=None): global includeMskVarsInDict self.index = 0 self.usedBFs = set() self.theSolver = Solver() # theSolver # copy self.theSolver.set(unsat_core=True) self.theSolver.add( theSolver.assertions() ) for i in self.skList: if self.verbose: myLog.info("BFSolver: key =", i, ", info =", info[i]) refs = self.unsatIDs[i][0] if unsat_id != None and refs in unsat_id: if self.verbose: myLog.info("BFSolver: skipping :", refs,"\n") continue for j in range(len(self.constraintsDict[ i ])): if self.verbose: myLog.info("BFSolver: ref: ", refs, ", constraint: ", self.constraintsDict[i][j]) self.theSolver.assert_and_track(self.constraintsDict[i][j], refs) if self.verbose: myLog.info("\n") if self.verbose: myLog.info(self.theSolver, "\n") myLog.info(self.theSolver.check(), "\n") if self.theSolver.check() != unsat: myLog.info("<=== Interpret Results ===>") self.solution = {} self.finalMapOfBFs = {} model = self.theSolver.model() myLog.info(model) for i in self.skList: myLog.info("SK: ", i, self.unsatIDs[i], ) refs = self.unsatIDs[i][0] self.solution[ i ] = {} self.finalMapOfBFs[ i ] = set() if unsat_id != None and refs in unsat_id: myLog.info("unique blinding factor for: ", i, "\n") bfNew = self.__getPlaceholder() self.usedBFs = self.usedBFs.union([ bfNew ]) self.solution[ i ] = bfNew self.finalMapOfBFs[ i ] = self.finalMapOfBFs[ i ].union([ bfNew ]) continue for k in self.constraintsDictVars[i]: for l in model.decls(): lKey = str(l.name()) if lKey in k: myLog.info("%s = %s" % (l.name(), model[l])) lVal = str(model[l]) if lVal != 'nil': self.usedBFs = self.usedBFs.union([ lVal ]) self.solution[ i ][ lKey ] = lVal self.finalMapOfBFs[ i ] = self.finalMapOfBFs[ i ].union([ lVal ]) myLog.info("") if includeMskVarsInDict: # rare cases where msk does not show up directly in any sk elements. # We just include in dictionary to be safe for i in self.mskVars: for l in model.decls(): lKey = str(l.name()) lVal = str(model[l]) if lKey == i: self.solution[ i ] = lVal self.finalMapOfBFs[ i ] = set([ lVal ]) myLog.info("<=== Interpret Results ===>") myLog.info("Unique blinding factors: ", self.usedBFs) myLog.info("Count: ", len(self.usedBFs)) return True, None else: unsat_list = self.theSolver.unsat_core() return False, unsat_list
def rule(self, ruleType, data, retList=False, excludeList=[]): self.usedVars = set() finalConstraints = [] newData = None for i in ruleType: if ADD in i: if self.baseCase(data[i]): if retList: newData = data[i] finalConstraints += self.__addRule(data[i], excludeList) else: newRuleList, attrList = self.getFirstNonAttr(data[i]) myLog.info("newDataList=", newRuleList) myLog.info("attrList=", attrList) if len(attrList) > 0: res = self.rule(newRuleList, data, True, excludeList) # myLog.info("RESULT0: ", res[0]) # myLog.info("RESULT1: ", res[1] + attrList) data[ i ] = res[1] + attrList # updating current ADD* key/value excludeList += list(res[1]) res2 = self.rule([ i ], data, excludeList) # myLog.info("RESULT2: ", res[0], res2[0]) finalConstraints += res[0] + res2[0] else: finalConstraints += self.rule(newRuleList, data, retList, excludeList) elif MUL in i: if self.baseCase(data[i]): if retList: newData = data[i] finalConstraints += self.__mulRule(data[i], excludeList) else: myLog.info("dealing with mix modes!!!") newRuleList, attrList = self.getFirstNonAttr(data[i]) myLog.info("newDataList=", newRuleList) myLog.info("attrList=", attrList) if len(attrList) > 0: res = self.rule(newRuleList, data, True, excludeList) myLog.info("RESULT0: ", res[0]) # myLog.info("RESULT1: ", res[1] + attrList) bindList = excludeList data[ i ] = [ res[1] ] + attrList # updating current ADD* key/value myLog.info("RESULT1: ", data[i]) bindList += list(res[1]) res2 = self.rule([ i ], data, bindList) # myLog.info("RESULT2: ", res2) finalConstraints += res2[0] + res[0] myLog.info("finalConstraints: ", finalConstraints) else: finalConstraints += self.rule(newRuleList, data, retList, excludeList) elif LEAF in i: finalConstraints += self.__attrRule(data[i]) # base case elif LIST in i: for i in data[i]: #print('i: ', i) finalConstraints += self.rule(data[i].get(root), data[i]) if retList: return finalConstraints, newData return finalConstraints
theVarMap = setupBF.theVarMap nil = setupBF.nil isPartOfList = checkForLists(mskVars) print("isPartOfList: ", isPartOfList) # 2. construct rule and store for each expression index = 0 construct = ConstructRule(theVarMap, isPartOfList, nil) skList = info.get(skVars) constraintsDict = {} constraintsDictVars = {} unsatIDs = {} hashID = {} skipList = [] for i in skList: myLog.info("key: ", i) constraints = construct.rule(info[i][root], info[i]) constraintsDictVars[ i ] = construct.getUsedVars() constraintsDict[ i ] = constraints _hashID = [] unsatIDs[ i ] = [] for j in range(len(constraints)): _hashID.append(constraints[j].hash()) # determine if hashID list is a subset of another variable. # Replace the refID to minimize assert tracking issues associated with group element expressions refVal = isSubset(_hashID, hashID, unsatIDs) if refVal == None: ref = 'p' + str(index) unsatIDs[ i ].append(ref) index += 1