def sendMail():
    if ck is not None:
        friend = comboxlist_friend.get()
        while friend not in certificate_list.keys():  # wait for certificate
            time.sleep(0.5)
        friend_certificate = certificate_list[friend]
        if friend_certificate["valid_before"] < str(datetime.datetime.now()):
            text.insert(tkinter.INSERT, friend + '\' certificate is invalid.\n')
            askCert(friend)
            return
        friend_ex_mode = friend_certificate["ex_mode"]
        friend_address = tuple(friend_certificate["address"])
        friend_alg = friend_certificate["alg"]
        pbk_list[friend] = friend_certificate["pbk"]
        if friend_ex_mode == "rsa":
            # 得到了加密方式以及friend地址,然后根据拿到的公钥以及来和对方共享密钥
            # 密钥在接收端方生成,询问接收端对应密钥。接受后通过私钥来解除

            while friend not in keys_list.keys() or friend_alg not in keys_list[friend]:
                askSek(friend, friend_alg, friend_address)
                time.sleep(0.5)
            # 得到对方的key之后,开始传输消息

            if friend_alg == "des":
                cipher = d.encode(esend.get("0.0", "end").strip(), keys_list[friend][friend_alg])
            elif friend_alg == "des3":
                cipher = cipher_des3.encode(esend.get("0.0", "end").strip(), keys_list[friend][friend_alg])
            elif friend_alg == "caesar":
                cipher = cipher_caesar.encode(esend.get("0.0", "end").strip(), keys_list[friend][friend_alg])
            else:
                cipher = cipher_playfair.encode(esend.get("0.0", "end").strip(),
                                                table=cipher_playfair.generate_table(keys_list[friend][friend_alg]))

        else:  # dh

            while friend not in dh_shared_key_list.keys():
                askPak(friend, tuple(friend_certificate["address"]))
                print("ask in sendmail()")
                time.sleep(0.2)
            # dh_shared_key_list[friend],根据friend_alg选择加密方式
            if friend_alg == "caesar":
                key_random = cipher_caesar.generate_key(dh_shared_key_list[friend])
                cipher = cipher_caesar.encode(esend.get("0.0", "end").strip(), key_random)
            elif friend_alg == "des3":
                key_random = cipher_des3.generate_key(dh_shared_key_list[friend])
                cipher = cipher_des3.encode(esend.get("0.0", "end").strip(), key_random)
            elif friend_alg == "des":
                key_random = cipher_des.generate_key(dh_shared_key_list[friend])
                cipher = d.encode(esend.get("0.0", "end").strip(), key_random)
            else:
                key_random = cipher_playfair.generate_key(dh_shared_key_list[friend])
                cipher = cipher_playfair.encode(esend.get("0.0", "end").strip(), table=cipher_playfair.generate_table(
                    key_random))
            print("生成的随机密钥", key_random)

        """
        type:'chat'
        target:'c2'
        from:'c1'
        signature:'foef32097^&*(%%ewfj043'
        msg:'*&^&^%^$^%xdcidsnvc'   
        """

        stream = {"type": "chat", "target": friend, "from": euser.get(), "msg": cipher, "alg": friend_alg,
                  "ex_mode": friend_ex_mode,
                  "signature": cipher_rsa.str_encryption(cipher, pvk[0], pvk[1])}
        client_msg.sendto(json.dumps(stream).encode(), friend_address)



    else:
        text.insert(tkinter.INSERT, "you are offline!!\n")
