new update v1.5

new encrypt system
This commit is contained in:
dharm pimsen 2023-12-18 18:24:23 +07:00
parent 82ba9cf8b4
commit c4c75f10e0
2 changed files with 127 additions and 12 deletions

View File

@ -9,6 +9,9 @@ import pickle
import pyaudio import pyaudio
from pyogg import OpusDecoder from pyogg import OpusDecoder
from damp11113 import CV22DPG from damp11113 import CV22DPG
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import scrypt
from Crypto.Random import get_random_bytes
librarylist = ["Opencv (opencv.org)", "PyOgg (TeamPyOgg)", "DearPyGui (hoffstadt)"] librarylist = ["Opencv (opencv.org)", "PyOgg (TeamPyOgg)", "DearPyGui (hoffstadt)"]
@ -37,6 +40,25 @@ def limit_string_in_line(text, limit):
return '\n'.join(new_lines) return '\n'.join(new_lines)
def unpad_message(padded_message):
padding_length = padded_message[-1]
return padded_message[:-padding_length]
def decrypt_data(encrypted_message, password, salt, iv):
# Derive the key from the password and salt
key = scrypt(password, salt, key_len=32, N=2 ** 14, r=8, p=1)
# Initialize AES cipher in CBC mode
cipher = AES.new(key, AES.MODE_CBC, iv)
# Decrypt the message
decrypted_message = cipher.decrypt(encrypted_message)
# Unpad the decrypted message
unpadded_message = unpad_message(decrypted_message)
return unpadded_message
class App: class App:
def __init__(self): def __init__(self):
self.RDS = None self.RDS = None
@ -46,6 +68,10 @@ class App:
self.firstrun = True self.firstrun = True
self.firststart = True self.firststart = True
self.device_index_output = 0 self.device_index_output = 0
self.ccdecryptpassword = None
self.ccisencrypt = None
self.ccisdecrypt = None
self.ccisdecryptpassword = None
def connecttoserver(self, sender, data): def connecttoserver(self, sender, data):
dpg.configure_item("connectservergroup", show=False) dpg.configure_item("connectservergroup", show=False)
@ -85,6 +111,10 @@ class App:
dpg.configure_item("serverstatus", default_value='disconnected', color=(255, 0, 0)) dpg.configure_item("serverstatus", default_value='disconnected', color=(255, 0, 0))
self.firstrun = True self.firstrun = True
self.firststart = True self.firststart = True
self.ccdecryptpassword = None
self.ccisencrypt = None
self.ccisdecrypt = None
self.ccisdecryptpassword = None
def RDSshow(self): def RDSshow(self):
try: try:
@ -110,6 +140,10 @@ class App:
dpg.configure_item("station_logo_config", show=False) dpg.configure_item("station_logo_config", show=False)
self.readchannel = int(dpg.get_value(sender).split(" ")[0]) self.readchannel = int(dpg.get_value(sender).split(" ")[0])
self.firstrun = True self.firstrun = True
self.ccdecryptpassword = None
self.ccisencrypt = None
self.ccisdecrypt = None
self.ccisdecryptpassword = None
p = pyaudio.PyAudio() p = pyaudio.PyAudio()
@ -120,6 +154,11 @@ class App:
self.device_index_output = dev['index'] self.device_index_output = dev['index']
break break
def submitpassworddecrypt(self, sender, data):
dpg.configure_item("requestpasswordpopup", show=False)
self.ccdecryptpassword = dpg.get_value("requestpasswordinputpopup")
self.ccisdecryptpassword = True
def stream(self, socket): def stream(self, socket):
opus_decoder = None opus_decoder = None
streamoutput = None streamoutput = None
@ -191,7 +230,7 @@ class App:
if len(datadecoded["channel"]) > 1: if len(datadecoded["channel"]) > 1:
channel_info = [] channel_info = []
for i in range(1, len(datadecoded["channel"]) + 1): for i in range(1, len(datadecoded["channel"]) + 1):
channel_info.append(f'{i} {datadecoded["channel"][i]["Station"]} ({datadecoded["channel"][i]["RDS"]["ContentInfo"]["Codec"]} {datadecoded["channel"][i]["RDS"]["ContentInfo"]["bitrate"] / 1000}Kbps {datadecoded["channel"][i]["RDS"]["AudioMode"]})') channel_info.append(f'{i} {"[Encrypt]" if datadecoded["channel"][i]["Encrypt"] else "[No Encrypt]"} {datadecoded["channel"][i]["Station"]} ({datadecoded["channel"][i]["RDS"]["ContentInfo"]["Codec"]} {datadecoded["channel"][i]["RDS"]["ContentInfo"]["bitrate"] / 1000}Kbps {datadecoded["channel"][i]["RDS"]["AudioMode"]})')
dpg.configure_item("mediachannelselect", show=True, items=channel_info) dpg.configure_item("mediachannelselect", show=True, items=channel_info)
dpg.configure_item("morerdsbutton", show=True) dpg.configure_item("morerdsbutton", show=True)
dpg.configure_item("serverinfobutton", show=True) dpg.configure_item("serverinfobutton", show=True)
@ -205,26 +244,54 @@ class App:
if self.firststart: if self.firststart:
self.readchannel = datadecoded["mainchannel"] self.readchannel = datadecoded["mainchannel"]
dpg.configure_item("mediachannelselect", show=True, default_value="mainchannel") dpg.configure_item("mediachannelselect", show=True, default_value="mainchannel")
dpg.configure_item("serverstatus", default_value='connected --Kbps (----)', color=(0, 255, 0))
# check if channel is encrypted
if datadecoded["channel"][self.readchannel]["Encrypt"]:
dpg.configure_item("requestpasswordpopup", show=True)
dpg.configure_item("serverstatus", default_value='connected', color=(0, 255, 0))
self.ccisencrypt = True
else:
dpg.configure_item("serverstatus", default_value='connected --Kbps (----)', color=(0, 255, 0))
self.firstrun = False self.firstrun = False
self.firststart = False self.firststart = False
if not self.firstrun: if not self.firstrun:
decoded_pcm = opus_decoder.decode(memoryview(bytearray(datadecoded["channel"][self.readchannel]["Content"]))) data = datadecoded["channel"][self.readchannel]["Content"]
if self.ccisdecryptpassword and self.ccisencrypt:
try:
# decrypt data
encryptdata = data.split(b'|||||')[0]
salt = data.split(b'|||||')[1]
iv = data.split(b'|||||')[2]
data = decrypt_data(encryptdata, self.ccdecryptpassword, salt, iv)
if data == b'':
self.ccisdecrypt = False
self.ccdecryptpassword = None
else:
self.ccisdecrypt = True
except:
dpg.configure_item("serverstatus", default_value="Decrypt Error", color=(255, 0, 0))
if self.ccisdecrypt or not self.ccisencrypt:
decoded_pcm = opus_decoder.decode(memoryview(bytearray(data)))
# Check if the decoded PCM is empty or not
if len(decoded_pcm) > 0:
pcm_to_write = np.frombuffer(decoded_pcm, dtype=np.int16)
streamoutput.write(pcm_to_write.tobytes())
else:
print("Decoded PCM is empty")
if len(adcctfrpy) > 250: if len(adcctfrpy) > 250:
adcctfrpy.pop(0) adcctfrpy.pop(0)
adcctfrpy.append(len(datadecoded["channel"][self.readchannel]["Content"])) adcctfrpy.append(len(datadecoded["channel"][self.readchannel]["Content"]))
dpg.set_value('transferateaudiodataoncchannelplot', [tfrpx, adcctfrpy]) dpg.set_value('transferateaudiodataoncchannelplot', [tfrpx, adcctfrpy])
# Check if the decoded PCM is empty or not
if len(decoded_pcm) > 0:
pcm_to_write = np.frombuffer(decoded_pcm, dtype=np.int16)
streamoutput.write(pcm_to_write.tobytes())
else:
print("Decoded PCM is empty")
bytesconunt_frame += 1 bytesconunt_frame += 1
else: else:
streamoutput.close() streamoutput.close()
@ -241,6 +308,7 @@ class App:
pass pass
socket.close() socket.close()
self.disconnectserver() self.disconnectserver()
raise
break break
def window(self): def window(self):
@ -330,6 +398,13 @@ class App:
dpg.add_spacer(height=20) dpg.add_spacer(height=20)
dpg.add_text(f"Copyright (C) 2023 ThaiSDR All rights reserved. (GPLv3)") dpg.add_text(f"Copyright (C) 2023 ThaiSDR All rights reserved. (GPLv3)")
with dpg.window(label="Password Required", tag="requestpasswordpopup", modal=True, no_resize=True, no_close=True, no_move=True, show=False):
dpg.add_text("This channel is encrypt! Please enter password for decrypt.")
dpg.add_spacer()
dpg.add_input_text(label="password", tag="requestpasswordinputpopup")
dpg.add_spacer()
dpg.add_button(label="confirm", callback=self.submitpassworddecrypt)
def menubar(self): def menubar(self):
with dpg.viewport_menu_bar(): with dpg.viewport_menu_bar():
with dpg.menu(label="File"): with dpg.menu(label="File"):

