Exemple #1
0
  def _generateRandomID(
      self,
      c1 = constants.CRYPTO_CHALLENGE_C1,
      c2 = constants.CRYPTO_CHALLENGE_C2):
    """Generates the NodeID by solving two cryptographic puzzles."""
    # Solve the static cryptographic puzzle.
    rsaKey = None
    p = 0x1 # non-zero value
    pub = None

    randomStream = Crypto.Random.new().read
    while not util.hasNZeroBitPrefix(p, c1):
      rsaKey = Crypto.PublicKey.RSA.generate(constants.RSA_BITS, randomStream)
      pub = str(rsaKey.n) + str(rsaKey.e)
      p = util.hsh2int(Crypto.Hash.SHA.new(Crypto.Hash.SHA.new(pub).digest()))

    # created correct NodeID
    self.rsaKey = rsaKey
    nodeID = Crypto.Hash.SHA.new(pub)

    # Solve the dynamic cryptographic puzzle.
    p, x = 0x1, None

    while not util.hasNZeroBitPrefix(p, c2):
      x = util.bin2int(util.generateRandomString(constants.ID_LENGTH))
      # This is madness!
      p = util.hsh2int(
          Crypto.Hash.SHA.new(
              util.int2bin(
                  (util.hsh2int(nodeID) ^ x))))

    # Found a correct value of X and nodeID
    self.x = x
    return nodeID.digest()
Exemple #2
0
 def _verifyID(self, nodeID, x):
   '''Verifies if a user's ID has been generated using the '''
   p1 = util.hsh2int(Crypto.Hash.SHA.new(nodeID))
   p2 = util.hsh2int(Crypto.Hash.SHA.new(
       util.int2bin((util.bin2int(nodeID) ^ x))))
   # check preceeding c_i bits in P1 and P2 using sharesXPrefices.
   return (
       util.hasNZeroBitPrefix(p1, constants.CRYPTO_CHALLENGE_C1) and
       util.hasNZeroBitPrefix(p2, constants.CRYPTO_CHALLENGE_C2))
def nandmultiply():
    '''Generates a NAND program. Outputs the string representation of a NAND
    program that takes in inputs x_0, ..., x_{127} and multiplies it with C
    mod 2^n. The output of the NAND program should be stored in variables
    y_0, ..., y_{127}. The first digit will be the least significant
    digit (ex: 110001 --> 35). Good luck!'''
    # creates a blank NAND program with n inputs and n outputs.
    prog = NANDProgram(PSET_DIM, PSET_DIM)

    # now add lines to your NAND program by calling python functions like
    # prog.NAND() or prog.OR() or other helper functions. For an example, take
    # a look at the stuff after if __name__ == '__main__': or the nand adder
    # function that we implemented.

    C_bin = util.int2bin(C, PSET_DIM)

    #column_carry = ""
    #for i in range(0, PSET_DIM):
    #column_sum = nand.allocate()
    #for j in range(0, i):
    #column_value = nand.allocate()
    #input_index = j
    #c_index = i - j
    #nand.AND(column_value, prog.input_var(input_index), C_bin[c_index])
    #nand.ADD_3(column_sum, column_sum, column_value, "0")
    prog.ONE("ONE")
    prog.ZERO("ZERO")
    prog.ONE("1")
    prog.ZERO("0")
    sum = ["ZERO"] * PSET_DIM
    for i in range(0, PSET_DIM):
        row = ["ZERO"] * i

        for j in range(0, PSET_DIM):
            elem = prog.allocate()
            prog.AND(elem, prog.input_var(i), C_bin[j])
            row.append(elem)

        row = row[:PSET_DIM]
        new_sum = mynandadder(PSET_DIM, prog, sum + row)

        for i in range(0, PSET_DIM):
            sum[i] = new_sum[i]

    for k in range(0, PSET_DIM):
        prog.OR(prog.output_var(k), "ZERO", sum[k])

    print(sum)

    # "compiles" your completed program as a NAND program string.
    return str(prog)
Exemple #4
0
def nandmultiply():
    '''Generates a NAND program. Outputs the string representation of a NAND 
    program that takes in inputs x_0, ..., x_{127} and multiplies it with C 
    mod 2^n. The output of the NAND program should be stored in variables
    y_0, ..., y_{127}. The first digit will be the least significant
    digit (ex: 110001 --> 35). Good luck!'''
    # creates a blank NAND program with n inputs and n outputs.
    prog = NANDProgram(PSET_DIM, PSET_DIM)

    # now add lines to your NAND program by calling python functions like
    # prog.NAND() or prog.OR() or other helper functions. For an example, take
    # a look at the stuff after if __name__ == '__main__': or the nand adder
    # function that we implemented.
    C_bin = util.int2bin(C, PSET_DIM)
    prog.ZERO("0")
    prog.ONE("1")

    # Need to allocate a variable to store the carry digits from previous
    # additions.

    zero_lst = []
    for i in range(0, PSET_DIM):
        zero_lst.append(prog.ZERO("0"))

    acc_lst = []

    for x in range(0, PSET_DIM):
        output = prog.CREATE(x, C_bin, PSET_DIM)
        if x == 0:
            acc_lst = prog.ADDER(zero_lst, output, PSET_DIM - 1)
        if x != 0:
            acc_lst = prog.ADDER(acc_lst, output, PSET_DIM - 1)

    for j in range(0, len(acc_lst)):
        prog.OR(prog.output_var(j), acc_lst[j], "0")

    # prog.OR(prog.output_var(PSET_DIM - 1), prog.ZERO("0"), prog.ONE("1"))
    # "compiles" your completed program as a NAND program string.
    # print(prog)

    return str(prog)
