def _checkInitiate(self, clientID, data, host_port): cookieNonce, encryptedCookie, nonce = _initiateStruct.unpack_from(data) try: decryptedCookie = self._secretBox.decrypt(encryptedCookie, 'c' * 8 + cookieNonce) except CryptoError: return clientShortPubkey = PublicKey(decryptedCookie[:32]) serverShortKey = PrivateKey(decryptedCookie[32:]) serverShortClientShort = Box(serverShortKey, clientShortPubkey) try: decrypted = serverShortClientShort.decrypt(data[176:], 'CurveCP-client-I' + nonce) except CryptoError: return clientPubkeyString, vouchNonce, encryptedVouch, serverDomain = _initiateInnerStruct.unpack_from(decrypted) clientPubkey = PublicKey(clientPubkeyString) serverLongClientLong = Box(self.serverKey.key, clientPubkey) try: vouchKey = serverLongClientLong.decrypt(encryptedVouch, 'CurveCPV' + vouchNonce) except CryptoError: return if vouchKey != str(clientShortPubkey): return transport = CurveCPServerTransport( self.reactor, self.serverKey, self.factory, clientID, clientPubkey, host_port, serverShortClientShort, dnsToName(serverDomain)) return transport, decrypted[352:]
def decrypt(self, data, public_key, base64=True): box = Box(self._private_key, public_key) # decrypted = box.decrypt(data) if base64: decrypted = box.decrypt(data, encoder=nacl.encoding.Base64Encoder) else: decrypted = box.decrypt(data) return decrypted
def test_box_failed_decryption(skalice, pkalice, skbob, pkbob, nonce, plaintext, ciphertext): pkbob = PublicKey(pkbob, encoder=HexEncoder) skbob = PrivateKey(skbob, encoder=HexEncoder) # this cannot decrypt the ciphertext! # the ciphertext must be decrypted by (pkbob, skalice) or (pkalice, skbob) box = Box(pkbob, skbob) with pytest.raises(CryptoError): box.decrypt(ciphertext, binascii.unhexlify(nonce), encoder=HexEncoder)
class CryptoBox: # Init def __init__(self, sk=None, pk=None): # Set local Variables self._box = None self.sk = None self.pk = None # Generate key pair if nessessary if not sk or not pk: self.sk = PrivateKey.generate() self.pk = self.sk.public_key else: self.sk = sk self.pk = pk # Generate shared key / box self._box = Box(self.sk, self.pk) # Encryption def encrypt(self, plaintext, nonce=None): if not nonce: nonce = nacl.utils.random(Box.NONCE_SIZE) ciphertext = self._box.encrypt(plaintext, nonce) return ciphertext[24:] # Decryption def decrypt(self, ciphertext, nonce=None): if nonce: plaintext = self._box.decrypt(ciphertext, nonce) else: plaintext = self._box.decrypt(ciphertext) return plaintext
def authenticate(self, permissions=[]): #TODO check is needs to = None keys = PrivateKey.generate() nonce = nacl.utils.random(Box.NONCE_SIZE) payload = { 'app': { 'name': self.name, 'version': self.version, 'vendor': self.vendor, 'id': self.id }, 'publicKey': base64.b64encode(keys.public_key.__bytes__()), 'nonce': base64.b64encode(nonce), 'permissions': permissions } headers = { 'Content-Type': 'application/json' } r = self._post('auth', headers, payload) if r.status_code == 200: responseJson = r.json() cipherText = base64.b64decode(responseJson['encryptedKey']) self.token = responseJson['token'] self.permissions = responseJson['permissions'] self.publicKey = base64.b64decode(responseJson['publicKey']) box = Box(keys, PublicKey(self.publicKey)) data = box.decrypt(cipherText, nonce=nonce) self.symmetricKey = data[0:PrivateKey.SIZE] self.symmetricNonce = data[PrivateKey.SIZE:] return True else: return False
def unwrap(self): # don't process the bundle if it's not meant for us # check the key fingerprint against our own # if it doesn't match # return false #TODO: Write this code #if self.destination is not config.get('global', 'nodename'): #return False; #else: # grab my private key with open( config.get('global', 'keypath') + '/' + self.destination + '.private', 'r' ) as destinationPrivateKey: destinationKey = self.deserialize(destinationPrivateKey) # grab the origin's public key with open( config.get('global', 'keypath') + '/' + self.origin + '.public', 'r' ) as originPublicKey: originKey = self.deserialize(originPublicKey) # grab the origin's verification keyhg with open( config.get('global', 'keypath') + '/' + self.origin + '.sighex', 'r' ) as originSigHex: originSigKey = self.deserialize(originSigHex) originVerify = nacl.signing.VerifyKey(originSigKey, encoder=nacl.encoding.HexEncoder) # create a box to decrypt this sucker container = Box(destinationKey, originKey) # verify the signature rawResult = originVerify.verify(self.payload) # decrypt it rawResult = container.decrypt(rawResult) # verify the signature again result = originVerify.verify(rawResult) return result
def validate_workload(r): if "powq" in r.args and "powa" in r.args: q = base64.b64decode(r.args["powq"][0]) a = r.args["powa"][0] box = Box(SERVER_KEY, SERVER_KEY.public_key) q = box.decrypt(q).split(",") if q[1] != a: print 1 defer.returnValue(False) return # Work is expired if (float(q[0]) - time.time()) > 80: print 2 defer.returnValue(False) return ex = yield REDIS.get(":workload:%s" % r.getClientIP()) ex = ex or 1 # Work load is smaller than what we require if int(q[2]) < int(ex): defer.returnValue(False) return defer.returnValue(True) return defer.returnValue(False)
def decrypt_room_message_key(message_key_array, captain_transport_pubkey, my_room_privkey): """ Parse the message key array, do the trial decryption, and try to retrieve the room message key. Return it if found, otherwise raise NoKeyFound. """ # The array length needs to be a multiple of 72 bytes. if len(message_key_array) % 72 != 0: util.debug("Received message key array of length %d" % len(message_key_array)) raise NoKeyFound # Build our decryption box. decryption_box = Box(my_room_privkey, captain_transport_pubkey) chunks = array_chunk_generator(message_key_array, 72) # Start walking over the message key array and trial decrypt every # ciphertext till we get our key. If we finish array and still haven't # found anything, bail with NoKeyFound exception. while True: try: chunk = chunks.next() except StopIteration: # no more chunks util.debug("Walked over the whole KEY_TRANSPORT packet!") raise NoKeyFound try: room_message_key = decryption_box.decrypt(chunk) break except nacl.exceptions.CryptoError: util.debug("Walking KEY_TRANSPORT: Not our key!") # if we didn't find key in first chunk, move to next one. continue return room_message_key
def parse_messages(messages): if messages is not None: for message in messages: try: value = objects.Value() value.ParseFromString(message) try: box = Box(PrivateKey(self.signing_key.encode()), PublicKey(value.valueKey)) ciphertext = value.serializedData plaintext = box.decrypt(ciphertext) p = objects.Plaintext_Message() p.ParseFromString(plaintext) signature = p.signature p.ClearField("signature") verify_key = nacl.signing.VerifyKey(p.signed_pubkey[64:]) verify_key.verify(p.SerializeToString(), signature) h = nacl.hash.sha512(p.signed_pubkey) pow_hash = h[64:128] if int(pow_hash[:6], 16) >= 50 or hexlify(p.sender_guid) != h[:40]: raise Exception('Invalid guid') listener.notify(p.sender_guid, p.encryption_pubkey, p.subject, objects.Plaintext_Message.Type.Name(p.type), p.message) except Exception: pass signature = self.signing_key.sign(value.valueKey)[:64] self.kserver.delete(self.kserver.node.id, value.valueKey, signature) except Exception: pass
def parse_messages(messages): if messages is not None: self.log.info("retrieved %s message(s) from the dht" % len(messages)) for message in messages: try: value = objects.Value() value.ParseFromString(message) try: box = Box(PrivateKey(self.signing_key.encode()), PublicKey(value.valueKey)) ciphertext = value.serializedData plaintext = box.decrypt(ciphertext) p = objects.Plaintext_Message() p.ParseFromString(plaintext) signature = p.signature p.ClearField("signature") verify_key = nacl.signing.VerifyKey(p.signed_pubkey[64:]) verify_key.verify(p.SerializeToString(), signature) h = nacl.hash.sha512(p.signed_pubkey) pow_hash = h[64:128] if int(pow_hash[:6], 16) >= 50 or p.sender_guid.encode("hex") != h[:40]: raise Exception('Invalid guid') if p.type == objects.Plaintext_Message.Type.Value("ORDER_CONFIRMATION"): c = Contract(self.db, hash_value=unhexlify(p.subject)) c.accept_order_confirmation(self.protocol.multiplexer.ws, confirmation_json=p.message) else: listener.notify(p.sender_guid, p.encryption_pubkey, p.subject, objects.Plaintext_Message.Type.Name(p.type), p.message) except Exception: pass signature = self.signing_key.sign(value.valueKey)[:64] self.kserver.delete(self.kserver.node.id, value.valueKey, signature) except Exception: pass
def decrypt_message(encrypted_message, keying_material, private_key): encrypted_key = keying_material['encrypted_key'] message_signature = keying_material['message_signature'] temp_public_key = PublicKey( keying_material['temp_public_key'], Base64Encoder) box = PublicBox(private_key, temp_public_key) message_key = box.decrypt( encrypted_key, encoder=Base64Encoder) # We got the key, so let's get the message. message_box = nacl.secret.SecretBox(message_key) message = message_box.decrypt( encrypted_message, encoder=Base64Encoder) # Check the signature. mac_key = sha256(box._shared_key, RawEncoder) signing_key = SigningKey(mac_key) if signing_key.sign(message, Base64Encoder) != message_signature: raise SignatureError("The signature is not valid") return message
def rpc_order(self, sender, pubkey, encrypted): try: box = Box(self.signing_key.to_curve25519_private_key(), PublicKey(pubkey)) order = box.decrypt(encrypted) c = Contract(self.db, contract=json.loads(order, object_pairs_hook=OrderedDict), testnet=self.multiplexer.testnet) v = c.verify(sender.pubkey) if v is True: self.router.addContact(sender) self.log.info("received an order from %s, waiting for payment..." % sender) payment_address = c.contract["buyer_order"]["order"]["payment"]["address"] chaincode = c.contract["buyer_order"]["order"]["payment"]["chaincode"] masterkey_b = c.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"] buyer_key = derive_childkey(masterkey_b, chaincode) amount = c.contract["buyer_order"]["order"]["payment"]["amount"] listing_hash = c.contract["vendor_offer"]["listing"]["contract_id"] signature = self.signing_key.sign( str(payment_address) + str(amount) + str(listing_hash) + str(buyer_key))[:64] c.await_funding(self.get_notification_listener(), self.multiplexer.blockchain, signature, False) return [signature] else: self.log.warning("received invalid order from %s reason %s" % (sender, v)) return ["False"] except Exception, e: self.log.error("Exception (%s) occurred processing order from %s" % (e.message, sender)) return ["False"]
def rpc_message(self, sender, pubkey, encrypted): try: box = Box(PrivateKey(self.signing_key.encode(nacl.encoding.RawEncoder)), PublicKey(pubkey)) plaintext = box.decrypt(encrypted) p = PlaintextMessage() p.ParseFromString(plaintext) signature = p.signature p.ClearField("signature") verify_key = nacl.signing.VerifyKey(p.signed_pubkey[64:]) verify_key.verify(p.SerializeToString(), signature) h = nacl.hash.sha512(p.signed_pubkey) pow_hash = h[64:128] if int(pow_hash[:6], 16) >= 50 or p.sender_guid.encode("hex") != h[:40] or p.sender_guid != sender.id: raise Exception('Invalid guid') self.log.info("received a message from %s" % sender) self.router.addContact(sender) for listener in self.listeners: try: verifyObject(MessageListener, listener) listener.notify(p, signature) except DoesNotImplement: pass return ["True"] except Exception: self.log.warning("received invalid message from %s" % sender) return ["False"]
def rpc_order(self, sender, pubkey, encrypted): try: box = Box(PrivateKey(self.signing_key.encode(nacl.encoding.RawEncoder)), PublicKey(pubkey)) order = box.decrypt(encrypted) c = Contract(self.db, contract=json.loads(order, object_pairs_hook=OrderedDict), testnet=self.multiplexer.testnet) if c.verify(sender.signed_pubkey[64:]): self.router.addContact(sender) self.log.info("received an order from %s, waiting for payment..." % sender) payment_address = c.contract["buyer_order"]["order"]["payment"]["address"] chaincode = c.contract["buyer_order"]["order"]["payment"]["chaincode"] masterkey_b = c.contract["buyer_order"]["order"]["id"]["pubkeys"]["bitcoin"] buyer_key = derive_childkey(masterkey_b, chaincode) amount = c.contract["buyer_order"]["order"]["payment"]["amount"] listing_hash = c.contract["buyer_order"]["order"]["ref_hash"] signature = self.signing_key.sign( str(payment_address) + str(amount) + str(listing_hash) + str(buyer_key))[:64] c.await_funding(self.get_notification_listener(), self.multiplexer.blockchain, signature, False) return [signature] else: self.log.warning("received invalid order from %s" % sender) return ["False"] except Exception: self.log.error("unable to decrypt order from %s" % sender) return ["False"]
def _sent(res): msgA = res[0][1] self.failUnless(msgA.startswith("a0:")) pubkey1_s, boxed = parseMsgA(msgA) tpriv = self.tport2[0]["privkey"] b = Box(tpriv, PublicKey(pubkey1_s)) msgB = b.decrypt(boxed) MSTID, msgC = parseMsgB(msgB)
def test(): pk = decode_reporter_key("4e9921b2ce590bffdbd31627b60e8e1ebd2603222381a99565488833ded2cf3e") nonce = from_hex("ede1604557223f4a50bbc667647d6baeaeae4cf6f86e7079") ciphertext = from_hex("6a9b95f98cf70c4ae2f50364375d833dd807448b90aa1db80329a3db08564c147e8325029850f2586079eec7640c01ab96bb85305a47d0ea0c3df585") sk = decode_server_secret_key(None); box = Box(sk, pk) plaintext = box.decrypt(ciphertext, nonce) print(plaintext)
def decode_report(report, reporterkey, nonce, keyfile): pk = decode_reporter_key(reporterkey) sk = decode_server_secret_key(keyfile) nonce = from_hex(nonce) ciphertext = from_hex(report) box = Box(sk, pk) plaintext = box.decrypt(ciphertext, nonce) return plaintext
def on_post(self, req, resp): configuration = req.context['configuration'] if req.content_length: data = json.load(req.bounded_stream) else: raise Exception("No data.") if 'challenge' not in data: raise Exception("No challenge.") if 'uuid' not in data['challenge']: raise Exception("No UUID.") if 'nonce' not in data['challenge']: raise Exception("No nonce.") if 'response' not in data['challenge']: raise Exception("No response") db_session = req.context['db_session'] challenge = db_session.query(db.Challenge).filter(db.Challenge.uuid == data['challenge']['uuid']).first() user = challenge.user if challenge is None: raise Exception("Challenge unknown.") db_session.delete(challenge) db_session.commit() user_public_key = PublicKey(challenge.user.public_key, encoder = nacl.encoding.RawEncoder) box = Box(configuration['server_key_pair'], user_public_key) response = base64.b64decode(data['challenge']['response'].encode('utf-8')) nonce = base64.b64decode(data['challenge']['nonce'].encode('utf-8')) answer = box.decrypt(response, nonce, encoder = nacl.encoding.RawEncoder) answer_hash = nacl.hash.sha256(answer, encoder = nacl.encoding.RawEncoder) if answer_hash != challenge.answer_hash: raise Exception("Response incorrect.") user_session = db.UserSession( uuid = str(uuid.uuid4()), user = user, ip_address_hash = nacl.hash.sha256(req.remote_addr.encode('utf-8'), encoder = nacl.encoding.RawEncoder), user_agent_hash = nacl.hash.sha256(req.user_agent.encode('utf_8'), encoder = nacl.encoding.RawEncoder) ) db_session.add(user_session) db_session.commit() resp.status = falcon.HTTP_200 resp.body = json.dumps({ 'uuid': user_session.uuid })
def _sent(res): msgA = res[0][1] self.failUnless(msgA.startswith("a0:")) pubkey1_s, boxed = parseMsgA(msgA) tpriv_hex = self.tports2["local"]["retrieval"]["privkey"] tpriv = PrivateKey(tpriv_hex.decode("hex")) b = Box(tpriv, PublicKey(pubkey1_s)) msgB = b.decrypt(boxed) MSTT, msgC = parseMsgB(msgB)
def decrypt(self, encrypted, sender_pub, recipient): box = Box(secret_key(recipient), public_key(sender_pub)) if encrypted[:4] != 'msg:': raise DecryptionError try: return box.decrypt(Base64Encoder.decode(encrypted[4:])) except CryptoError: raise DecryptionError
def test_box_wrong_length(): with pytest.raises(ValueError): PublicKey(b"") with pytest.raises(TypeError): PrivateKey(b"") pub = PublicKey( b"ec2bee2d5be613ca82e377c96a0bf2220d823ce980cdff6279473edc52862798", encoder=HexEncoder, ) priv = PrivateKey( b"5c2bee2d5be613ca82e377c96a0bf2220d823ce980cdff6279473edc52862798", encoder=HexEncoder, ) b = Box(priv, pub) with pytest.raises(ValueError): b.encrypt(b"", b"") with pytest.raises(ValueError): b.decrypt(b"", b"")
def test_box_decryption_combined(skalice, pkalice, skbob, pkbob, nonce, plaintext, ciphertext): pkbob = PublicKey(pkbob, encoder=HexEncoder) skalice = PrivateKey(skalice, encoder=HexEncoder) box = Box(skalice, pkbob) combined = binascii.hexlify( binascii.unhexlify(nonce) + binascii.unhexlify(ciphertext)) decrypted = binascii.hexlify(box.decrypt(combined, encoder=HexEncoder)) assert decrypted == plaintext
def _replyWithCookie(self, data, host_port): if len(data) != _helloStruct.size: return serverExtension, clientExtension, clientShortPubkey, nonce, encrypted = _helloStruct.unpack(data) serverLongClientShort = Box(self.serverKey.key, PublicKey(clientShortPubkey)) try: serverLongClientShort.decrypt(encrypted, 'CurveCP-client-H' + nonce) except CryptoError: return serverShortKey = PrivateKey.generate() unencryptedCookie = clientShortPubkey + str(serverShortKey) cookieNonce = self.serverKey.nonce(longterm=True) cookie = cookieNonce + self._secretBox.encrypt(unencryptedCookie, 'c' * 8 + cookieNonce).ciphertext boxData = str(serverShortKey.public_key) + cookie cookiePacket = ( 'RL3aNMXK' + clientExtension + serverExtension + cookieNonce + serverLongClientShort.encrypt(boxData, 'CurveCPK' + cookieNonce).ciphertext) self.transport.write(cookiePacket, host_port)
def parse_messages(messages): if messages is not None: self.log.info("retrieved %s message(s) from the dht" % len(messages)) for message in messages: try: value = objects.Value() value.ParseFromString(message) try: box = Box(self.signing_key.to_curve25519_private_key(), PublicKey(value.valueKey)) ciphertext = value.serializedData plaintext = box.decrypt(ciphertext).decode("zlib") p = objects.PlaintextMessage() p.ParseFromString(plaintext) signature = p.signature p.ClearField("signature") verify_key = nacl.signing.VerifyKey(p.pubkey) verify_key.verify(p.SerializeToString(), signature) h = nacl.hash.sha512(p.pubkey) pow_hash = h[40:] if int(pow_hash[:6], 16) >= 50 or p.sender_guid.encode("hex") != h[:40]: raise Exception("Invalid guid") if p.type == objects.PlaintextMessage.Type.Value("ORDER_CONFIRMATION"): c = Contract( self.db, hash_value=unhexlify(p.subject), testnet=self.protocol.multiplexer.testnet ) c.accept_order_confirmation( self.protocol.get_notification_listener(), confirmation_json=p.message ) elif p.type == objects.PlaintextMessage.Type.Value("RECEIPT"): c = Contract( self.db, hash_value=unhexlify(p.subject), testnet=self.protocol.multiplexer.testnet ) c.accept_receipt( self.protocol.get_notification_listener(), self.protocol.multiplexer.blockchain, receipt_json=p.message, ) elif p.type == objects.PlaintextMessage.Type.Value("DISPUTE_OPEN"): process_dispute( json.loads(p.message, object_pairs_hook=OrderedDict), self.db, self.protocol.get_message_listener(), self.protocol.get_notification_listener(), self.protocol.multiplexer.testnet, ) else: listener.notify(p, signature) except Exception: pass signature = self.signing_key.sign(value.valueKey)[:64] self.kserver.delete(self.kserver.node.id, value.valueKey, signature) except Exception: pass
def test_box_optional_nonce( privalice, pubalice, privbob, pubbob, nonce, plaintext, ciphertext): pubbob = PublicKey(pubbob, encoder=HexEncoder) privalice = PrivateKey(privalice, encoder=HexEncoder) box = Box(privalice, pubbob) encrypted = box.encrypt(binascii.unhexlify(plaintext), encoder=HexEncoder) decrypted = binascii.hexlify(box.decrypt(encrypted, encoder=HexEncoder)) assert decrypted == plaintext
def decrypt(self, mqttpayload): image_types = { 'image/png' : 'png', 'image/jpeg' : 'jpg', 'image/jpg' : 'jpg', 'image/gif' : 'gif', } messagehex = b64decode(mqttpayload) message = nacl.signing.SignedMessage(messagehex) self.verkey.verify(message) #print "verified" box = Box(me.seckey, self.pubkey) # #CK don't like the literal 64, but I don't know where to get the symbol # plaintext = box.decrypt(message[64:]) #print "decrypted" message_data = json.loads(plaintext) #print "json out" if '_type' in message_data: tst = message_data['timestamp'] time_str = time.strftime('%H:%M', time.localtime(float(tst))) if message_data.get('_type') == 'ack': return time_str, "ACK" if message_data.get('_type') == 'see': return time_str, "SEE" if message_data.get('_type') == 'msg': message = b64decode(message_data['content']) content_type = message_data.get('content-type', 'unknown') if content_type in image_types: extension = image_types[content_type] filename = '%s-%s.%s' % (self.identifier, time.time(), extension) try: fd = open(filename, "wb") fd.write(message) fd.close() except Exception, e: return time_str, "Cannot create file %s: %s" % (filename, str(e)) return time_str, "<Incoming file stored as %s>" % filename if message_data.get('content-type') != u'text/plain; charset:"utf-8"': message = 'Unsupported content-type: %s' % message_data.get('content-type') return time_str, message
def rpc_dispute_close(self, sender, pubkey, encrypted): try: box = Box(PrivateKey(self.signing_key.encode(nacl.encoding.RawEncoder)), PublicKey(pubkey)) order = box.decrypt(encrypted) contract = json.loads(order, object_pairs_hook=OrderedDict) close_dispute(contract, self.db, self.get_message_listener(), self.get_notification_listener(), self.multiplexer.testnet) self.router.addContact(sender) self.log.info("Contract dispute closed by %s" % sender) return ["True"] except Exception: self.log.error("unable to parse disputed close message from %s" % sender) return ["False"]
def rpc_dispute_close(self, sender, pubkey, encrypted): try: box = Box(self.signing_key.to_curve25519_private_key(), PublicKey(pubkey)) res = box.decrypt(encrypted) resolution_json = json.loads(res, object_pairs_hook=OrderedDict) close_dispute(resolution_json, self.db, self.get_message_listener(), self.get_notification_listener(), self.multiplexer.testnet) self.router.addContact(sender) self.log.info("Contract dispute closed by %s" % sender) return ["True"] except Exception: self.log.error("unable to parse disputed close message from %s" % sender) return ["False"]
def test_box_decryption( privalice, pubalice, privbob, pubbob, nonce, plaintext, ciphertext): pubbob = PublicKey(pubbob, encoder=HexEncoder) privalice = PrivateKey(privalice, encoder=HexEncoder) box = Box(privalice, pubbob) nonce = binascii.unhexlify(nonce) decrypted = binascii.hexlify( box.decrypt(ciphertext, nonce, encoder=HexEncoder), ) assert decrypted == plaintext
def decrypt_from_perma_payments(ciphertext, encoder=encoding.Base64Encoder): """ Decrypt bytes encrypted by perma-payments. """ box = Box( PrivateKey( settings.PERMA_PAYMENTS_ENCRYPTION_KEYS['perma_secret_key'], encoder=encoder ), PublicKey( settings.PERMA_PAYMENTS_ENCRYPTION_KEYS['perma_payments_public_key'], encoder=encoder ) ) return box.decrypt(ciphertext, encoder=encoder)
def setUp(self): self.session_secret_key = "a7d028388e9d80f2679c236ebb2d0fedc5b7b0a28b393f6a20cc8f6be636aa71" # our public / private key box box = PrivateKey.generate() self.test_email = "*****@*****.**" self.test_username = "******" + settings.ALLOWED_DOMAINS[0] self.test_authkey = binascii.hexlify( os.urandom(settings.AUTH_KEY_LENGTH_BYTES)).decode() self.test_public_key = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() self.test_real_private_key = box.encode( encoder=nacl.encoding.HexEncoder).decode() self.test_private_key = binascii.hexlify( os.urandom(settings.USER_PRIVATE_KEY_LENGTH_BYTES)).decode() self.test_private_key_nonce = binascii.hexlify( os.urandom(settings.NONCE_LENGTH_BYTES)).decode() self.test_secret_key = binascii.hexlify( os.urandom(settings.USER_SECRET_KEY_LENGTH_BYTES)).decode() self.test_secret_key_nonce = binascii.hexlify( os.urandom(settings.NONCE_LENGTH_BYTES)).decode() self.test_user_sauce = '0865977160de11fe18806e6843bc14663433982fdeadc45c217d6127f260ff33' self.device_fingerprint = '123456' self.device_time = timezone.now() data = { 'username': self.test_username, 'email': self.test_email, 'authkey': self.test_authkey, 'public_key': self.test_public_key, 'private_key': self.test_private_key, 'private_key_nonce': self.test_private_key_nonce, 'secret_key': self.test_secret_key, 'secret_key_nonce': self.test_secret_key_nonce, 'user_sauce': self.test_user_sauce, } url = reverse('authentication_register') response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.user_obj = models.User.objects.get(username=self.test_username) self.user_obj.is_email_active = True self.user_obj.save() # encrypt authorization validator with session key secret_box = nacl.secret.SecretBox(self.session_secret_key, encoder=nacl.encoding.HexEncoder) authorization_validator_nonce = nacl.utils.random( nacl.secret.SecretBox.NONCE_SIZE) authorization_validator_nonce_hex = nacl.encoding.HexEncoder.encode( authorization_validator_nonce) encrypted = secret_box.encrypt( json.dumps({}).encode("utf-8"), authorization_validator_nonce) authorization_validator = encrypted[len(authorization_validator_nonce ):] authorization_validator_hex = nacl.encoding.HexEncoder.encode( authorization_validator) self.authorization_validator = json.dumps({ 'text': authorization_validator_hex.decode(), 'nonce': authorization_validator_nonce_hex.decode(), }) # our public / private key box box = PrivateKey.generate() # our hex encoded public / private keys user_session_private_key_hex = box.encode( encoder=nacl.encoding.HexEncoder).decode() user_session_public_key_hex = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() server_crypto_box = Box( PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder), PublicKey(settings.PUBLIC_KEY, encoder=nacl.encoding.HexEncoder)) login_info_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) encrypted = server_crypto_box.encrypt( json.dumps({ 'username': self.test_username, 'authkey': self.test_authkey, 'device_fingerprint': self.device_fingerprint, 'device_time': str(self.device_time), }).encode("utf-8"), login_info_nonce) login_info_encrypted = encrypted[len(login_info_nonce):] data = { 'login_info': nacl.encoding.HexEncoder.encode(login_info_encrypted).decode(), 'login_info_nonce': nacl.encoding.HexEncoder.encode(login_info_nonce).decode(), 'public_key': user_session_public_key_hex, } url = reverse('authentication_login') response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) request_data = json.loads( server_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( response.data.get('login_info').decode()), nacl.encoding.HexEncoder.decode( response.data.get('login_info_nonce').decode())).decode()) self.token_key = request_data.get('token', False) server_public_key_hex = request_data.get('session_public_key', False) # lets encrypt our token user_private_key = PrivateKey(self.test_real_private_key, encoder=nacl.encoding.HexEncoder) user_session_private_key = PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder) server_public_key = PublicKey(server_public_key_hex, encoder=nacl.encoding.HexEncoder) # create both our crypto boxes user_crypto_box = Box(user_private_key, server_public_key) session_crypto_box = Box(user_session_private_key, server_public_key) # decrypt session secret session_secret_key_nonce_hex = request_data.get( 'session_secret_key_nonce', False) session_secret_key_nonce = nacl.encoding.HexEncoder.decode( session_secret_key_nonce_hex) session_secret_key_hex = request_data.get('session_secret_key', False) session_secret_key = nacl.encoding.HexEncoder.decode( session_secret_key_hex) decrypted_session_key_hex = session_crypto_box.decrypt( session_secret_key, session_secret_key_nonce) # decrypt user validator user_validator_nonce_hex = request_data.get('user_validator_nonce', False) user_validator_nonce = nacl.encoding.HexEncoder.decode( user_validator_nonce_hex) user_validator_hex = request_data.get('user_validator', False) user_validator = nacl.encoding.HexEncoder.decode(user_validator_hex) decrypted_user_validator = user_crypto_box.decrypt( user_validator, user_validator_nonce) # encrypt user validator with session key verification_nonce = nacl.utils.random( nacl.secret.SecretBox.NONCE_SIZE) self.verification_nonce_hex = nacl.encoding.HexEncoder.encode( verification_nonce) self.decrypted_session_key = nacl.encoding.HexEncoder.decode( decrypted_session_key_hex) self.secret_box = nacl.secret.SecretBox(self.decrypted_session_key) encrypted = self.secret_box.encrypt(decrypted_user_validator, verification_nonce) verification = encrypted[len(verification_nonce):] self.verification_hex = nacl.encoding.HexEncoder.encode(verification)
def handle(self, *args, **options): # pylint: disable=too-many-locals, too-many-branches, too-many-statements source = options['source'] supports_json = install_supports_jsonfield() # Remove bundles if options['skip_bundle']: print 'Skipped inspecting and removing DataBundle objects.' else: deleted = 0 partial_bundles = 0 to_delete = [] index = 0 total = DataBundle.objects.all().count() while index < total: print 'Inspecting DataBundle ' + str(index) + ' of ' + str( total) for bundle in DataBundle.objects.all().order_by( 'recorded')[index:(index + PAGE_SIZE)]: if supports_json is False: bundle.properties = json.loads(bundle.properties) if bundle.encrypted: if 'nonce' in bundle.properties and 'encrypted' in bundle.properties: payload = base64.b64decode( bundle.properties['encrypted']) nonce = base64.b64decode( bundle.properties['nonce']) private_key = PrivateKey(base64.b64decode(settings.PDK_SERVER_KEY).strip()) # pylint: disable=line-too-long public_key = PublicKey(base64.b64decode(settings.PDK_CLIENT_KEY).strip()) # pylint: disable=line-too-long box = Box(private_key, public_key) decrypted_message = box.decrypt(payload, nonce) decrypted = six.text_type(decrypted_message, encoding='utf8') bundle.properties = json.loads(decrypted) elif 'encrypted' in bundle.properties: print 'Missing "nonce" in encrypted bundle. Cannot decrypt bundle ' + str( bundle.pk) + '. Skipping...' break elif 'nonce' in bundle.properties: print 'Missing "encrypted" in encrypted bundle. Cannot decrypt bundle ' + str( bundle.pk) + '. Skipping...' break total_points = len(bundle.properties) for data_point in bundle.properties: if source == data_point['passive-data-metadata'][ 'source']: total_points -= 1 if total_points == 0: to_delete.append(bundle.pk) elif total_points != len(bundle.properties): partial_bundles += 1 index += PAGE_SIZE for bundle_pk in to_delete: DataBundle.objects.get(pk=bundle_pk).delete() print 'Removed ' + str(len(to_delete)) + ' DataBundle objects.' print 'Found ' + str( partial_bundles) + ' partial DataBundle objects (not removed).' source_reference = DataSourceReference.reference_for_source(source) if source_reference is not None: deleted = DataPoint.objects.filter( source_reference=source_reference).delete() print 'Removed ' + str( deleted[0]) + ' DataPoint objects by source reference.' source_reference.delete() print 'Removed DataSourceReference object.' points_query = DataPoint.objects.filter(source=source) index = 0 total = points_query.count() print 'Matching DataPoint objects by source identifier: ' + str(total) to_delete = [] while index < total: print 'Queuing DataPoint objects for deletion: ' + str( index) + ' of ' + str(total) for point in points_query.order_by('pk')[index:(index + PAGE_SIZE)]: to_delete.append(point.pk) index += PAGE_SIZE index = 0 total = len(to_delete) while index < total: print 'Removing DataPoint objects: ' + str(index) + ' of ' + str( total) for point_pk in to_delete[index:(index + PAGE_SIZE)]: DataPoint.objects.get(pk=point_pk).delete() index += PAGE_SIZE print 'Removed ' + str( len(to_delete)) + ' DataPoint objects by source match.' source_obj = DataSource.objects.filter(identifier=source).first() if source_obj is not None: deleted = DataSourceAlert.objects.filter( data_source=source_obj).delete() print 'Removed ' + str( deleted[0]) + ' DataSourceAlert objects by source match.' source_obj.delete() print 'Removed DataSource object.'
class SyncRemoteManager(BaseCASManager): def __init__(self, addr=('127.0.0.1', 10811), save_file=None): BaseCASManager.__init__(self) self.addr = addr if not save_file: if isinstance(addr, str): save_file = addr.replace('/', '_') + '.vac' else: save_file = '%s_%s.vac' % self.addr self.save_file = save_file self.sock = None self.rfile = self.wfile = None self._record = None self._changed = False self.server_box = None self.use_encryption = ENCRYPTION self.cache = Cache(maxsize=256) def load(self, return_file=False): try: fp = open(self.save_file, 'rb') if return_file: return fp with fp: return CasDir.from_bytes(fp.read()) except FileNotFoundError: if return_file: return None return CasDir.from_dict({}) def save(self): if self._changed: rec = self.record parent = self.load(return_file=True) if parent: rec.parent, level = self.writefile(parent, blocksize=4096) parent.close() val = rec.to_bytes() with open(self.save_file, 'wb') as fp: fp.write(rec.to_bytes()) self._changed = False @property def record(self): if self._record is None: self._record = self.load() return self._record @record.setter def record(self, rec): self._record = rec def save_file_data(self, path, meta, buf, cipher=None, subdir=False): hist = BaseCASManager.save_file_data(self, path, meta, buf, cipher=cipher) if not subdir: self.record.files[hist.path] = hist.to_bytes() self._changed = True return hist def open(self, filename, mode=Perm.read, owner=Owner.ALL, rev=None): try: hist = self.record.get_file(filename) except KeyError: if mode == Perm.read: raise FileNotFoundError(filename) else: hist = CasHistoryInfo.from_dict({'path': filename}) hist.history_key = self.record.parent return VersionedFile(self, filename, mode=mode, rev=rev, file_info=hist) def _negotiate_encryption(self, server_pub_key, server_auth=None): six.print_('server public_key: %s' % server_pub_key.hex()) self.server_box = None if blake2b(server_pub_key + get_cas_secret(), encoder=RawEncoder) != server_auth: raise RuntimeError('Bad Server Auth! %s' % server_auth) self.private_key = PrivateKey.generate() my_pub_key = bytes(self.private_key.public_key) six.print_('client public_key: %s' % my_pub_key.hex()) auth = blake2b(my_pub_key + get_cas_secret(), encoder=RawEncoder) self._send(b'N' + my_pub_key + auth) resp = self.rfile.read(2) if resp == b'OK': self.server_box = Box(self.private_key, PublicKey(server_pub_key)) else: six.print_(resp) def connect(self): if isinstance(self.addr, str) and self.addr.startswith('/'): self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) self.sock.connect(self.addr) else: self.sock = socket.create_connection(self.addr) self.rfile = self.sock.makefile('rb') self.wfile = self.sock.makefile('wb') line = self.rfile.read(64) six.print_('connected to %s:%s' % (self.addr, line.hex())) if self.use_encryption: public_key, auth = line[:32], line[32:] self._negotiate_encryption(public_key, auth) def _decrypt(self, message): if self.server_box: return self.server_box.decrypt(message) else: return message def readblock(self, key, verify=False): # block = self.cache.get(key) block = None if block is None: message = b'R %s\n' % key self._send(message) resp = self.rfile.read(4) if resp != b'ERRR': length = struct.unpack('>I', resp)[0] block = self._decrypt(self.rfile.read(length)) if verify: if self._hash_block(block) != key[1:]: raise Exception('Bad block!') self.cache.set(key, block) else: block = None return block def writeblock(self, level, block): key = struct.pack('>B20s', level, self._hash_block(block)) if not self.cache.get(key): message = b'W %s\n' % struct.pack('>BI', level, len(block)) message += block self._send(message) length = struct.unpack('>I', self.rfile.read(4))[0] key = self._decrypt(self.rfile.read(length)) assert len(key) == 21, key self.cache.set(key, block) return key def walkblocks(self, key): message = b'T %s\n' % key self._send(message) while 1: resp = self.rfile.read(4) if resp == b'\x00\x00\x00\x00': break if resp != b'ERRR': length = struct.unpack('>I', resp)[0] block = self._decrypt(self.rfile.read(length)) yield block else: yield None break def missing(self, keys): missing = [] while keys: to_check, keys = keys[:10000], keys[10000:] message = b'H ' + b''.join(to_check) self._send(message) while 1: resp = self.rfile.read(21) if resp != b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00': missing.append(resp) else: break return missing def get_stats(self): import json message = b'S\n' self._send(message) return json.loads(self.rfile.readline().decode('utf8')) def _send(self, message): if not self.sock: self.connect() if self.server_box: message = self.server_box.encrypt(message) lm = len(message) mess = struct.pack('>I', lm) + message self.wfile.write(mess) self.wfile.flush() def close(self): if self._record: self.save() self._send(b'Q\n') self.wfile.close() self.rfile.close() self.sock.close() self.sock = None def __enter__(self): if not self.sock: self.connect() return self def __exit__(self, exc_type, exc, tb): self.close() if exc: six.reraise(exc_type, exc, tb)
def handle(self): (packet_id, data) = receive_packet(self.request) if packet_id == PACKET_ID_REGISTRATION_REQUEST: client_pk = data[0:PUBLICKEY_BYTES] client_nonce = data[PUBLICKEY_BYTES:PUBLICKEY_BYTES + NONCE_BYTES] client_mail_crypt = data[PUBLICKEY_BYTES + NONCE_BYTES:] box = Box(server_sk, PublicKey(client_pk)) client_mail = box.decrypt(client_mail_crypt, client_nonce) client_mail = parseaddr(client_mail)[1] if '@' not in client_mail: raise UserWarning("Invalid mail address") client_mail_hash = hashlib.sha512(client_mail).hexdigest() return_code = 0 _global_db_write_lock.acquire(True) try: # make sure the lock will be released again if os.path.isfile(STORAGE_PIR_DIR + client_mail_hash): # do not allow reregistrations when the registration # is already done return_code = 1 elif os.path.isfile(STORAGE_REGISTRATION_DIR + client_mail_hash): # get the stored token with open(STORAGE_REGISTRATION_DIR + client_mail_hash, 'rb') as f: storage_data = f.read() storage_pk = storage_data[0:PUBLICKEY_BYTES] storage_token = storage_data[PUBLICKEY_BYTES:\ PUBLICKEY_BYTES+TOKEN_BYTES] if not compare_bytes(storage_pk, client_pk): return_code = 2 else: client_token = storage_token else: # only generate a token if none has been created yet client_token = nacl.utils.random(TOKEN_BYTES) with open(STORAGE_REGISTRATION_DIR + client_mail_hash, 'wb') as f: f.write(client_pk + client_token) finally: _global_db_write_lock.release() # TODO: send token via mail if return_code == 0: print "[TOKEN] for `" + client_mail + "`: " + client_token.encode( 'hex') else: print "Not printing token because return_code is " +\ str(return_code) # send back the return code return_code_encrypted = box.encrypt( to_byte(return_code), increase_nonce(client_nonce)).ciphertext # we use 11 as our packed id for the response data = to_byte(PACKET_ID_REGISTRATION_REQUEST_ACK) +\ return_code_encrypted self.request.sendall(itonb(len(data)) + data) elif packet_id == PACKET_ID_REGISTRATION_TOKEN: client_pk = data[0:PUBLICKEY_BYTES] client_nonce = data[PUBLICKEY_BYTES:PUBLICKEY_BYTES + NONCE_BYTES] client_data_crypt = data[PUBLICKEY_BYTES + NONCE_BYTES:] box = Box(server_sk, PublicKey(client_pk)) client_data = box.decrypt(client_data_crypt, client_nonce) client_token = client_data[0:TOKEN_BYTES] client_mail = client_data[TOKEN_BYTES:] client_mail = parseaddr(client_mail)[1] if '@' not in client_mail: raise UserWarning("Invalid mail address") client_mail_hash = hashlib.sha512(client_mail).hexdigest() return_code = 0 return_msg = "" if os.path.isfile(STORAGE_PIR_DIR + client_mail_hash): return_code = 1 return_msg = 'the registration was already completed successfully' if return_code == 0: _global_db_write_lock.acquire(True) try: # make sure the lock will be released again with open(STORAGE_REGISTRATION_DIR + client_mail_hash, 'rb') as f: storage_data = f.read() finally: _global_db_write_lock.release() storage_pk = storage_data[0:PUBLICKEY_BYTES] storage_token = storage_data[PUBLICKEY_BYTES:PUBLICKEY_BYTES+\ TOKEN_BYTES] if not compare_bytes(storage_token, client_token): return_code = 2 return_msg = 'invalid token' if not compare_bytes(storage_pk, client_pk): return_code = 3 return_msg = 'wrong public key' if return_code == 0: # create the file that will be send when contacts query for an # email address _global_db_write_lock.acquire(True) try: # make sure the lock will be released again with open(STORAGE_PIR_DIR + client_mail_hash, 'wb') as f: f.write(client_pk) finally: _global_db_write_lock.release() # update PIR manifest update_pir_manifest() # delete the file from the registration process which is not # needed any more _global_db_write_lock.acquire(True) try: # make sure the lock will be released again os.remove(STORAGE_REGISTRATION_DIR + client_mail_hash) finally: _global_db_write_lock.release() print "Return code", return_code, return_msg # send back the return code return_code_encrypted = box.encrypt( to_byte(return_code), increase_nonce(client_nonce)).ciphertext # add the packet id data = to_byte(PACKET_ID_REGISTRATION_TOKEN_ACK) +\ return_code_encrypted self.request.sendall(itonb(len(data)) + data) elif packet_id == PACKET_ID_UPDATE_PK_REQUEST: offset = 0 client_pk = data[offset:offset + PUBLICKEY_BYTES] offset += PUBLICKEY_BYTES client_nonce = data[offset:offset + NONCE_BYTES] offset += NONCE_BYTES client_mail_raw = data[offset:offset + SHA512HASH_BYTES] client_mail_hash = binascii.hexlify(client_mail_raw).decode( 'ascii') offset += SHA512HASH_BYTES client_data_crypt = data[offset:] box = Box(server_sk, PublicKey(client_pk)) client_tmp_pk_raw = box.decrypt(client_data_crypt, client_nonce) box = None assert len(client_tmp_pk_raw) == PUBLICKEY_BYTES tmp_sk = PrivateKey.generate() tmp_pk_raw =\ tmp_sk.public_key.encode(encoder=nacl.encoding.RawEncoder) client_nonce = increase_nonce(client_nonce) tmp_box1 = Box(server_sk, PublicKey(client_tmp_pk_raw)) ciphertext = tmp_box1.encrypt(tmp_pk_raw, client_nonce).ciphertext tmp_box1 = None data = to_byte(PACKET_ID_UPDATE_PK_RESPONSE) + ciphertext self.request.sendall(itonb(len(data)) + data) (packet_id, data) = receive_packet(self.request) if packet_id != PACKET_ID_UPDATE_PK_SEND_DATA: raise UserWarning("Unexpected packet id.") client_nonce = increase_nonce(client_nonce) tmp_box2 = Box(tmp_sk, PublicKey(client_tmp_pk_raw)) profile_data = tmp_box2.decrypt(data, client_nonce) return_code = 0 if not os.path.isfile(STORAGE_PIR_DIR + client_mail_hash): # the registration is not completed yet return_code = 1 if return_code == 0: _global_db_write_lock.acquire(True) try: # make sure the lock will be released again with open(STORAGE_PIR_DIR + client_mail_hash, 'rb') as f: storage_data = f.read() finally: _global_db_write_lock.release() assert len(storage_data) >= PUBLICKEY_BYTES storage_pk = storage_data[0:PUBLICKEY_BYTES] # the client needs to verify it's identity against the server assert compare_bytes(profile_data[0:PUBLICKEY_BYTES], storage_pk) if len(storage_data) > PUBLICKEY_BYTES and compare_bytes( profile_data[PUBLICKEY_BYTES:PUBLICKEY_BYTES + NONCE_BYTES], storage_data[PUBLICKEY_BYTES:PUBLICKEY_BYTES + NONCE_BYTES]): # the nonce has to change to avoid leaking information about # the size of the friend list return_code = 2 # write the profile data sent by the client _global_db_write_lock.acquire(True) try: # make sure the lock will be released again with open(STORAGE_PIR_DIR + client_mail_hash, 'wb') as f: f.write(profile_data) except: return_code = 3 finally: _global_db_write_lock.release() update_pir_manifest() # send back the return code return_code_encrypted = tmp_box2.encrypt( to_byte(return_code), increase_nonce(client_nonce)).ciphertext tmp_box2 = None # add the packet id data = to_byte(PACKET_ID_UPDATE_PK_SEND_DATA_ACK) +\ return_code_encrypted self.request.sendall(itonb(len(data)) + data) elif packet_id == PACKET_ID_SEND_MSG: client_pk = data[0:PUBLICKEY_BYTES] client_nonce = data[PUBLICKEY_BYTES:PUBLICKEY_BYTES + NONCE_BYTES] client_data_crypt = data[PUBLICKEY_BYTES + NONCE_BYTES:] box = Box(server_sk, PublicKey(client_pk)) request = from_byte(box.decrypt(client_data_crypt, client_nonce)) assert request == 0 tmp_sk = PrivateKey.generate() tmp_pk_raw =\ tmp_sk.public_key.encode(encoder=nacl.encoding.RawEncoder) client_nonce = increase_nonce(client_nonce) ciphertext = box.encrypt(tmp_pk_raw, client_nonce).ciphertext box = None data = to_byte(PACKET_ID_SEND_MSG_RESPONSE) + ciphertext self.request.sendall(itonb(len(data)) + data) (packet_id, data) = receive_packet(self.request) if packet_id != PACKET_ID_SEND_MSG_DATA: raise UserWarning("Unexpected packet id.") client_nonce = increase_nonce(client_nonce) tmp_box1 = Box(tmp_sk, PublicKey(client_pk)) data = tmp_box1.decrypt(data, client_nonce) channel = data[:128] msg = data[128:] return_code = 0 print "WRITING TO CHANNEL", channel # write message sent by the client _global_db_write_lock.acquire(True) try: # make sure the lock will be released again with open(STORAGE_CHANNELS_DIR + channel, 'ab+') as f: f.write(itonb(len(msg)) + msg) except: return_code = 1 finally: _global_db_write_lock.release() # send back the return code return_code_encrypted = tmp_box1.encrypt( to_byte(return_code), increase_nonce(client_nonce)).ciphertext tmp_box1 = None # add the packet id data = to_byte(PACKET_ID_SEND_MSG_DATA_ACK) +\ return_code_encrypted self.request.sendall(itonb(len(data)) + data) elif packet_id == PACKET_ID_RECV_MSG: client_pk = data[0:PUBLICKEY_BYTES] client_nonce = data[PUBLICKEY_BYTES:PUBLICKEY_BYTES + NONCE_BYTES] client_data_crypt = data[PUBLICKEY_BYTES + NONCE_BYTES:] box = Box(server_sk, PublicKey(client_pk)) channel = box.decrypt(client_data_crypt, client_nonce) data = None # read messages for the client _global_db_write_lock.acquire(True) try: # make sure the lock will be released again with open(STORAGE_CHANNELS_DIR + channel, 'r+') as f: data = f.read() f.seek(0) f.truncate() except Exception as e: # print "Error reading file:", e # the channel does not exist data = '' finally: _global_db_write_lock.release() client_nonce = increase_nonce(client_nonce) ciphertext = box.encrypt(data, client_nonce).ciphertext box = None data = to_byte(PACKET_ID_RECV_MSG_RESPONSE) + ciphertext self.request.sendall(itonb(len(data)) + data) else: raise UserWarning("Unknown packet id.")
class CrCrypto: _sk = None _pk = None _k = None _encrypt_nonce = None _decrypt_nonce = None session_key = None @property def pk(self): return bytes(self._pk) @property def k(self): return bytes(self._k) @k.setter def k(self, k): self._k = Box.decode(k) @property def encrypt_nonce(self): return bytes(self._encrypt_nonce) @encrypt_nonce.setter def encrypt_nonce(self, encrypt_nonce): self._encrypt_nonce = CrNonce(nonce=encrypt_nonce) @property def decrypt_nonce(self): return bytes(self._decrypt_nonce) @decrypt_nonce.setter def decrypt_nonce(self, decrypt_nonce): self._decrypt_nonce = CrNonce(nonce=decrypt_nonce) def keypair(self): self._sk = PrivateKey.generate() self._pk = self._sk.public_key def beforenm(self, pk): pk = PublicKey(bytes(pk)) self._k = Box(self._sk, pk) def encrypt(self, message, nonce=None): if not nonce: self._encrypt_nonce.increment() nonce = self.encrypt_nonce return self._k.encrypt(message, bytes(nonce))[24:] def decrypt(self, ciphertext, nonce=None): if not nonce: self._decrypt_nonce.increment() nonce = self.decrypt_nonce return self._k.decrypt(ciphertext, bytes(nonce)) def encryptPacket(self, messageid, unknown, payload): raise NotImplementedError def decryptPacket(self, packet): raise NotImplementedError
class socket: def __init__(self): # fill in your code here # create any lists/arrays/hashes you need self.sPort = sock352portTx self.rPort = sock352portRx self.addr = None self.seq = 0 self.ack = 0 self.socket = syssock.socket(AF_INET, SOCK_DGRAM) self.encrypt = False self.myPrivateKey = None self.theirPublicKey = None self.box = None self.packetList = [] # for part 1 we dont need a buffer to be stored, # so we're only using this list to store the current packet self.PLindex = 0 return def bind(self, address): # bind is not used in this assignment self.socket.bind(("", int(address[1]))) return def connect(self, *args): # example code to parse an argument list global sock352portTx global ENCRYPT if (len(args) >= 1): (host, port) = args[0] if (len(args) >= 2): if (args[1] == ENCRYPT): self.encrypt = True # your code goes here # create a new sequence number # create a new packet header with the SYN bit set in the flags (use the Struct.pack method) # also set the other fields (e.g sequence #) # add the packet to the send buffer # set the timeout # wait for the return SYN # if there was a timeout, retransmit the SYN packet # set the send and recv packets sequence numbers self.addr = (syssock.gethostbyname(syssock.getfqdn(host)), (int)(port)) #search for correct keys if (self.encrypt): for k, v in publicKeys.items(): temp = k if (k[0] != '*' and k[1] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), (int)(k[1])) elif (k[0] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), k[1]) elif (k[1] != '*'): temp = (k[0], (int)(k[1])) if ((temp[0] == self.addr[0] or temp[0] == host or temp[0] == '*') and (temp[1] == self.sPort or temp[1] == self.addr[1] or temp[1] == port or temp[1] == '*')): self.theirPublicKey = v break for k, v in privateKeys.items(): temp = k if (k[0] != '*' and k[1] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), (int)(k[1])) elif (k[0] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), k[1]) elif (k[1] != '*'): temp = (k[0], (int)(k[1])) if ((temp[0] == self.addr[0] or temp[0] == host or temp[0] == '*') and (temp[1] == self.rPort or temp[1] == '*')): self.myPrivateKey = v break #make a box self.box = Box(self.myPrivateKey, self.theirPublicKey) self.seq = random.randint(0, 1000) self.socket.bind(("", sock352portRx)) udpPkt_hdr_data = struct.Struct(sock352HdrStructStr) header = udpPkt_hdr_data.pack(1, 1, 0, 0, 40, 0, 0, 0, self.seq, self.ack, 0, 0) #first part self.socket.sendto(header, self.addr) waiting = True while (waiting): try: #second part self.socket.settimeout(0.2) ret, ad = self.socket.recvfrom(40) retStruct = struct.unpack('!BBBBHHLLQQLL', ret) synCheck = retStruct[1] incSeqNum = retStruct[8] incAckNum = retStruct[9] #invalid if (synCheck != 5 or incAckNum != self.seq + 1 or (incSeqNum != self.ack and self.ack != 0)): continue self.ack = incSeqNum + 1 except: #first part failed self.socket.sendto(header, self.addr) continue waiting = False #third part self.seq += 1 udpPkt_hdr_data2 = struct.Struct(sock352HdrStructStr) header2 = udpPkt_hdr_data2.pack(1, 5, 0, 0, 40, 0, 0, 0, self.seq, self.ack, 0, 0) self.socket.sendto(header2, self.addr) self.seq += 1 return def listen(self, backlog): # listen is not used in this assignments return def accept(self, *args): # example code to parse an argument list global ENCRYPT if (len(args) >= 1): if (args[0] == ENCRYPT): self.encrypt = True # your code goes here # call __sock352_get_packet() until we get a new conection # check the the incoming packet - did we see a new SYN packet? self.socket.settimeout(None) temp = self.socket.recvfrom(40) self.packetList.append(temp[0]) ad = temp[1] self.addr = (syssock.gethostbyname(syssock.getfqdn(ad[0])), (int)(ad[1])) #search for correct keys if (self.encrypt): for k, v in publicKeys.items(): temp = k if (k[0] != '*' and k[1] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), (int)(k[1])) elif (k[0] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), k[1]) elif (k[1] != '*'): temp = (k[0], (int)(k[1])) if ((temp[0] == self.addr[0] or temp[0] == ad[0] or temp[0] == '*') and (temp[1] == self.sPort or temp[1] == self.addr[1] or temp[1] == ad[1] or temp[1] == '*')): self.theirPublicKey = v break for k, v in privateKeys.items(): temp = k if (k[0] != '*' and k[1] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), (int)(k[1])) elif (k[0] != '*'): temp = (syssock.gethostbyname(syssock.getfqdn(k[0])), k[1]) elif (k[1] != '*'): temp = (k[0], (int)(k[1])) if ((temp[0] == self.addr[0] or temp[0] == ad[0] or temp[0] == '*') and (temp[1] == self.rPort or temp[1] == '*')): self.myPrivateKey = v break #make a box self.box = Box(self.myPrivateKey, self.theirPublicKey) self.__sock352_get_packet() self.packetList[0] = None self.socket.settimeout(0.2) return (self, self.addr) def close(self): # fill in your code here self.socket.close() return def send(self, buffer): bytessent = 0 # fill in your code here # make sure the correct fields are set in the flags # make sure the sequence and acknowlegement numbers are correct # create a new sock352 header using the struct.pack # create a new UDP packet with the header and buffer # send the UDP packet to the destination and transmit port # set the timeout # wait or check for the ACK or a timeout udpPkt_hdr_data = struct.Struct(sock352HdrStructStr) header = None packet = None if (self.encrypt): header = udpPkt_hdr_data.pack(1, 16, 1, 0, 40, 0, 0, 0, self.seq, self.ack, 0, len(buffer) + 40) packet = header + self.box.encrypt(buffer) else: header = udpPkt_hdr_data.pack(1, 0, 0, 0, 40, 0, 0, 0, self.seq, self.ack, 0, len(buffer)) packet = header + buffer bytessent = self.socket.sendto(packet, self.addr) waiting = True while (waiting): try: #second part ret, ad = self.socket.recvfrom(40) retStruct = struct.unpack(sock352HdrStructStr, ret) ackCheck = retStruct[1] incSeqNum = retStruct[8] incAckNum = retStruct[9] #invalid if (ackCheck != 4 or incAckNum != self.seq + 1 or incSeqNum != self.ack): continue self.ack = incSeqNum + 1 except: #first part failed bytessent = self.socket.sendto(packet, self.addr) continue waiting = False self.seq += 1 return len(buffer) def recv(self, nbytes): # fill in your code here if (self.encrypt): nbytes += 40 self.packetList[0], ad = self.socket.recvfrom(nbytes + 40) self.__sock352_get_packet() bytesreceived = self.packetList[0][40:] self.packetList[0] = None # call __sock352_get_packet() to get packets (polling) # check the list of received fragements # copy up to bytes_to_receive into a buffer # return the buffer if there is some data return bytesreceived # this is an internal function that demultiplexes all incomming packets # it update lists and data structures used by other methods def __sock352_get_packet(self): # There is a differenct action for each packet type, based on the flags: # First check if it's a connection set up (SYN bit set in flags) # Create a new fragment list # Send a SYN packet back with the correct sequence number # Wake up any readers wating for a connection via accept() or return # else # if it is a connection tear down (FIN) # send a FIN packet, remove fragment list # else if it is a data packet # check the sequence numbers, add to the list of received fragments # send an ACK packet back with the correct sequence number # else if it's nothing it's a malformed packet. # send a reset (RST) packet with the sequence number header = self.packetList[self.PLindex][:40] msg = self.packetList[self.PLindex][40:] headerData = struct.unpack(sock352HdrStructStr, header) if (headerData[1] == 1): #syn udpPkt_hdr_data = struct.Struct(sock352HdrStructStr) self.seq = self.seq = random.randint(0, 1000) self.ack = headerData[8] + 1 syn = udpPkt_hdr_data.pack(1, 5, 0, 0, 40, 0, 0, 0, self.seq, self.ack, 0, 0) self.socket.sendto(syn, self.addr) self.socket.settimeout(0.2) waiting = True while (waiting): try: #wait for third part ret, ad = self.socket.recvfrom(40) retStruct = struct.unpack(sock352HdrStructStr, ret) ackCheck = retStruct[1] incSeqNum = retStruct[8] incAckNum = retStruct[9] #invalid if (ackCheck != 5 or incAckNum != self.seq + 1 or incSeqNum != self.ack): continue self.ack += 1 except: #our ack failed; resend self.socket.settimeout(0.2) self.socket.sendto(syn, self.addr) continue waiting = False self.seq += 1 elif (headerData[1] == 2): #fin udpPkt_hdr_data = struct.Struct(sock352HdrStructStr) self.ack += 1 fin = udpPkt_hdr_data.pack(1, 6, 0, 0, 40, 0, 0, 0, self.seq, self.ack, 0, 0) self.socket.sendto(fin, self.addr) elif (headerData[1] == 0 or headerData[1] == 16): #data if (self.encrypt): msg = self.box.decrypt(msg) self.packetList[self.PLindex] = header + msg udpPkt_hdr_data = struct.Struct(sock352HdrStructStr) self.ack += 1 ack = udpPkt_hdr_data.pack(1, 4, 0, 0, 40, 0, 0, 0, self.seq, self.ack, 0, 0) self.socket.sendto(ack, self.addr) self.seq += 1 else: #malformed packet udpPkt_hdr_data = struct.Struct(sock352HdrStructStr) res = udpPkt_hdr_data.pack(1, 8, 0, 0, 40, 0, 0, 0, self.seq, self.ack, 0, 0) self.socket.sendto(res, self.addr) return
def accept(self,*args): # makes sure again that the server is not already connected # because part 1 supports a single connection only if self.is_connected: print(CONNECTION_ALREADY_ESTABLISHED_MESSAGE) return # Keeps trying to receive the request to connect from a potential client until we get a connection request got_connection_request = False while not got_connection_request: try: # tries to receive a potential SYN packet and unpacks it (syn_packet, addr) = self.socket.recvfrom(PACKET_HEADER_LENGTH) # example code to parse an argument list (use option arguments if you want) global ENCRYPT if (len(args) >= 1): if (args[0] == ENCRYPT): self.encrypt = True # Take keys and use them to create another box # Note: we had trouble figuring out how to create the box # we didn't figure out the parameters in time # We would've created a new box with the server's private key and the client's public key # since the server calls this method to decrypt an incoming packet socket_box = Box(args[0, 0], args[0, 1]) # test, possible (host,port) nonce = nacl.utils.random(Box.NONCE_SIZE) header = socket_box.decrypt(syn_packet) syn_packet = header syn_packet = struct.unpack(PACKET_HEADER_FORMAT, syn_packet) # if the received packet is not a SYN packet, it ignores the packet if syn_packet[PACKET_FLAG_INDEX] == SOCK352_SYN: got_connection_request = True # if the receive times out while receiving a SYN packet, it tries to listen again except syssock.timeout: pass # Step 2: Send a SYN/ACK packet for the 3-way handshake # creates the flags bit to be the bit-wise OR of SYN/ACK flags = SOCK352_SYN | SOCK352_ACK # creates the SYN/ACK packet to ACK the connection request from client # and sends the SYN to establish the connection from this end syn_ack_packet = self.createPacket(flags=flags, sequence_no=self.sequence_no, ack_no=syn_packet[PACKET_SEQUENCE_NO_INDEX] + 1) # increments the sequence number as it just consumed it when creating the SYN/ACK packet self.sequence_no += 1 # sends the created packet to the address from which it received the SYN packet if (self.encrypt == True): # Need to encrypt the contents of the packet (didn't get to implement properly here) # Needed to make another box to send it # Had trouble figuring out Box parameters # We would've created a new box with the server's public key and the client's private key # since the server calls this method to encrypt an outgoing packet encrypted = socket_box.encrypt(syn_ack_packet, nonce) syn_ack_packet = encrypted self.socket.sendto(syn_ack_packet, addr) # Receive the final ACK to complete the handshake and establish connection got_final_ack = False while not got_final_ack: try: # keeps trying to receive the final ACK packet to finalize the connection (ack_packet, addr) = self.socket.recvfrom(PACKET_HEADER_LENGTH) if (self.encrypt == True): # We would need to create another box here (maybe we could've used the previous box, we weren't sure) # Had trouble figuring out Box parameters # We would've created a new box with the server's private key and the client's public key # since the server calls this method to decrypt an incoming packet header = socket_box.decrypt(ack_packet) ack_packet = header ack_packet = struct.unpack(PACKET_HEADER_FORMAT, ack_packet) # if the unpacked packet has the ACK flag set, we are done if ack_packet[PACKET_FLAG_INDEX] == SOCK352_ACK: got_final_ack = True # if the server times out when trying to receive the final ACK, it retransmits the SYN/ACK packet except syssock.timeout: # Need to encrypt the packet before sending (might not be correctly implemented here, wasn't sure about the nonce) if (self.encrypt == True): # Needed to make another box to send it (maybe we could've used the previous box, we weren't sure) # Had trouble figuring out Box parameters # We would've created a new box with the server's public key and the client's private key # since the server calls this method to encrypt an outgoing packet encrypted = socket_box.encrypt(syn_ack_packet, nonce) syn_ack_packet = encrypted self.socket.sendto(syn_ack_packet, addr) # updates the server's ack number to be the last packet's sequence number + 1 self.ack_no = ack_packet[PACKET_SEQUENCE_NO_INDEX] + 1 # updates the server's send address self.send_address = (addr[0], portTx) # connect to the client using the send address just set # self.socket.connect(self.send_address) # updates the connected boolean to reflect that the server is now connected self.is_connected = True print("Server is now connected to the client at %s:%s" % (self.send_address[0], self.send_address[1])) return self, addr
def handle_event(self, event): for key in event: if key in {"type", "from"}: continue elif key == "messageid": event[key] = int(event[key], 16) elif type(event[key]) is bool: continue elif type(event[key]) in {str, unicode}: event[key] = event[key].decode("hex") if event["type"] == "socket": self.tee = Tee( os.path.join(self.BASE_DIR, "session-{}.log".format(event["threadid"]))) self.log("session started") elif event["type"] == "keypair": self.sk = PrivateKey(event["sk"]) self.dump({"sk": self.sk}, function="PrivateKey") elif event["type"] == "send" or event["type"] == "recv": if event["messageid"] == 10100: event.update({"message": event["buffer"]}) self.dump(event) elif event["messageid"] == 20100: event.update({"message": event["buffer"]}) self.dump(event) else: if self.serverkey: if self.sk: if event["messageid"] == 10101: self.pk = PublicKey(event["buffer"][:32]) self.dump({"pk": bytes(self.pk)}, function="PublicKey") event["buffer"] = event["buffer"][32:] if self.pk: if event["messageid"] == 10101 or self.snonce: if event["messageid"] in {10101, 20104 } or self.rnonce: if event["messageid"] in {10101, 20104 } or self.k: if event["messageid"] in { 10101, 20104 }: k = Box(self.sk, self.serverkey) self.dump({"s": k}, function="Box") b2 = blake2b(digest_size=24) if event["messageid"] == 20104: b2.update(bytes(self.snonce)) b2.update(bytes(self.pk)) b2.update(bytes(self.serverkey)) nonce = b2.digest() if event["messageid"] == 10101: self.dump( { "pk": self.pk, "serverkey": self.serverkey, "nonce": nonce }, function="blake2b") elif event["messageid"] == 20104: self.dump( { "snonce": self.snonce, "pk": self.pk, "serverkey": self.serverkey, "nonce": nonce }, function="blake2b") else: k = self.k if event["type"] == "send": self.snonce = self.increment_nonce( self.snonce) nonce = self.snonce elif event["type"] == "recv": self.rnonce = self.increment_nonce( self.rnonce) nonce = self.rnonce ciphertext = event["buffer"] event.update({ "k": k, "nonce": nonce, "ciphertext": event["buffer"] }) try: message = k.decrypt( ciphertext, nonce) except: self.dump(event, error=True) self.log( "Warning: failed to decrypt {}" .format(event["messageid"]), error=True) if event["messageid"] in { 10101, 20104 }: raise else: if event["messageid"] == 10101: self.snonce = message[24:48] self.dump( {"snonce": self.snonce}, function="slice") message = message[48:] elif event["messageid"] == 20104: self.rnonce = message[:24] self.k = Box.decode( message[24:56]) self.dump( { "rnonce": self.rnonce, "k": self.k }, function="slice") message = message[56:] event.update({"message": message}) self.dump(event) else: raise Exception( "Missing shared key ({}).".format( event["messageid"])) else: raise Exception( "Missing server nonce ({}).".format( event["messageid"])) else: raise Exception( "Missing client nonce ({}).".format( event["messageid"])) else: raise Exception("Missing public key ({}).".format( event["messageid"])) else: raise Exception("Missing secret key ({}).".format( event["messageid"])) else: raise Exception("Missing server key ({}).".format( event["messageid"])) elif event["type"] == "closing": self.log("session closed") elif event["type"] == "close": self.tee.flush() self.tee.close() else: raise Exception("Invalid event type ({}).".format(event["type"]))
def decrypt(self, event: EVENT, parse=False): """ Using this function a user tries to decrypt an event. Parameters ---------- self : USER The user decrypting an event event : EVENT The event to decrypt parse : bool Describes if event need to be parsed """ # msg = '{"event": "app/action", "content": "xxx"}' # log_event = '{"hmac": "'+digest.hex()+'", "cyphertext": "'+encrypted.hex()+'"}' # log_event = {"cleartext": {"event": "chat/create", "content": "two"}} # log_event = {"cleartext": {"event": "log/sync", "content": "RAW_BACNET_EVENT"}} # print(event) # determine sender sender = get_alias_by_id(self.fid) # check if need to sync e = check_sync(event.content()) if (e != None): # parse this content event = e sender = get_alias_by_id(e.fid.hex()) # return 'sync: ' + e.fid.hex() + ' ' + e.content().__repr__() data = loads(event.content()) try: # print cleartext return sender + '@all: ' + data['cleartext']['event'] + ' ' + data[ 'cleartext']['content'] except KeyError: # cyphertext --> needs decryption cypher = bytes.fromhex(data['cyphertext']) if bytes.fromhex(data['hmac']) == hmac.digest( event.fid, cypher, sha256): try: # try to decrypt private event box = Box( self.get_curve_private_key(), PublicKey( crypto_sign_ed25519_pk_to_curve25519(event.fid))) cleartext = box.decrypt(cypher, encoder=Base64Encoder) data = loads(cleartext) inv = check_invite(data) if parse and inv != None: self.add_channel(inv) return sender + '@private: ' + data['event'] + ' ' + data[ 'content'] except nacl.exceptions.CryptoError: # not allowed to decrypt private boy return sender + '@privatebox' # loop through other channels hkey for c in self.channels: c = CHANNEL(self, c[0]) channel = get_alias_by_id(c.cid) hkey = c.hkey_bytes() if bytes.fromhex(data['hmac']) == hmac.digest( hkey, cypher, sha256): # print('matched hkey: '+hkey) # print('hmac: '+data['hmac']) # print('unboxing...') for dk in c.dkeys_bytes(): try: # decrypt message in channel box = SecretBox(dk) cleartext = box.decrypt(cypher, encoder=Base64Encoder) data = loads(cleartext) rekey = check_rekey(data) if parse and rekey != None: c.add_dkey(self, rekey) return sender + '@[' + channel + ']: ' + data[ 'event'] + ' ' + data['content'] except nacl.exceptions.CryptoError: # not allowed to decrypt channel message continue # perhaps there is another dkey return sender + '@lock[' + channel + ']' # no dkey found (not a member anymore) return sender + '@secret' # - not cleartext nor matching a channel
def test_activate_token(self): """ Ensure we can activate our token """ # our public / private key box box = PrivateKey.generate() # our hex encoded public / private keys user_session_private_key_hex = box.encode( encoder=nacl.encoding.HexEncoder).decode() user_session_public_key_hex = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() server_crypto_box = Box( PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder), PublicKey(settings.PUBLIC_KEY, encoder=nacl.encoding.HexEncoder)) login_info_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) encrypted = server_crypto_box.encrypt( json.dumps({ 'username': self.test_username, 'authkey': self.test_authkey, }).encode("utf-8"), login_info_nonce) login_info_encrypted = encrypted[len(login_info_nonce):] data = { 'login_info': nacl.encoding.HexEncoder.encode(login_info_encrypted).decode(), 'login_info_nonce': nacl.encoding.HexEncoder.encode(login_info_nonce).decode(), 'public_key': user_session_public_key_hex, } url = reverse('authentication_login') response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) request_data = json.loads( server_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( response.data.get('login_info').decode()), nacl.encoding.HexEncoder.decode( response.data.get('login_info_nonce').decode())).decode()) token = request_data.get('token', False) server_public_key_hex = request_data.get('session_public_key', False) # lets encrypt our token user_private_key = PrivateKey(self.test_real_private_key, encoder=nacl.encoding.HexEncoder) user_session_private_key = PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder) server_public_key = PublicKey(server_public_key_hex, encoder=nacl.encoding.HexEncoder) # create both our crypto boxes user_crypto_box = Box(user_private_key, server_public_key) session_crypto_box = Box(user_session_private_key, server_public_key) # decrypt session secret session_secret_key_nonce_hex = request_data.get( 'session_secret_key_nonce', False) session_secret_key_nonce = nacl.encoding.HexEncoder.decode( session_secret_key_nonce_hex) session_secret_key_hex = request_data.get('session_secret_key', False) session_secret_key = nacl.encoding.HexEncoder.decode( session_secret_key_hex) decrypted_session_key_hex = session_crypto_box.decrypt( session_secret_key, session_secret_key_nonce) # decrypt user validator user_validator_nonce_hex = request_data.get('user_validator_nonce', False) user_validator_nonce = nacl.encoding.HexEncoder.decode( user_validator_nonce_hex) user_validator_hex = request_data.get('user_validator', False) user_validator = nacl.encoding.HexEncoder.decode(user_validator_hex) decrypted_user_validator = user_crypto_box.decrypt( user_validator, user_validator_nonce) # encrypt user validator with session key verification_nonce = nacl.utils.random( nacl.secret.SecretBox.NONCE_SIZE) verification_nonce_hex = nacl.encoding.HexEncoder.encode( verification_nonce) decrypted_session_key = nacl.encoding.HexEncoder.decode( decrypted_session_key_hex) secret_box = nacl.secret.SecretBox(decrypted_session_key) encrypted = secret_box.encrypt(decrypted_user_validator, verification_nonce) verification = encrypted[len(verification_nonce):] verification_hex = nacl.encoding.HexEncoder.encode(verification) # encrypt authorization validator with session key authorization_validator_nonce = nacl.utils.random( nacl.secret.SecretBox.NONCE_SIZE) authorization_validator_nonce_hex = nacl.encoding.HexEncoder.encode( authorization_validator_nonce) encrypted = secret_box.encrypt( json.dumps({}).encode("utf-8"), authorization_validator_nonce) authorization_validator = encrypted[len(authorization_validator_nonce ):] authorization_validator_hex = nacl.encoding.HexEncoder.encode( authorization_validator) url = reverse('authentication_activate_token') data = { 'token': token, 'verification': verification_hex.decode(), 'verification_nonce': verification_nonce_hex.decode(), } self.client.credentials(HTTP_AUTHORIZATION='Token ' + token, HTTP_AUTHORIZATION_VALIDATOR=json.dumps({ 'text': authorization_validator_hex.decode(), 'nonce': authorization_validator_nonce_hex.decode(), })) response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertTrue( response.data.get('user', {}).get('id', False), 'User ID does not exist in login response') self.assertEqual( response.data.get('user', {}).get('email', False), self.test_email, 'Email is wrong in response or does not exist') self.assertEqual( response.data.get('user', {}).get('secret_key', False), self.test_secret_key, 'Secret key is wrong in response or does not exist') self.assertEqual( response.data.get('user', {}).get('secret_key_nonce', False), self.test_secret_key_nonce, 'Secret key is wrong in response or does not exist')
def test_login_with_duo(self): """ Ensure we can login with duo """ url = reverse('authentication_login') models.Duo.objects.create( user=self.user_obj, title='My Sweet Title', duo_integration_key='duo_integration_key', duo_secret_key=encrypt_with_db_secret('duo_secret_key'), duo_host='duo_secret_key', enrollment_user_id='enrollment_user_id', enrollment_activation_code='enrollment_activation_code', enrollment_expiration_date=timezone.now() + timedelta(seconds=600), active=True, ) self.user_obj.duo_enabled = True self.user_obj.save() # our public / private key box box = PrivateKey.generate() # our hex encoded public / private keys user_session_private_key_hex = box.encode( encoder=nacl.encoding.HexEncoder).decode() user_session_public_key_hex = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() server_crypto_box = Box( PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder), PublicKey(settings.PUBLIC_KEY, encoder=nacl.encoding.HexEncoder)) login_info_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) encrypted = server_crypto_box.encrypt( json.dumps({ 'username': self.test_username, 'authkey': self.test_authkey, }).encode("utf-8"), login_info_nonce) login_info_encrypted = encrypted[len(login_info_nonce):] data = { 'login_info': nacl.encoding.HexEncoder.encode(login_info_encrypted).decode(), 'login_info_nonce': nacl.encoding.HexEncoder.encode(login_info_nonce).decode(), 'public_key': user_session_public_key_hex, } models.Token.objects.all().delete() response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) request_data = json.loads( server_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( response.data.get('login_info')), nacl.encoding.HexEncoder.decode( response.data.get('login_info_nonce'))).decode()) self.assertTrue(request_data.get('token', False), 'Token does not exist in login response') self.assertEqual(request_data.get('required_multifactors', False), ['duo_2fa'], 'duo_2fa not part of the required_multifactors') self.assertEqual( request_data.get('user', {}).get('public_key', False), self.test_public_key, 'Public key is wrong in response or does not exist') self.assertEqual( request_data.get('user', {}).get('private_key', False), self.test_private_key, 'Private key is wrong in response or does not exist') self.assertEqual( request_data.get('user', {}).get('private_key_nonce', False), self.test_private_key_nonce, 'Private key nonce is wrong in response or does not exist') self.assertEqual( request_data.get('user', {}).get('user_sauce', False), self.test_user_sauce, 'Secret key nonce is wrong in response or does not exist') self.assertNotEqual(request_data.get('session_public_key', False), False, 'Session public key does not exist') self.assertNotEqual(request_data.get('user_validator', False), False, 'User validator does not exist') self.assertNotEqual(request_data.get('user_validator_nonce', False), False, 'User validator nonce does not exist') self.assertNotEqual(request_data.get('session_secret_key', False), False, 'Session secret key does not exist') self.assertNotEqual( request_data.get('session_secret_key_nonce', False), False, 'Session secret key nonce does not exist') self.assertEqual(models.Token.objects.count(), 1)
def test_login(self): """ Ensure we can login """ # our public / private key box box = PrivateKey.generate() # our hex encoded public / private keys user_session_private_key_hex = box.encode( encoder=nacl.encoding.HexEncoder).decode() user_session_public_key_hex = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() server_crypto_box = Box( PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder), PublicKey(settings.PUBLIC_KEY, encoder=nacl.encoding.HexEncoder)) login_info_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) encrypted = server_crypto_box.encrypt( json.dumps({ 'username': self.test_username, 'authkey': self.test_authkey, }).encode("utf-8"), login_info_nonce) login_info_encrypted = encrypted[len(login_info_nonce):] data = { 'login_info': nacl.encoding.HexEncoder.encode(login_info_encrypted).decode(), 'login_info_nonce': nacl.encoding.HexEncoder.encode(login_info_nonce).decode(), 'public_key': user_session_public_key_hex, } url = reverse('authentication_login') models.Token.objects.all().delete() response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) request_data = json.loads( server_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( response.data.get('login_info')), nacl.encoding.HexEncoder.decode( response.data.get('login_info_nonce'))).decode()) self.assertTrue(request_data.get('token', False), 'Token does not exist in login response') self.assertEqual( request_data.get('required_multifactors', False), [], 'required_multifactors not part of the return value or not an empty list' ) self.assertEqual( request_data.get('user', {}).get('public_key', False), self.test_public_key, 'Public key is wrong in response or does not exist') self.assertEqual( request_data.get('user', {}).get('private_key', False), self.test_private_key, 'Private key is wrong in response or does not exist') self.assertEqual( request_data.get('user', {}).get('private_key_nonce', False), self.test_private_key_nonce, 'Private key nonce is wrong in response or does not exist') self.assertEqual( request_data.get('user', {}).get('user_sauce', False), self.test_user_sauce, 'Secret key nonce is wrong in response or does not exist') self.assertNotEqual(request_data.get('session_public_key', False), False, 'Session public key does not exist') self.assertNotEqual(request_data.get('user_validator', False), False, 'User validator does not exist') self.assertNotEqual(request_data.get('user_validator_nonce', False), False, 'User validator nonce does not exist') self.assertNotEqual(request_data.get('session_secret_key', False), False, 'Session secret key does not exist') self.assertNotEqual( request_data.get('session_secret_key_nonce', False), False, 'Session secret key nonce does not exist') self.assertEqual(models.Token.objects.count(), 1)
def test_token_expiration(self): """ Ensure expired tokens are invalid """ # our public / private key box box = PrivateKey.generate() # our hex encoded public / private keys user_session_private_key_hex = box.encode( encoder=nacl.encoding.HexEncoder).decode() user_session_public_key_hex = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() server_crypto_box = Box( PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder), PublicKey(settings.PUBLIC_KEY, encoder=nacl.encoding.HexEncoder)) login_info_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) encrypted = server_crypto_box.encrypt( json.dumps({ 'username': self.test_username, 'authkey': self.test_authkey, }).encode("utf-8"), login_info_nonce) login_info_encrypted = encrypted[len(login_info_nonce):] data = { 'login_info': nacl.encoding.HexEncoder.encode(login_info_encrypted).decode(), 'login_info_nonce': nacl.encoding.HexEncoder.encode(login_info_nonce).decode(), 'public_key': user_session_public_key_hex, } # lets delete all tokens models.Token.objects.all().delete() # lets create one new token url = reverse('authentication_login') response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) request_data = json.loads( server_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( response.data.get('login_info')), nacl.encoding.HexEncoder.decode( response.data.get('login_info_nonce'))).decode()) self.assertTrue(request_data.get('token', False), 'Token does not exist in login response') token = request_data.get('token', False) # lets fake activation for our token tok = models.Token.objects.filter( key=TokenAuthentication.user_token_to_token_hash(token)).get() tok.active = True tok.user_validator = None tok.save() # encrypt authorization validator with session key secret_box = nacl.secret.SecretBox(tok.secret_key, encoder=nacl.encoding.HexEncoder) authorization_validator_nonce = nacl.utils.random( nacl.secret.SecretBox.NONCE_SIZE) authorization_validator_nonce_hex = nacl.encoding.HexEncoder.encode( authorization_validator_nonce) encrypted = secret_box.encrypt( json.dumps({}).encode("utf-8"), authorization_validator_nonce) authorization_validator = encrypted[len(authorization_validator_nonce ):] authorization_validator_hex = nacl.encoding.HexEncoder.encode( authorization_validator) # to test we first query our datastores with the valid token url = reverse('datastore') data = {} self.client.credentials(HTTP_AUTHORIZATION='Token ' + token, HTTP_AUTHORIZATION_VALIDATOR=json.dumps({ 'text': authorization_validator_hex.decode(), 'nonce': authorization_validator_nonce_hex.decode(), })) response = self.client.get(url, data) self.assertEqual(response.status_code, status.HTTP_200_OK) # seems to work, so lets now put the token back into the past token_obj = models.Token.objects.get() token_obj.valid_till = timezone.now() - timedelta(seconds=10) token_obj.save() # ... and try again url = reverse('datastore') data = {} self.client.credentials(HTTP_AUTHORIZATION='Token ' + token, HTTP_AUTHORIZATION_VALIDATOR=json.dumps({ 'text': authorization_validator_hex.decode(), 'nonce': authorization_validator_nonce_hex.decode(), })) response = self.client.get(url, data) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
k = public.encode(encoder=Base16Encoder) msg = (b'CRYPTO 1.0 REQUEST\r\n' + b'Name: Jeff Dwyer\r\n' + b'PublicKey: ' + k + b'\r\n' + b'\r\n') # Sending Request print(msg.decode('utf-8')) totalsent = 0 while totalsent < len(msg): sent = s.send(msg[totalsent:]) if sent == 0: raise RuntimeError('socket connection broken') totalsent += sent chunks = [] listen = True while listen: chunk = s.recv(2048) chunks.extend(chunk) listen = chunk != b'' c = bytearray(chunks).decode('utf-8') server_public = c.split('\r\n')[2].split(': ')[1] c = c.split('\r\n')[3].split(': ')[1] dumb = PrivateKey.generate() dumb.public_key._public_key = base64.b16decode(server_public) b = Box(private, dumb.public_key) c = c.encode('utf-8') c = binascii.unhexlify(c) print(b.decrypt(c))
def setUp(self): # our public / private key box box = PrivateKey.generate() self.test_email = "*****@*****.**" self.test_username = "******" + settings.ALLOWED_DOMAINS[0] self.test_authkey = binascii.hexlify( os.urandom(settings.AUTH_KEY_LENGTH_BYTES)).decode() self.test_public_key = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() self.test_real_private_key = box.encode( encoder=nacl.encoding.HexEncoder).decode() self.test_private_key = binascii.hexlify( os.urandom(settings.USER_PRIVATE_KEY_LENGTH_BYTES)).decode() self.test_private_key_nonce = binascii.hexlify( os.urandom(settings.NONCE_LENGTH_BYTES)).decode() self.test_secret_key = binascii.hexlify( os.urandom(settings.USER_SECRET_KEY_LENGTH_BYTES)).decode() self.test_secret_key_nonce = binascii.hexlify( os.urandom(settings.NONCE_LENGTH_BYTES)).decode() self.test_user_sauce = '24350a638726c0073ec43c8c84ac110bfc2c45e7a430a257f768837f1470c9c7' data = { 'username': self.test_username, 'email': self.test_email, 'authkey': self.test_authkey, 'public_key': self.test_public_key, 'private_key': self.test_private_key, 'private_key_nonce': self.test_private_key_nonce, 'secret_key': self.test_secret_key, 'secret_key_nonce': self.test_secret_key_nonce, 'user_sauce': self.test_user_sauce, } url = reverse('authentication_register') response = self.client.post(url, data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.user_obj = models.User.objects.get(username=self.test_username) self.user_obj.is_email_active = True self.user_obj.save() url = reverse('authentication_login') # our public / private key box box = PrivateKey.generate() # our hex encoded public / private keys user_session_private_key_hex = box.encode( encoder=nacl.encoding.HexEncoder).decode() user_session_public_key_hex = box.public_key.encode( encoder=nacl.encoding.HexEncoder).decode() server_crypto_box = Box( PrivateKey(user_session_private_key_hex, encoder=nacl.encoding.HexEncoder), PublicKey(settings.PUBLIC_KEY, encoder=nacl.encoding.HexEncoder)) login_info_nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) encrypted = server_crypto_box.encrypt( json.dumps({ 'username': self.test_username, 'authkey': self.test_authkey, }).encode("utf-8"), login_info_nonce) login_info_encrypted = encrypted[len(login_info_nonce):] data = { 'login_info': nacl.encoding.HexEncoder.encode(login_info_encrypted).decode(), 'login_info_nonce': nacl.encoding.HexEncoder.encode(login_info_nonce).decode(), 'public_key': user_session_public_key_hex, } response = self.client.post(url, data) request_data = json.loads( server_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( response.data.get('login_info')), nacl.encoding.HexEncoder.decode( response.data.get('login_info_nonce'))).decode()) self.test_token = request_data.get('token', False) # lets fake activation for our token tok = models.Token.objects.filter( key=TokenAuthentication.user_token_to_token_hash( self.test_token)).get() tok.active = True tok.user_validator = None tok.save() response = self.client.post(url, data) request_data = json.loads( server_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( response.data.get('login_info')), nacl.encoding.HexEncoder.decode( response.data.get('login_info_nonce'))).decode()) self.test_token2 = request_data.get('token', False) # lets fake activation for our token self.tok2 = models.Token.objects.filter( key=TokenAuthentication.user_token_to_token_hash( self.test_token2)).get() self.tok2.active = True self.tok2.user_validator = None self.tok2.save() # encrypt authorization validator with session key secret_box = nacl.secret.SecretBox(tok.secret_key, encoder=nacl.encoding.HexEncoder) authorization_validator_nonce = nacl.utils.random( nacl.secret.SecretBox.NONCE_SIZE) authorization_validator_nonce_hex = nacl.encoding.HexEncoder.encode( authorization_validator_nonce) encrypted = secret_box.encrypt( json.dumps({}).encode("utf-8"), authorization_validator_nonce) authorization_validator = encrypted[len(authorization_validator_nonce ):] authorization_validator_hex = nacl.encoding.HexEncoder.encode( authorization_validator) self.authorization_validator1 = json.dumps({ 'text': authorization_validator_hex.decode(), 'nonce': authorization_validator_nonce_hex.decode(), }) # encrypt authorization validator with session key secret_box = nacl.secret.SecretBox(self.tok2.secret_key, encoder=nacl.encoding.HexEncoder) authorization_validator_nonce = nacl.utils.random( nacl.secret.SecretBox.NONCE_SIZE) authorization_validator_nonce_hex = nacl.encoding.HexEncoder.encode( authorization_validator_nonce) encrypted = secret_box.encrypt( json.dumps({}).encode("utf-8"), authorization_validator_nonce) authorization_validator = encrypted[len(authorization_validator_nonce ):] authorization_validator_hex = nacl.encoding.HexEncoder.encode( authorization_validator) self.authorization_validator2 = json.dumps({ 'text': authorization_validator_hex.decode(), 'nonce': authorization_validator_nonce_hex.decode(), })
def authenticate(self, request): try: token_hash = self.get_token_hash(request) except exceptions.AuthenticationFailed: token_hash = None fileserver = None if token_hash is not None: try: fileserver = Fileserver_Cluster_Members.objects.only('pk').get( key=token_hash) except Fileserver_Cluster_Members.DoesNotExist: pass if fileserver is None and token_hash is not None: cluster_id, fileserver_info_enc = self.get_fileserver_validator( request) try: cluster = Fileserver_Cluster.objects.get(pk=cluster_id) except Fileserver_Cluster.DoesNotExist: msg = _('Invalid token header. Cluster ID does not exist.') raise exceptions.AuthenticationFailed(msg) cluster_public_key = decrypt_with_db_secret( cluster.auth_public_key) cluster_crypto_box = Box( PrivateKey(settings.PRIVATE_KEY, encoder=nacl.encoding.HexEncoder), PublicKey(cluster_public_key, encoder=nacl.encoding.HexEncoder)) try: fileserver_info = json.loads( cluster_crypto_box.decrypt( nacl.encoding.HexEncoder.decode( fileserver_info_enc)).decode()) except nacl.exceptions.CryptoError: msg = _('Invalid fileserver info.') raise exceptions.AuthenticationFailed(msg) if not constant_time_compare(fileserver_info['CLUSTER_ID'], cluster_id): msg = _('Invalid fileserver info.') raise exceptions.AuthenticationFailed(msg) if not constant_time_compare( FileserverAliveAuthentication.user_token_to_token_hash( fileserver_info['FILESERVER_ID']), token_hash): msg = _('Invalid fileserver info.') raise exceptions.AuthenticationFailed(msg) self.validate_cluster_shard_access( cluster_id, fileserver_info['SHARDS_PUBLIC']) fileserver = Fileserver_Cluster_Members.objects.create( create_ip=get_ip(request), fileserver_cluster_id=cluster_id, key=token_hash, public_key=fileserver_info['FILESERVER_PUBLIC_KEY'], secret_key=fileserver_info['FILESERVER_SESSION_KEY'], version=fileserver_info['VERSION'], hostname=fileserver_info['HOSTNAME'], url=fileserver_info['HOST_URL'], read=fileserver_info['READ'], write=fileserver_info['WRITE'], allow_link_shares=fileserver_info.get('ALLOW_LINK_SHARES', True), delete_capability=fileserver_info['DELETE'], valid_till=timezone.now() + datetime.timedelta(seconds=30), ) for shard in fileserver_info['SHARDS_PUBLIC']: Fileserver_Cluster_Member_Shard_Link.objects.create( shard_id=shard['shard_id'], member_id=fileserver.id, read=shard['read'], write=shard['write'], allow_link_shares=shard.get('allow_link_shares', True), delete_capability=shard['delete'], ip_read_whitelist=json.dumps( fileserver_info['IP_READ_WHITELIST']), ip_read_blacklist=json.dumps( fileserver_info['IP_READ_BLACKLIST']), ip_write_whitelist=json.dumps( fileserver_info['IP_WRITE_WHITELIST']), ip_write_blacklist=json.dumps( fileserver_info['IP_WRITE_BLACKLIST']), ) if fileserver is None: msg = _('Login failed') raise exceptions.AuthenticationFailed(msg) return fileserver, fileserver
def connect(self,*args): # different from Project 1 code because it's *args instead of address # example code to parse an argument list (use option arguments if you want) global portTx # sock352portTx global ENCRYPT if (len(args)>=1): # Example code: # (host, port) = args[0] # sets the send address to the tuple (address ip, transmit port) self.send_address = (args[0], portTx) # (address[0], portTx) # binds the client on the receiving port self.socket.bind((args[0], portRx)) # (address[0], portRx) # makes sure the client isn't already connected. If it is, prints an error message if self.is_connected: print(CONNECTION_ALREADY_ESTABLISHED_MESSAGE) return if (len(args)>=2): # check constant, add encryption # create nonce, find keys, create Box object # FILL IN WITH CODE if (args[1] == ENCRYPT): self.encrypt = True # Note: we had trouble figuring out how to create the box # we didn't figure out the parameters in time # We would've created a new box with the server's private key and the client's public key # since the client calls this method to encrypt an outgoing packet socket_box = Box(args[0,0], args[0,1]) # test, possible (host,port) nonce = nacl.utils.random(Box.NONCE_SIZE) # Bob wishes to send Alice an encrypted message so Bob must make a Box with # his private key and Alice's public key #bob_box = Box(skbob, pkalice) else: print("ERROR: Provide destination host and port number") # Step 1: Request to connect to the server by setting the SYN flag # first the packet is created using createPacket and passing in the apprpriate variables syn_packet = self.createPacket(flags=SOCK352_SYN, sequence_no=self.sequence_no) # we need to encrypt the new packet before sending it if (self.encrypt == True): # Needed to make another box to send it (maybe we could've used the previous box, we weren't sure) # Had trouble figuring out Box parameters # We would've created a new box with the server's private key and the client's public key # since the client calls this method to encrypt an outgoing packet encrypted = socket_box.encrypt(syn_packet, nonce) syn_ack_packet = encrypted self.socket.sendto(syn_packet, self.send_address) # increments the sequence since it was consumed in creation of the SYN packet self.sequence_no += 1 # Receives the SYN_ACK from Step 2 within accept() received_handshake_packet = False while not received_handshake_packet: try: # tries to receive a SYN/ACK packet from the server using recvfrom and unpacks it (syn_ack_packet, addr) = self.socket.recvfrom(PACKET_HEADER_LENGTH) # Create a box and decrypt the message if (self.encrypt == True): # Needed to make another box to send it (maybe we could've used the previous box, we weren't sure) # Had trouble figuring out Box parameters # We would've created a new box with the server's public key and the client's private key # since the client calls this method to decrypt an outgoing packet header = socket_box.decrypt(syn_ack_packet) syn_ack_packet = header syn_ack_packet = struct.unpack(PACKET_HEADER_FORMAT, syn_ack_packet) # if it receives a reset marked flag for any reason, abort the handshake if syn_ack_packet[PACKET_FLAG_INDEX] == SOCK352_RESET: print "Connection was reset by the server" return # if it receives a packet, and it is SYN/ACK, we are done if syn_ack_packet[PACKET_FLAG_INDEX] == SOCK352_SYN | SOCK352_ACK: received_handshake_packet = True # if it receives a packet with an incorrect ACK from its sequence number, # it tries to receive more packets if syn_ack_packet[PACKET_ACK_NO_INDEX] != self.sequence_no: received_handshake_packet = False # retransmits the SYN packet in case of timeout when receiving a SYN/ACK from the server except syssock.timeout: self.socket.sendto(syn_packet, self.send_address) # sets the client's acknowledgement number to be SYN/ACK packet's sequence number + 1 self.ack_no = syn_ack_packet[PACKET_SEQUENCE_NO_INDEX] + 1 # Step 3: Send a packet with the ACK flag set to acknowledge the SYN/ACK packet ack_packet = self.createPacket(flags=SOCK352_ACK, sequence_no=self.sequence_no, ack_no=self.ack_no) # increments the sequence number as it was consumed by the ACK packet self.sequence_no += 1 # sets the connected boolean to be true self.is_connected = True # sends the ack packet to the server, as it assumes it's connected now # Needed to make another box to send it (maybe we could've used the previous box, we weren't sure) # Had trouble figuring out Box parameters # We would've created a new box with the server's private key and the client's public key # since the client calls this method to encrypt an outgoing packet if (self.encrypt == True): encrypted = socket_box.encrypt(ack_packet, nonce) ack_packet = encrypted self.socket.sendto(ack_packet, self.send_address) print("Client is now connected to the server at %s:%s" % (self.send_address[0], self.send_address[1]))
def decrypt(cipher, privateKey, publicKey): box = Box(privateKey, publicKey) cipher_raw = base64url_decode(cipher) return box.decrypt(cipher_raw) \ .decode('utf-8')
def decrypt(self, encrypted, public_key): from nacl.public import Box key = self.private_key box = Box(key, public_key) return box.decrypt(encrypted)
def listen(): global shared_secret global listener_stream global secretNotKnown global nonce global nonce2 global callInProgress p = pyaudio.PyAudio() listener_stream = p.open(format=p.get_format_from_width(WIDTH), channels=CHANNELS, rate=RATE, output=True, frames_per_buffer=Listen_CHUNK) PORT = 50007 #23555#50007 changed to 50007 from 50008 # Arbitrary non-privileged port s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) s.bind(('', PORT)) s.listen(1) #caller = threading.Thread(target=call) #caller.start() conn, addr = s.accept() #here the thread waits for a connection global waitingForCall if waitingForCall: if (conn): waitingForCall = False talker = threading.Thread(target=talk) talker.start() print('Connected by', addr) time.sleep(2) data = conn.recv(Listen_CHUNK) # #1024 #might need this ? nonce = nacl.utils.random(nacl.secret.SecretBox.NONCE_SIZE) i = 1 print("first data received") print(len(data)) writer.start() #https://github.com/pyca/pynacl/blob/51acad0e34e125378d166d6bb9662408056702e0/tests/test_public.py #alice_box = Box(skalice, pkbob) global skbob pkalice = jsonpickle.decode(firebase.get('/fatman/pk', None)) pkalice = PublicKey(pkalice, encoder=HexEncoder) bob_box = Box(skbob, pkalice) data = bob_box.decrypt(data) shared_secret = bob_box.shared_key() talk_secret_box = nacl.secret.SecretBox(shared_secret) print("listen", shared_secret) secretNotKnown = False data = conn.recv(Listen_CHUNK) while data != '' and callInProgress: try: data = talk_secret_box.decrypt(data) data = oc.decode(data) jitter_buf.put(data) data = conn.recv(Listen_CHUNK) # #1024 i = i + 1 except Exception: print("Error warning:", sys.exc_info()[0]) print("length of shit data", len(data)) data = conn.recv(Listen_CHUNK - len(data)) # throwing away this god awful derter #talk_secret_box = nacl.secret.SecretBox(shared_secret) time.sleep(.05) data = conn.recv(Listen_CHUNK) # #1024 if (not callInProgress): break continue #break listener_stream.stop_stream() listener_stream.close() p.terminate() conn.close() callInProgress = False print("listen stopped")
# Encrypt our message, it will be exactly 40 bytes longer than the # original message as it stores authentication information and the # nonce alongside it. # This is a nonce, it *MUST* only be used once, but it is not considered # secret and can be transmitted or stored alongside the ciphertext. A # good source of nonces are just sequences of 24 random bytes. nonceB2A = nacl.utils.random(Box.NONCE_SIZE) nonceA2B = nacl.utils.random(Box.NONCE_SIZE) encryptedB2A = bob_box.encrypt(messageB2A, nonceB2A) encryptedA2B = alice_box.encrypt(messageA2B, nonceA2B) # Decrypt our message, an exception will be raised if the encryption was # tampered with or there was otherwise an error. plaintextB2A = alice_box.decrypt(encryptedB2A) plaintextA2B = bob_box.decrypt(encryptedA2B) print("the plaintext Bob sent is: %s" % (plaintextB2A)) print("the plaintext Alice sent is: %s" % (plaintextA2B)) # the following code illustrates that decryption should fail when we modify the message # make a copy of the message into a byte-array which is mutable bogusMessage = bytearray(encryptedB2A) # we have to wrap the message with a bytes() function to make an immutable copy acceptable # for the nacl library plaintext_should_work = alice_box.decrypt(bytes(bogusMessage)) print("the plaintext Bob sent is: %s" % (plaintext_should_work))
def callback(): """Takes the response from the provider and verify the identity of the logged in user Returns: Redirect to the wanted page after authentication """ session = request.environ.get("beaker.session") data = request.query.get("signedAttempt") if not data: return abort(400, "signedAttempt parameter is missing") data = j.data.serializers.json.loads(data) if "signedAttempt" not in data: return abort(400, "signedAttempt value is missing") username = data["doubleName"] if not username: return abort(400, "DoubleName is missing") res = requests.get(f"https://login.threefold.me/api/users/{username}", {"Content-Type": "application/json"}) if res.status_code != 200: return abort(400, "Error getting user pub key") pub_key = res.json()["publicKey"] user_pub_key = VerifyKey(j.data.serializers.base64.decode(pub_key)) # verify data signedData = data["signedAttempt"] verifiedData = user_pub_key.verify( j.data.serializers.base64.decode(signedData)).decode() data = j.data.serializers.json.loads(verifiedData) if "doubleName" not in data: return abort(400, "Decrypted data does not contain (doubleName)") if "signedState" not in data: return abort(400, "Decrypted data does not contain (state)") if data["doubleName"] != username: return abort(400, "username mismatch!") # verify state state = data["signedState"] if state != session["state"]: return abort(400, "Invalid state. not matching one in user session") nonce = j.data.serializers.base64.decode(data["data"]["nonce"]) ciphertext = j.data.serializers.base64.decode(data["data"]["ciphertext"]) try: priv = j.core.identity.me.nacl.private_key box = Box(priv, user_pub_key.to_curve25519_public_key()) decrypted = box.decrypt(ciphertext, nonce) except nacl.exceptions.CryptoError: return abort(400, "Error decrypting data") try: result = j.data.serializers.json.loads(decrypted) except JSONDecodeError: return abort(400, "3Bot login returned faulty data") if "email" not in result: return abort(400, "Email is not present in data") email = result["email"]["email"] sei = result["email"]["sei"] res = requests.post( "https://openkyc.live/verification/verify-sei", headers={"Content-Type": "application/json"}, json={"signedEmailIdentifier": sei}, ) if res.status_code != 200: return abort(400, "Email is not verified") username = username.lower( ) # workaround usernames that are returned by signed attempt with camel cases session["username"] = username session["email"] = email session["authorized"] = True session["signedAttempt"] = signedData try: tid = j.sals.reservation_chatflow.reservation_chatflow.validate_user({ "username": username, "email": email }).id session["tid"] = tid session["explorer"] = j.core.identity.me.explorer_url except Exception as e: j.logger.warning( f"Error in validating user: {username} with email: {email} in explorer: {j.core.identity.me.explorer_url}\n from {str(e)}" ) return redirect(unquote(session.get("next_url", "/")))
message2 = {"api_token": "8de531a564e2cb932bf1382b964199ad5967f38fc76c6d366f9e0fa323ffb2e5", "public_key" : basekey} r2= requests.post("https://whoomp.cs.uwaterloo.ca/458a3/api/pke/set-key",headers=headers1, json=message2) print(r2.status_code) #part 2b nessiekey = nacl.public.PublicKey(Str1, encoder=nacl.encoding.Base64Encoder) box = Box(sk, nessiekey) secret = "take a walk" cipher = box.encrypt(secret) cipherbase64 = base64.standard_b64encode(cipher) message2 = {"api_token": "8de531a564e2cb932bf1382b964199ad5967f38fc76c6d366f9e0fa323ffb2e5", "to" :"nessie", "message": cipherbase64} r= requests.post("https://whoomp.cs.uwaterloo.ca/458a3/api/pke/send",headers=headers1, json=message2) print(r.status_code) #part 3 message2 = {"api_token": "8de531a564e2cb932bf1382b964199ad5967f38fc76c6d366f9e0fa323ffb2e5"} r= requests.post("https://whoomp.cs.uwaterloo.ca/458a3/api/pke/inbox",headers=headers1, json=message2) str = json.loads(r.text) str2 = str[0]['message'] print str2 ciphmsg = base64.standard_b64decode(str2) lastmsg = box.decrypt(ciphmsg) print lastmsg
from nacl import utils from nacl.public import PrivateKey, Box from nacl.encoding import Base64Encoder aliceKey = PrivateKey.generate() alicePub = aliceKey.public_key bobKey = PrivateKey.generate() bobPub = bobKey.public_key # with open('pubkey.txt', mode='w') as f: # f.write(bytes.decode(pubKey) + '\n') aliceBox = Box(aliceKey, bobPub) bobBox = Box(bobKey, alicePub) message = b'This is a secret message!' encryptedMessage = aliceBox.encrypt(message, encoder=Base64Encoder) print("Plaintext: {}".format(message)) print("Encrypted: {}".format(encryptedMessage)) print("Bob decrypted it: {}".format( bobBox.decrypt(encryptedMessage, encoder=Base64Encoder)))
class socket: def __init__(self): self.receivedACK = [] self.receivedSeq_no = [] self.encrypt = False return def bind(self, address): return def connect(self, *args): # Check for encryption global ENCRYPT, privateKeys, publicKeys if (len(args) >= 1): address = args[0] if (len(args) >= 2): if (args[1] == ENCRYPT): self.encrypt = True self.box = Box(privateKeys[('*', '*')], publicKeys[(address[0], str(Tx))]) # Fill in header values global version, opt_ptr, protocol, header_len, checksum, source_port, dest_port, window flags = SOCK352_SYN sequence_no = random.random() ack_no = 0 payload_len = 0 # Pack the data sock352PktHdrData = '!BBBBHHLLQQLL' udpPkt_hdr_data = struct.Struct(sock352PktHdrData) header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) # Connect with the server destination = address[0] s.connect((destination, Tx)) print('Trying to connect w/ server..') # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) # Send SYN flagged header to server and receive the server's response and check to see if SYN/ACK # If the server had another response, resend the packet while flags != SOCK352_SYN + SOCK352_ACK: s.send(header) receivedHeader = '' # Check for encrypion before receiving if self.encrypt: receivedHeader = s.recv(header_len + 40) receivedHeader = self.box.decrypt(receivedHeader) else: receivedHeader = s.recv(header_len) (version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) = udpPkt_hdr_data.unpack(receivedHeader) # Record received ACK/seq_no self.receivedACK.append(ack_no) self.receivedSeq_no.append(sequence_no) # After receiving SYN/ACK from server, send ACK flags = SOCK352_ACK temp = sequence_no sequence_no = ack_no ack_no = temp + 1 header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) s.send(header) return def listen(self, backlog): return def accept(self, *args): # Wait to receive header data print('waiting for connection...') # Check for encryption if (len(args) >= 1): if (args[0] == ENCRYPT): self.encrypt = True (clientsocket, address) = self.__sock352_get_packet() print(address) return (clientsocket, address) def close(self): # fill in your code here # Fill in header values, make sure flags is FIN global version, opt_ptr, protocol, header_len, checksum, source_port, dest_port, window flags = SOCK352_FIN sequence_no = 0 ack_no = 0 payload_len = 0 # Pack the data sock352PktHdrData = '!BBBBHHLLQQLL' udpPkt_hdr_data = struct.Struct(sock352PktHdrData) header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) # Send header and close the socket s.send(header) s.close() return def send(self, buffer): # fill in your code here # Fill in header values: sequence_no will be the last receivedACK, and ack_no # will be the last received sequence_no + 1 global version, opt_ptr, protocol, header_len, checksum, source_port, dest_port, window flags = SOCK352_ACK sequence_no = self.receivedACK[-1] ack_no = self.receivedSeq_no[-1] + 1 # Hard-coded fragmentsize because can't handle it dynamically :( # This is the max # of bytes that the server can receive # as defined in server1 index = 0; FRAGMENTSIZE = 4096 fragment = '' while (index != len(buffer)): if (len(buffer) - index > FRAGMENTSIZE): payload_len = FRAGMENTSIZE # Pack the header data and send it to server sock352PktHdrData = '!BBBBHHLLQQLL' udpPkt_hdr_data = struct.Struct(sock352PktHdrData) header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) s.send(header) # Send fragment to server fragment = buffer[index:(index + FRAGMENTSIZE)] # Encrypt fragment if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) fragment = self.box.encrypt(fragment, nonce) # Set timeout and send fragment try: s.settimeout(.2) s.send(fragment) except syssock.timeout: s.send(fragment) finally: s.settimeout(None) print('sent packet: '), len(fragment), ('bytes') # TODO: receive ACK? # Check for encrypion before receiving if self.encrypt: receivedHeader = s.recv(header_len + 40) receivedHeader = self.box.decrypt(receivedHeader) else: receivedHeader = s.recv(header_len) # Increment index index += FRAGMENTSIZE else: payload_len = len(buffer) - index # Pack the header data sock352PktHdrData = '!BBBBHHLLQQLL' udpPkt_hdr_data = struct.Struct(sock352PktHdrData) header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) s.send(header) # Send fragment to server fragment = buffer[index:len(buffer)] # Encrypt fragment if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) fragment = self.box.encrypt(fragment, nonce) # Set timeout and send fragment try: s.settimeout(.2) s.send(fragment) except syssock.timeout: s.send(fragment) finally: s.settimeout(None) print('sent packet: '), len(fragment), ('bytes') # TODO: receive ACK? # Check for encrypion before receiving if self.encrypt: receivedHeader = s.recv(header_len + 40) receivedHeader = self.box.decrypt(receivedHeader) else: receivedHeader = s.recv(header_len) # Increment index index = payload_len break; return len(buffer) def recv(self, nbytes): # Fill in header values global version, opt_ptr, protocol, header_len, checksum, source_port, dest_port, window # Receive and unpack header data from client receivedHeader = '' # Check for encrypion before receiving if self.encrypt: receivedHeader = s.recv(header_len + 40) receivedHeader = self.box.decrypt(receivedHeader) else: receivedHeader = s.recv(header_len) sock352PktHdrData = '!BBBBHHLLQQLL' udpPkt_hdr_data = struct.Struct(sock352PktHdrData) (version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) = udpPkt_hdr_data.unpack(receivedHeader) # Receive the bytes dictated by the payload_len # Check for encrypion before receiving if self.encrypt: bytesreceived = s.recv(payload_len + 40) bytesreceived = self.box.decrypt(bytesreceived) else: bytesreceived = s.recv(payload_len) # Give ack_no the value of the next sequence number the client should send over # And give sequence_no the value of what the client is asking for temp = ack_no ack_no = sequence_no + payload_len + 1 sequence_no = temp flags = SOCK352_ACK # Pack and send the ACK to the client header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) s.send(header) print('received '), len(bytesreceived), (' bytes') return bytesreceived def __sock352_get_packet(self): global version, opt_ptr, protocol, header_len, checksum, source_port, dest_port, window # Receive and unpack the data receivedHeader = '' addr = (1, 1) # If encryption is enabled, receive a longer encrypted message and decrypt it if self.encrypt: (receivedHeader, addr) = s.recvfrom(header_len + 40) if addr[0] == '127.0.0.1': self.box = Box(privateKeys[('*', '*')], publicKeys[('localhost', str(Tx))]) else: self.box = Box(privateKeys[('*', '*')], publicKeys[(addr[0], str(Tx))]) receivedHeader = self.box.decrypt(receivedHeader) else: (receivedHeader, addr) = s.recvfrom(header_len) sock352PktHdrData = '!BBBBHHLLQQLL' udpPkt_hdr_data = struct.Struct(sock352PktHdrData) (version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) = udpPkt_hdr_data.unpack(receivedHeader) # If the header flag was SYN if flags == SOCK352_SYN: # Check to see if the address is in the list of connections # and if it's not, send back a random sequence_no and a # and set the ack_no to the incoming sequence_no + 1 # Also instantiate a second socket to communicate w/ client if addr not in connections: connections.append(addr) ack_no = sequence_no + 1 sequence_no = random.random() flags = SOCK352_SYN + SOCK352_ACK header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) s.connect(addr) # Check for encryption before sending if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) # Send out the SYN/ACK flagged header, and wait for # ACK response from client while flags != SOCK352_ACK: s.send(header) # Check for encrypion before receiving if self.encrypt: receivedHeader = s.recv(header_len + 40) receivedHeader = self.box.decrypt(receivedHeader) else: receivedHeader = s.recv(header_len) (version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) = udpPkt_hdr_data.unpack(receivedHeader) print('Connected to:') return (self, addr) # If it is in the list, the connection is reset else: sequence_no = sequence_no + 1 flags = SOCK352_RESET header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) s.connect(addr) # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) s.send(header) return else: # If the header flag is FIN, send back a FIN and remove the addr # from connections and clear the fragments if flags == SOCK352_FIN: flags = SOCK352_FIN header = udpPkt_hdr_data.pack(version, flags, opt_ptr, protocol, header_len, checksum, source_port, dest_port, sequence_no, ack_no, window, payload_len) connections.remove(addr) self.fragments.clear() s.connect(addr) # Encrypt message if encrypt is enabled if self.encrypt: nonce = nacl.utils.random(Box.NONCE_SIZE) header = self.box.encrypt(header, nonce) s.send(header) print('closing connection')
r = request.urlopen(req) data = json.loads(r.read().decode(r.info().get_param('charset') or 'utf-8')) print(data) print(data["public_key"]) jessie_signed_prekey = base64.b64decode(data["public_key"]) jessie_pk = nacl.bindings.crypto_sign_open(jessie_signed_prekey, jessie_id_vk) message = b"lmao" nonce = nacl.utils.random(Box.NONCE_SIZE) encrypted = nacl.bindings.crypto_box(message, nonce, jessie_pk, bytes(secretkey)) data = parse.urlencode({ "api_token": "f0cd8f18e9d280fd23f9eae0d1df65bc0a93d1dbfc3e9f730d31c425249ce05e", "to": "jessie", "message": base64.b64encode(nonce + encrypted) }).encode() req = request.Request('https://whoomp.cs.uwaterloo.ca/458a3/api/prekey/send', data) r = request.urlopen(req) # Part 3 data = parse.urlencode({ "api_token": "f0cd8f18e9d280fd23f9eae0d1df65bc0a93d1dbfc3e9f730d31c425249ce05e" }).encode() req = request.Request('https://whoomp.cs.uwaterloo.ca/458a3/api/prekey/inbox', data) r = request.urlopen(req) data = json.loads(r.read().decode(r.info().get_param('charset') or 'utf-8')) encrypted = base64.b64decode(data[0]["message"]) box = Box(secretkey, PublicKey(jessie_pk)) plaintext = box.decrypt(encrypted) print(plaintext.decode('utf-8'))
def validate(self, attrs: dict) -> dict: username = attrs.get('username') emergency_authkey = attrs.get('emergency_authkey') update_data = nacl.encoding.HexEncoder.decode(attrs.get('update_data')) update_data_nonce = nacl.encoding.HexEncoder.decode( attrs.get('update_data_nonce')) try: user = User.objects.get(username=username) except User.DoesNotExist: # TODO REPLACE WITH USERNAME_OR_RECOVERY_CODE_INCORRECT msg = _("Username or recovery code incorrect.") raise exceptions.ValidationError(msg) emergency_codes = Emergency_Code.objects.filter(user_id=user.id) valid_emergency_code = None for emergency_code in emergency_codes: if not check_password(emergency_authkey, emergency_code.emergency_authkey): continue valid_emergency_code = emergency_code break if not valid_emergency_code: msg = _("Username or emergency code incorrect.") raise exceptions.ValidationError(msg) if valid_emergency_code.verifier_issue_date + datetime.timedelta( 0, settings.RECOVERY_VERIFIER_TIME_VALID) < timezone.now(): msg = _("Validator expired.") raise exceptions.ValidationError(msg) try: crypto_box = Box( PrivateKey(valid_emergency_code.verifier, encoder=nacl.encoding.HexEncoder), PublicKey(user.public_key, encoder=nacl.encoding.HexEncoder)) login_info = json.loads( crypto_box.decrypt(update_data, update_data_nonce).decode()) except: msg = _("Validator failed.") raise exceptions.ValidationError(msg) if not valid_emergency_code.user.is_active: msg = _('User account is disabled.') raise exceptions.ValidationError(msg) if not valid_emergency_code.user.is_email_active: msg = _('E-mail is not yet verified.') raise exceptions.ValidationError(msg) attrs['emergency_code'] = valid_emergency_code attrs['user'] = user attrs['session_duration'] = settings.DEFAULT_TOKEN_TIME_VALID attrs['device_fingerprint'] = login_info.get('device_fingerprint', '') attrs['device_description'] = login_info.get('device_description', '') attrs['user_session_public_key'] = login_info.get( 'session_public_key', '') device_time = login_info.get('device_time', None) if device_time is None: attrs['device_time'] = None else: attrs['device_time'] = dateutil.parser.parse(device_time) return attrs
class socket: def __init__(self): # Initalizes the socket, setting all values to default print("Initializing Lib") self.connectionFlag = False self.prev_ack = 0 self.next_sequence_no = 0 self.next_acknolodgement_no = 0 self.start_sequence_no = 0 self.encrypt = False self.window = 32000 return def bind(self, address): # bind is not used in this assignment print "Bind" return def connect(self, *args): global ENCRYPT global publicKeysHex global privateKeysHex global publicKeys global privateKeys global sock print("In connect:") if (len(args) >= 1): print("args[0], ", args[0]) (host, port) = args[0] if (len(args) >= 2): if (args[1] == ENCRYPT): self.encrypt = True # If the encrypt flag is on we will create a box for the client # to send encrypted messages if (self.encrypt is True): print "Connection is using encrpytion" print("Public key =" + str(publicKeysHex[(host, recv_port)])) print("Private key =" + str(privateKeysHex[('*', '*')])) self.box = Box(privateKeys[('*', '*')], publicKeys[(host, recv_port)]) # Create nonce for client sending messages self.nonce = nacl.utils.random(Box.NONCE_SIZE) # Generates a random initial sequence number and creates and packs a SYN pkt self.start_sequence_no = randint(0, 5000) self.ack_number = 0 print "Creating SYN Packet......." SYN_pkt = pkt() SYN_pkt.create_syn(self.start_sequence_no) print "Packing SYN Packet......." packed_SYN_pkt = SYN_pkt.packPacket() len_hdr = len(packed_SYN_pkt) print "Sending SYN Packet....." # If the connection is encrypted, you must encrypt the packed synpacket and get the length of the # newly encrypted pkt if (self.encrypt): packed_SYN_pkt = self.box.encrypt(packed_SYN_pkt, self.nonce) self.length_encrypted_header = len(packed_SYN_pkt) len_hdr = self.length_encrypted_header # Until succesfull connecction we will continue to try while True: # Try to send the packet sock.sendto(packed_SYN_pkt, (host, int(send_port))) try: # unless we get a response then it wasn't received sock.settimeout(def_timeout_value) raw_packet, sender = sock.recvfrom(len_hdr) break except syssock.timeout: # We didnt get a respone, run the while loop again print "Socket Timed Out.... Resending Packet" time.sleep(2) # If there is encryption then the ack must be decrypted as well if (self.encrypt): recieved_packet_header = packetHeader(self.box.decrypt(raw_packet)) else: recieved_packet_header = packetHeader(raw_packet) print "Packet received... Packed Header is: ", recieved_packet_header print "Flags for recieved_packet_header.flags:", recieved_packet_header.flags print "received ACK_NO: ", recieved_packet_header.ack_no # Check to make sure the received response is an SYN ACK if (recieved_packet_header.flags != 5 or recieved_packet_header.ack_no != (SYN_pkt.header.sequence_no + 1)): print("Ack inforrectly formatted") else: print "Client: Connection created..." self.connectionFlag = True connections[sender] = sender self.destination = sender self.next_sequence_no = recieved_packet_header.ack_no self.prev_ack = recieved_packet_header.ack_no - 1 return def listen(self, backlog): return def accept(self, *args): global connections global ENCRYPT # Checks to see if args length is > 1, if so it checks to if the server is encrypted if (len(args) >= 1): if (args[0] == ENCRYPT): self.encrypt = True print "This is Encrypted server" print "Server: Waiting...." # We will loop until a connection is accepted while True: try: sock.settimeout(def_timeout_value) raw_packet, sender = sock.recvfrom(def_pkt_size) if (self.encrypt): self.length_encrypted_header = len(raw_packet) self.box = Box(privateKeys[('*', '*')], publicKeys[('localhost', send_port)]) raw_packet = self.box.decrypt(raw_packet) print "PrivateKey = " ( (privateKeysHex[('*', '*')] + " PublicKey = " + str(publicKeysHex[('localhost', recv_port)]))) print "Encrypted Server Creating Box" print "Packet Read During Accept" print "Packet received... Packed Header is: ", binascii.hexlify( raw_packet) recieved_packet_header = packetHeader(raw_packet) # If statement to make sure the pkt received is a SYN pkt if (recieved_packet_header.flags != SOCK352_SYN): print "Not Connection Request" else: break except syssock.timeout: print "Socket timed out recieving" time.sleep(5) continue finally: sock.settimeout(None) # Once we reach this point we have a connection. We then send back an ACK print "Accepted Connection" self.start_sequence_no = randint(0, (math.pow(2, 64) - 1)) self.prev_ack = recieved_packet_header.sequence_no + recieved_packet_header.payload_len - 1 ack_packet = pkt() if (connections.has_key(sender)): print "Server already connectionFlag to this client" ack_packet.header.flags = SOCK352_RESET else: ack_packet.header.flags = (SOCK352_ACK + SOCK352_SYN) print "Ack_Packet_Header: ", ack_packet.header.flags print "received seqnum: ", recieved_packet_header.sequence_no ack_packet.header.sequence_no = self.start_sequence_no ack_packet.header.ack_no = recieved_packet_header.sequence_no + 1 print "Ack_No", ack_packet.header.ack_no packed_ack_packet = ack_packet.packPacket() # Checks to see if encrypted connection, if so must create nonce and encrpyt the ACK pkt if (self.encrypt): self.nonce = nacl.utils.random(Box.NONCE_SIZE) packed_ack_packet = self.box.encrypt(packed_ack_packet, self.nonce) # Records the total number of bytes sent. bytesSent = sock.sendto(packed_ack_packet, sender) self.destination = sender print bytesSent print "Sender: ", sender return (self, sender) def close(self): global connections # Creates the FIN pkt for when close() is called FIN_packet = pkt() FIN_packet.header.flags = SOCK352_FIN # Packs the FIN pkt, if encryption we encrypt the FIN pkt packed_FIN = FIN_packet.packPacket() if (self.encrypt): packed_FIN = self.box.encrypt(packed_FIN, self.nonce) # Send the FIN pkt to the destination and reset the variables sock.sendto(packed_FIN, self.destination) self.connectionFlag = False connections.pop(self.destination, None) self.destination = {} self.prev_ack = 0 self.next_sequence_no = 0 self.next_acknolodgement_no = 0 self.start_sequence_no = 0 return def send(self, buffer): print "*******************************************" print "Inside Send Method..........." global sPort # example using a variable global to the Python module # The next six lines create the pkt based on desired data print("BUFFER LEN " + str(len(buffer))) payload = buffer[:4096] # payload = buffer data_packet = pkt() data_packet.header.payload_len = len(payload) data_packet.header.sequence_no = self.next_sequence_no data_packet.header.ack_no = self.next_acknolodgement_no data_packet.payload = payload print "Length Payload: ", len(payload) packed_data_packet = data_packet.packPacket() print "Length of Data_Packet: ", len(packed_data_packet) # print "Packed Value :", binascii.hexlify(packed_data_packet) # Encrypt pkt if connection is encrypted print "Sending pkt" if (self.encrypt): self.nonce = nacl.utils.random(Box.NONCE_SIZE) packed_data_packet = self.box.encrypt(packed_data_packet, self.nonce) # Attempts to send the pkt. If timeout, it will resend. Like accept, if the timeout is hit # the exception will be thrown. There are also checks for the ACK number and flags to make sure it is a # proper ACK pkt while True: # We resend the pkt if we have a timeout bytesSent = sock.sendto(packed_data_packet, self.destination) print "Bytes Sent: ", bytesSent try: sock.settimeout(def_timeout_value) if (self.encrypt): raw_packet_header, sender = sock.recvfrom( self.length_encrypted_header) raw_packet_header = self.box.decrypt(raw_packet_header) else: raw_packet_header, sender = sock.recvfrom(header_len) recieved_packet_header = packetHeader(raw_packet_header) print "SeqNum Sent: ", data_packet.header.sequence_no print "Ack received: ", recieved_packet_header.ack_no print "Window size: ", recieved_packet_header.window if (recieved_packet_header.flags != SOCK352_ACK or recieved_packet_header.ack_no != (data_packet.header.sequence_no + data_packet.header.payload_len)): print "Not proper ACK" break except syssock.timeout: print "Socket Timed Out.... Resending Packet" continue finally: sock.settimeout(None) # Stores the last ACK # and the next ACK # self.next_sequence_no = recieved_packet_header.ack_no # SIGNALED THAT THIS LINE IS UNREACHABLE self.prev_ack = recieved_packet_header.ack_no - 1 self.next_acknolodgement_no = recieved_packet_header.ack_no + 1 print "Returning ", bytesSent # Check to see if encrypted connection, if so must set length to encrypted header size if (self.encrypt): len_hdr = self.length_encrypted_header else: len_hdr = header_len bytesSent = len(buffer) if (len(buffer) > 4096): bytesSent = 4096 return recieved_packet_header.window def recv(self, nbytes): print "In Recieve" print("nbytes == " + str(nbytes)) # Loop used to receive pkt. Exception thrown if timeout. Also checks to see if it is a valid data pkt # or if it is a FIIN pkt while True: try: # This means we got a pkt. sock.settimeout(def_timeout_value) raw_packet, sender = sock.recvfrom(5000) if (self.encrypt): raw_packet = self.box.decrypt(raw_packet) recieved_packet_header = packetHeader(raw_packet[:header_len]) print "Packet received... Packed Header is: ", binascii.hexlify( raw_packet[:header_len]) print "Unpacked Header is: ", udpPkt_hdr_data.unpack( raw_packet[:header_len]) if (recieved_packet_header.flags > 0): print "Not data pkt" if (recieved_packet_header.flags == SOCK352_FIN): sock.close() else: break except syssock.timeout: print "Socket timed out recieving" finally: sock.settimeout(None) # ack_window = pkt() # ack_window.create_ack_window(nbytes) # packed_ack_window = ack_window.packPacket() # sock.sendto(packed_ack_window, sender) self.next_sequence_no = recieved_packet_header.ack_no # SIGNALED THAT THIS LINE IS UNREACHABLE # Stores the last ACK # and the next ACK num self.prev_ack = recieved_packet_header.ack_no - 1 self.next_acknolodgement_no = recieved_packet_header.ack_no + 1 recieved_packet_header.window = nbytes payload = raw_packet[(40):(40 + nbytes)] print "payload length: ", len(payload) # as a 4 byte integer in network byte order (big endian) # Creates an ACK pkt and checks to see if it needs to be encrypted. Packet is then sent to sender ack_packet = pkt() ack_packet.create_ack(recieved_packet_header) print "Ack Packet Ack_NO: ", ack_packet.header.ack_no print "Ack Packet WINDOW: ", ack_packet.header.window packed_ack_packet = ack_packet.packPacket() if (self.encrypt): packed_ack_packet = self.box.encrypt(packed_ack_packet, self.nonce) sock.sendto(packed_ack_packet, sender) return payload
# This is our message to send, it must be a bytestring as Box will treat it # as just a binary blob of data. # Note the "b" in the front of the string means to keep the string in # binary/ascii format, as opposed to UTF-8 or Unicode message = b"This is a binary message" # Encrypt our message, it will be exactly 40 bytes longer than the # original message as it stores authentication information and the # nonce alongside it. # the encrypt function must take a nonce now # encrypted = bob_box.encrypt(message) # This is a nonce, it *MUST* only be used once, but it is not considered # secret and can be transmitted or stored alongside the ciphertext. A # good source of nonces are just sequences of 24 random bytes. nonce = nacl.utils.random(Box.NONCE_SIZE) encrypted = bob_box.encrypt(message, nonce) print("The length of the plaintext is %d and the cyphertext is %d" % (len(message), len(encrypted))) # Alice creates a second box with her private key to decrypt the message alice_box = Box(skalice, pkbob) # Decrypt our message, an exception will be raised if the encryption was # tampered with or there was otherwise an error. plaintext = alice_box.decrypt(encrypted) print("the plaintext is: %s" % (plaintext))
def public_decrypt(message, origin_pub, target_priv): priv = PrivateKey(binascii.unhexlify(target_priv)) pub = PublicKey(binascii.unhexlify(origin_pub)) box = Box(priv, pub) return box.decrypt(message)