使用 LSB 隐写术的 Python3 youtube 抗压缩性

问题描述 投票:0回答:1

我有一些代码使用 LSB 隐写术来隐藏视频帧中的加密数据。我遇到的主要问题是我不知道我能做些什么来使视频更能抵抗 YouTube 压缩/压缩。我也找不到更好的隐写库来提供帮助。

就我的尝试而言,我考虑过使用 ECC,但我使用的库“stegano”除了“red”和“lsb”之外实际上没有任何东西。我还考虑过将生成的视频编辑为随机颜色的一大帧,也许会使压缩效果不那么有效,但它仍然不起作用。

就我所说的“Youtube 压缩”而言,视频最终会上传到不公开的 YouTube,然后我可以下载它并显示隐藏的加密数据,然后从那里开始。

以下是我当前使用的代码,无需压缩即可工作。

这段代码工作得很好,并且完全符合我的要求。问题是当我将视频上传到 YouTube 并从 YouTube 下载视频时,它会损坏。

import cv2
import numpy as np
import secrets
import string
import os
import beaupy #Teminal User Interface | TUI. aka nice menu
from pystyle import Colors, Colorate
import math
from tqdm import tqdm
from stegano import lsb #what I use to hide and reveal data.
import shutil
import magic
import gcm
import base64
from pytube import YouTube #downloading video from youtube
from subprocess import call,STDOUT


def clear():
    os.system('clear||cls')



def get_file_type(bytes_data):
    mime = magic.Magic(mime=True)
    file_type = mime.from_buffer(bytes_data)
    return file_type.split('/')[1]


def generate_filename():
    alphabet = string.ascii_letters + string.digits
    filename = ''.join(secrets.choice(alphabet) for i in range(12)) + ".mp4"
    return filename



def generate_video():
    output_filename = generate_filename()
    duration=7
    width=640
    height=480
    fps=30

    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(output_filename, fourcc, fps, (width, height))

    # Generate "random" background color  |  BGR from left to right
    background_color = tuple(secrets.randbelow(256) for i in range(3)) #(0, 0, 255) = red

    # Create frames with "random" background color
    for i in tqdm(range(int(fps * duration)), desc="Creating video..."):
        frame = np.zeros((height, width, 3), dtype=np.uint8)
        frame[:, :, :] = background_color
        out.write(frame)

    out.release()
    cv2.destroyAllWindows()
    clear()
    return output_filename





def clean_tmp(path=".tmp"):
    if os.path.exists(path):
        shutil.rmtree(path)
        print("[INFO] tmp files have been cleaned up.\n")



def split_string(s_str,count=25): #up to how many frames the data is embedded into.
    per_c=math.ceil(len(s_str)/count)
    c_cout=0
    out_str=''
    split_list=[]
    for s in s_str:
        out_str+=s
        c_cout+=1
        if c_cout == per_c:
            split_list.append(out_str)
            out_str=''
            c_cout=0
    if c_cout!=0:
        split_list.append(out_str)
    return split_list




def frame_extraction(video):
    if not os.path.exists(".tmp"):
        os.makedirs(".tmp")
    temp_folder=".tmp"
    print("[INFO] tmp directory has been created")
    vidcap = cv2.VideoCapture(video)
    count = 0
    while True:
        success, image = vidcap.read()
        if not success:
            break
        cv2.imwrite(os.path.join(temp_folder, "{:d}.png".format(count)), image)
        count += 1



def encode_video(file_name):
    clear()
    key_data = beaupy.prompt("Data for key gen")
    if not key_data:
        clear()
        return None
    key_data = key_data.encode()

    clear()
    eKey = gcm.keygen(key_data) #Returns random bytes from Argon2id and will return "None" if what's provided is less than 100 characters.
    if not eKey:
        return None

    save_me = base64.b64encode(eKey) #for saving eKey to decrypt later.
    input(f'Save this key so you can decrypt and decode later: {save_me.decode()}\n\nPress "enter" to contine...')
    clear()

    with open(file_name, 'rb') as rb:
        data = rb.read()
        data_enc = gcm.stringE(enc_data=data, key=eKey) #encrypts data and returns base64 encoded string


    video_file = generate_video()
    frame_extraction(video_file)

    root=".tmp/"
    split_string_list = split_string(data_enc)
    for i in range(0, len(split_string_list)):
        f_name=f"{root}{i}.png"
        secret_enc=lsb.hide(f_name, split_string_list[i])
        secret_enc.save(f_name)
        print(f"[INFO] frame {f_name} holds {split_string_list[i]}")

    output_vid = '.tmp_vid.mp4'
    call(["ffmpeg", "-i", ".tmp/%d.png" , "-vcodec", "png", output_vid, "-y"], stdout=open(os.devnull, "w"), stderr=STDOUT)
    cwd = os.getcwd()
    os.walk(f".tmp/{output_vid}", cwd)
    clean_tmp()
    os.rename(output_vid, video_file)




def decode_video(video, b64_enc_key):
    frame_extraction(video)
    secret=[]
    root=".tmp/"
    for i in range(len(os.listdir(root))):
        f_name=f"{root}{i}.png"
        try:
            secret_dec=lsb.reveal(f_name)
            print(f"Found data in: {f_name}. Data: {secret_dec}")
        except Exception:
            break
        secret.append(secret_dec)

    result = ''.join([i for i in secret]) # base64 string
    clean_tmp()
    dKey = base64.b64decode(b64_enc_key)

    str_dcr = gcm.stringD(dcr_data=result, key=dKey)
    gcm.clear()
    return str_dcr


# ... (if __name__ == '__main__': code and the creation of the beaupy menu options would be below this line)

我正在寻求帮助的是如何有效地处理压缩并简单地使用LSB/上面显示的代码。如果“stegano”库不够好,那么推荐任何其他更好的库或方法将非常感激。如果有人有其他文档可以分享,那也会有帮助。

请随意帮助编写一个或两个函数来帮助我处理视频的压缩问题。

另外..如果 LSB 无论如何都不起作用,那么更好的选择是什么?您能否提供带有示例的链接/文档,供我使用,以便我可以使用。 (这可以在上面显示的代码以及我如何使用多个框架的上下文中工作)

python python-3.x steganography video-compression
1个回答
0
投票

YouTube 重新压缩上传到其中的所有视频。尽管水印的设计可以在重新压缩后继续存在,但基本的隐写术(例如 LSB)会因此被完全破坏。

能够在再压缩中幸存下来的鲁棒隐写术是一个活跃的研究领域。

  • Fan、Zhang、Zhao:具有最小嵌入成本的自适应 QIM,可实现社交网络上的鲁棒视频隐写术。 2022.
  • Mstfa、Elleithy、Abdelfattah:稳健且安全的视频隐写术 基于多重的DWT-DCT域方法 对象跟踪和 ECC。 2017.

恐怕您需要等待很长时间才能找到一个好的、既定的解决方案来解决您的问题。

© www.soinside.com 2019 - 2024. All rights reserved.