def udp_msg():
    while True:
        data, friend_addr = client_msg.recvfrom(1024)  # Information from other client
        data = data.decode()
        stream = json.loads(data)
        print(stream)

        if stream["type"] == "sek_ask":
            """
            type:'sek_ask'
            target:'c2'
            from:'c1'
            alg:''(aes, des3, caesar, playfair)
            """
            alg = stream["alg"]
            while stream["from"] not in certificate_list.keys():  # wait for certificate
                askCert(stream["from"])
                time.sleep(0.3)
            friend_certificate = certificate_list[stream["from"]]
            friend_pbk = friend_certificate["pbk"]
            pbk_list[stream["from"]] = friend_pbk

            if alg == "caesar":
                key_cipher = cipher_rsa.encryption(my_sek_list[alg], friend_pbk[0], friend_pbk[1])
            elif alg == "des3":
                key0 = cipher_rsa.str_encryption(my_sek_list[alg][0], friend_pbk[0], friend_pbk[1])
                key1 = cipher_rsa.str_encryption(my_sek_list[alg][1], friend_pbk[0], friend_pbk[1])
                key2 = cipher_rsa.str_encryption(my_sek_list[alg][2], friend_pbk[0], friend_pbk[1])
                key_cipher = (key0, key1, key2)
            else:
                key_cipher = cipher_rsa.str_encryption(my_sek_list[alg], friend_pbk[0], friend_pbk[1])
            """
            type:'sek_rep'
            target:'c1'
            from:'c2'
            alg:''(aes,des3,caesar,playfair)
            key:[123,435,54356,4325435,98897986]由c1的公钥加密后得到的
            """
            resp = {"type": "sek_rep", "target": stream["from"], "from": euser.get(), "alg": alg, "key": key_cipher}
            client_msg.sendto(json.dumps(resp).encode(), friend_addr)
        elif stream["type"] == "sek_rep":
            """
            type:'sek_rep'
            target:'c1'
            from:'c2'
            alg:''(aes,des3,caesar,playfair)
            key:[123,435,54356,4325435,98897986]由c1的公钥加密后得到的
            """
            alg = stream["alg"]
            if alg == "caesar":
                keys_list[stream["from"]][alg] = cipher_rsa.decryption(stream["key"], pvk[0], pvk[1])
            elif alg == "des3":
                key0 = cipher_rsa.numlist_to_decryption_str(stream["key"][0], pvk[0], pvk[1])
                key1 = cipher_rsa.numlist_to_decryption_str(stream["key"][1], pvk[0], pvk[1])
                key2 = cipher_rsa.numlist_to_decryption_str(stream["key"][2], pvk[0], pvk[1])
                keys_list[stream["from"]][alg] = key0, key1, key2
            else:
                keys_list[stream["from"]][alg] = cipher_rsa.numlist_to_decryption_str(stream["key"], pvk[0], pvk[1])
        elif stream["type"] == "pak_ask":
            """
            type:"pak_ask"
            target:c2
            from:c1
            pak:34458
            p:192863
            """
            repPak(stream, friend_addr)
        elif stream["type"] == "pak_rep":
            dh_shared_key_list[stream["from"]] = cipher_dh.get_key(pvk_a, stream["pak"], p)
            print("receive key from ", stream["from"], ":", dh_shared_key_list[stream["from"]])
        elif stream["type"] == "chat":
            alg = stream["alg"]
            ex_mode = stream["ex_mode"]
            while stream["from"] not in certificate_list.keys():  # wait for certificate
                askCert(stream["from"])
                time.sleep(0.2)
            friend_certificate = certificate_list[stream["from"]]
            friend_pbk = friend_certificate["pbk"]
            pbk_list[stream["from"]] = friend_pbk
            if exchange_mode == "rsa":
                friend_pbk = friend_certificate["pbk"]
                pbk_list[stream["from"]] = friend_pbk
                """
                type:'chat'
                target:'c2'
                from:'c1'
                signature:'foef32097^&*(%%ewfj043'
                msg:'*&^&^%^$^%xdcidsnvc'  
                alg:
                """
                if alg == encryption_mode and ex_mode == exchange_mode:
                    signature = cipher_rsa.numlist_to_decryption_str(stream["signature"], friend_pbk[0], friend_pbk[1])
                    if signature == stream["msg"]:
                        if encryption_mode == "des":
                            msg = d.decode(stream["msg"], my_sek_list[encryption_mode])
                        elif encryption_mode == "des3":
                            msg = cipher_des3.decode(stream["msg"], my_sek_list[encryption_mode])
                        elif encryption_mode == "caesar":
                            msg = cipher_caesar.decode(stream["msg"], my_sek_list[encryption_mode])
                        else:
                            msg = cipher_playfair.decode(stream["msg"],
                                                         table=cipher_playfair.generate_table(
                                                             my_sek_list[encryption_mode]))

                        if update_on_receive:
                            text.insert(tkinter.INSERT, stream["from"] + ": " + msg + "\n")
                        else:
                            message_list[stream["from"]].append(msg)
                    else:
                        print("signature:", signature)
                        print("msg:", stream["msg"])
                else:
                    text.insert(tkinter.INSERT, stream["from"] +
                                " send msg using " + alg + "," + ex_mode + ", but you are using " + encryption_mode + "," + exchange_mode + "\n")
            else:  # dh mode

                if alg == encryption_mode and ex_mode == exchange_mode:
                    signature = cipher_rsa.numlist_to_decryption_str(stream["signature"], friend_pbk[0],
                                                                     friend_pbk[1])
                    if stream["msg"] == signature:
                        while stream["from"] not in dh_shared_key_list.keys():
                            __askPak__(stream["from"], tuple(friend_certificate["address"]))
                        if encryption_mode == "des3":
                            key_random = cipher_des3.generate_key(dh_shared_key_list[stream["from"]])
                            message = cipher_des3.decode(stream["msg"], key_random)
                        elif encryption_mode == "des":
                            key_random = cipher_des.generate_key(dh_shared_key_list[stream["from"]])
                            message = d.decode(stream["msg"], key_random)
                        elif encryption_mode == "caesar":
                            key_random = cipher_caesar.generate_key(dh_shared_key_list[stream["from"]])
                            message = cipher_caesar.decode(stream["msg"], key_random)
                        else:
                            key_random = cipher_playfair.generate_key(dh_shared_key_list[stream["from"]])
                            message = cipher_playfair.decode(stream["msg"], cipher_playfair.generate_table(key_random))
                        if update_on_receive:
                            text.insert(tkinter.INSERT,
                                        stream["from"] + ":" + message + '\n')  # Display on the information box
                        else:
                            message_list[stream["from"]].append(message)
                else:
                    text.insert(tkinter.INSERT, stream["from"] +
                                " send msg using " + alg + "," + ex_mode + ", but you are using " + encryption_mode + "," + exchange_mode + "\n")
        elif stream["type"] == "file":
            recvFile(stream["name"], stream["hash"], stream["encoding"], stream["sender"])
p, a = cipher_dh.generate_key()
pvk_a = random.randint(0, p - 1)
pak_a = cipher_dh.get_pak(p, a, pvk_a)

client_msg = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
address = ('localhost', 1024)
client_msg.bind(address)  # udp

certificate = {
    "pbk": pbk,
    "alg": encryption_mode,
    "hash": "md5",
    "ex_mode": exchange_mode,
    "valid_before": str(datetime.datetime.now() + datetime.timedelta(minutes=10)),
    "address": address
}
certificate_list = defaultdict(dict)
my_sek_list = {"caesar": cipher_caesar.generate_key(), "des": cipher_des.generate_key(),
               "des3": cipher_des3.generate_key(), "playfair": cipher_playfair.generate_key()}

d = cipher_des.des()

buffer = 4096

message_list = defaultdict(list)

update_on_receive = True

win.mainloop()