View File

@ -9,6 +9,36 @@ from damp11113 import scrollTextBySteps
from queue import Queue from queue import Queue
from datetime import datetime, timezone from datetime import datetime, timezone
import cv2 import cv2
from Crypto.Cipher import AES
from Crypto.Protocol.KDF import scrypt
from Crypto.Random import get_random_bytes
def pad_message(message_bytes):
block_size = AES.block_size
padding_length = block_size - (len(message_bytes) % block_size)
padding = bytes([padding_length] * padding_length)
return message_bytes + padding
def encrypt_data(message_bytes, password):
# Derive a key from the password
salt = get_random_bytes(16)
key = scrypt(password, salt, key_len=32, N=2 ** 14, r=8, p=1)
# Generate an IV (Initialization Vector)
iv = get_random_bytes(AES.block_size)
# Pad the message
padded_message = pad_message(message_bytes)
# Initialize AES cipher in CBC mode
cipher = AES.new(key, AES.MODE_CBC, iv)
# Encrypt the padded message
encrypted_message = cipher.encrypt(padded_message)
# Return the encrypted message, salt, and IV (for decryption)
return encrypted_message, salt, iv
# create tcp # create tcp
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
@ -206,9 +236,11 @@ def encode_audio():
encoded_packets = encoder.buffered_encode(memoryview(bytearray(pcm))) encoded_packets = encoder.buffered_encode(memoryview(bytearray(pcm)))
for encoded_packet, _, _ in encoded_packets: for encoded_packet, _, _ in encoded_packets:
# Put the encoded audio into the buffer # Put the encoded audio into the buffer
channel1.put(encoded_packet.tobytes()) channel1.put(encoded_packet.tobytes())
def encode_audio2(): def encode_audio2():
encoder2 = OpusBufferedEncoder() encoder2 = OpusBufferedEncoder()
encoder2.set_application("audio") encoder2.set_application("audio")
@ -240,18 +272,26 @@ def handle_client():
while True: while True:
# Get the encoded audio from the buffer # Get the encoded audio from the buffer
ENchannel1 = channel1.get() ENchannel1 = channel1.get()
# encrypt data
ENC1encrypted, ENC1salt, ENC1iv = encrypt_data(ENchannel1, "password")
ENchannel1 = ENC1encrypted + b'|||||' + ENC1salt + b'|||||' + ENC1iv
ENchannel2 = channel2.get() ENchannel2 = channel2.get()
content = { content = {
"mainchannel": 1, "mainchannel": 1,
"channel": { "channel": {
1: { 1: {
"Station": "DPRadio+", "Station": "DPRadio+",
"Encrypt": b'|||||' in ENchannel1, # check if encrypt
"ContentSize": len(ENchannel1), "ContentSize": len(ENchannel1),
"Content": ENchannel1, "Content": ENchannel1,
"RDS": RDS "RDS": RDS
}, },
2: { 2: {
"Station": "DPTest", "Station": "DPTest",
"Encrypt": b'|||||' in ENchannel2,
"ContentSize": len(ENchannel2), "ContentSize": len(ENchannel2),
"Content": ENchannel2, "Content": ENchannel2,
"RDS": RDS2 "RDS": RDS2