Exemple #5
0
 def getDigest(self, n = 10):
   """Gets latest n updates from friends."""
   digest = {}
   for f in self.friends:
     # update post cache
     lastKnownPost = max([0] + self.postCache[f].keys())
     # Do eventual update of cache
     #  Note: unfortunaly we can't block and wait for updates, so make do
     self.getUpdates(f, lastKnownPost)
   for f in self.friends:
     for k in self.postCache[f].keys()[-n:]:
       postID = self.postCache[f][k]['id']
       if postID in self.sharingKeys:
         self.postCache[f][k].update({'key': self.sharingKeys[postID]})
         self.postCache[f][k].update({'postp':
             self._decryptPost(
                 self.sharingKeys[postID],
                 util.int2bin(k, nbytes = constants.NONCE_LENGTH),
                 self.postCache[f][k]['post'])})
       else:
         sharingKeyName = ('%s:share:%s' % (postID, self.node.id))
         sharingKeyID = self.node.getNameID(sharingKeyName)
         def _createClosureForPSKR(postID):
           def _processSharingKeyResult(result):
             if type(result) == dict:
               for r in result:
                 if not isinstance(result[r], entangled.kademlia.contact.Contact):
                   self.sharingKeys[postID] = self.node.rsaKey.decrypt(
                       result[r][0])
             else:
               print('Could not find sharing key for: %s : %s' % (
                   util.bin2hex(postID),
                   util.bin2hex(self.node.id),
                   ))
           return _processSharingKeyResult
         self.node.iterativeFindValue(sharingKeyID).addCallback(
             _createClosureForPSKR(postID))
     # get last n from this friend
     digest[f] = self.postCache[f].items()[-n:][::-1]
   return digest
Exemple #6
0
 def post(self, content):
   """ Post some resource to the network.
   Ask the network to store some (encrypted) resource.
   Note:
   This should be encrypted with a symmetric key which will be private
   until shared through the above share() method.
   """
   newSequenceNumber = self._getSequenceNumber()
   postKey = util.generateRandomString(constants.SYMMETRIC_KEY_LENGTH)
   #nonce = util.generateRandomString(constants.NONCE_LENGTH)
   # Use sequence number as nonce - that way we dont need to include it
   nonce = util.int2bin(newSequenceNumber, nbytes = constants.NONCE_LENGTH)
   encryptedContent = self._encryptPost(postKey, nonce, content)
   postName = ('%s:post:%s' % (self.node.id, newSequenceNumber))
   postID = self.node.getNameID(postName)
   # We need to remember post keys used so we can issue sharing keys later
   self.sharingKeys[postID] = postKey
   postDefer = self.node.publishData(postName, encryptedContent)
   # update our latest sequence number
   latestName = ('%s:latest' % (self.node.id))
   latestDefer = self.node.publishData(latestName, newSequenceNumber)
   # store post key by sharing the post with ourself
   postDefer.addCallback(lambda result: self.share(postID, self.node.id))
Exemple #7
0
    return str(nand)


if __name__ == '__main__':
    # Generate the string representation of a NAND prog. that adds numbers
    addtwo = str(nandadder(2))
    print(EVAL(addtwo, '1111'))  # 0 + 1 = 1 mod 2
    print(EVAL(addtwo, '1010'))  # 1 + 1 = 2 mod 2

    addfive = str(nandadder(10))
    # Input Number 1: 11110 --> 15
    # Input Number 2: 10110 --> 13   1111010110
    # Expected Output: 28 --> 001110

    #816 0000110011
    #877 1011011011
    #    10111001011

    # You should test your implementation.
    # Again, note that the binary strings have the least significant digit first
    # Or, you can submit to gradescope and run the automatic test cases.
    prog = nandmultiply()

    for test_integer in [0, 100, 123123123]:
        print("Testing C * {}".format(test_integer))
        ans = (test_integer * C) % (2**PSET_DIM)
        print("Answer should be: {} with binary:\n{}".format(
            ans, util.int2bin(ans, PSET_DIM)))
        print("Program Output")
        print(EVAL(prog, util.int2bin(test_integer, PSET_DIM)))
        print("-" * 80)
Exemple #8
0


if __name__ == '__main__':
    # Generate the string representation of a NAND prog. that adds numbers
    #addtwo = str(nandadder(2))
    #print(EVAL(addtwo, '0010'))  # 0 + 1 = 1 mod 2
    #print(EVAL(addtwo, '1010'))  # 1 + 1 = 2 mod 2

    #addfive = str(nandadder(10))
    # Input Number 1: 11110 --> 15
    # Input Number 2: 10110 --> 13   1111010110
    # Expected Output: 28 --> 001110

    #816 0000110011
    #877 1011011011
    #    10111001011
    #print(EVAL(addfive,'00001100111011011011'))

    # You should test your implementation.
    # Again, note that the binary strings have the least significant digit first 
    # Or, you can submit to gradescope and run the automatic test cases.
    prog = nandmultiply()
    for test_integer in [0, 1, 100, 123123]:
        print("Testing C * {}".format(test_integer))
        ans = (test_integer * C) % (2 ** PSET_DIM)
        print("Answer should be: {} with binary:\n{}".format(ans, util.int2bin(ans, PSET_DIM)))
        print("Program Output")
        print(EVAL(prog, util.int2bin(test_integer, PSET_DIM)))
        print("-" * 80)