简单视频加密与授权

原创文章,转载请注明原始链接,谢谢!

应同学邀请参加信息安全大赛,负责作品的"离线空间"模块,简单来说,离线空间就是要求加密视频只能在指定机器播放,并且只能播放规定次数。

思维导图如下


运行环境:JDK1.8, WIN8


一、加密视频EncVideo部分由以下几个模块组成:

1、Mac.java 

负责获取本地Mac

//获取本机MAC地址
//提供一个方法 String getMac()
//返回本机Mac地址
package org.tree.enc;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Mac {
	public String getMac() throws IOException
	{
		String MacAddress = null;
		BufferedReader br = null;
		Process pro = null;
		try{
			pro = Runtime.getRuntime().exec("ipconfig /all");
			br = new BufferedReader(new InputStreamReader(pro.getInputStream()));
			int index = -1;
			String line = null;
			while((line = br.readLine()) != null){
				String t = "物理地址";
				String que = new String(t.getBytes("GBK"));
				if(((index = line.indexOf(que)) != -1) || ((index = line.toLowerCase().indexOf("physical address")) != -1)){
					index = line.indexOf(":");
					MacAddress = line.substring(index + 1).trim();
					break;
				}
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		finally{
			br.close();
		}
		return MacAddress;
	}
}


2、MD5.java 

负责将Mac进行MD5加密

//对MAC地址进行MD5加密,生成32位字符串
//提供一个方法String getMD5()
//返回经过MD5加密后的MAC
package org.tree.enc;

import java.security.MessageDigest;

public class MD5 {
	public String getMD5(){
		String RawMessage = null;
		String MD5Message = null;
		try{
			RawMessage = new Mac().getMac();;
			MessageDigest md = MessageDigest.getInstance("MD5");
			md.update(RawMessage.getBytes());
			byte[] b = md.digest();
			StringBuffer temp = new StringBuffer("");
			for(int i = 0 ; i < b.length; i++){
				int tep = b[i];
				if(tep < 0){
					tep += 256;
				}
				if(tep < 16){
					temp.append("0");
				}
				temp.append(Integer.toHexString(tep));
			}
			MD5Message = temp.toString();
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return MD5Message;
	}
}


3、EncVideo.java 

负责对视频进行加密

//加密视频,在视频末尾添加MAC的MD5,生成Result.k文件
//提供一个方法 void encVideo(String InPath, String OutPath)
//InPath:需要加密的文件路径 OutPath:输出文件路径
package org.tree.enc;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;


public class EncVideo {
	public void encVideo(String InPath, String OutPath) throws IOException
	{
		FileInputStream in  = null;
		FileOutputStream out = null;
		try{
			in = new FileInputStream(InPath);	
			out = new FileOutputStream(new File(OutPath+"\\Result.k"));
			byte[] b = new byte[1024];
			int temp = 0;
			while((temp = in.read(b)) != -1){
				out.write(b);
			}
			out.write(new MD5().getMD5().getBytes());
		}
		catch(Exception e){
			e.printStackTrace();
		}
		finally{
			if(in != null){
				in.close();
			}
			if(out != null){
				out.close();
			}
		}
	}
}


4、UI.java

负责GUI部分

package org.tree.enc;

import java.awt.BorderLayout;
import java.io.File;



import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class UI {
	private String InPath = null;
	private String OutPath = null;
	
	public UI(){
		JFrame f = new JFrame("加密视频");
		f.setSize(200, 150);
		f.setResizable(false);
		JPanel p1 = new JPanel();
		JPanel p2 = new JPanel();
		JPanel p3 = new JPanel();
		JFileChooser fc1 = new JFileChooser();
		JButton b1 = new JButton("选择加密文件");
		JFileChooser fc2 = new JFileChooser();
		JButton b2 = new JButton("选择保存位置");
		JButton b3 = new JButton("加密");
		p1.add(b1);
		p2.add(b2);
		p3.add(b3);
		f.add(p1, BorderLayout.NORTH);
		f.add(p2, BorderLayout.CENTER);
		f.add(p3, BorderLayout.SOUTH);
		f.setVisible(true);
		
		b1.addActionListener(event -> {
			fc1.setDialogTitle("请选择需要加密的文件");
			fc1.showOpenDialog(b1);
		});
		
		b2.addActionListener(event -> {
			fc2.setDialogTitle("请选择要保存的位置");
			fc2.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
			fc2.showSaveDialog(b2);
		});
		
		fc1.addPropertyChangeListener(event -> {
			if(event.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY){
				File file = (File)event.getNewValue();
				InPath = file.getPath();
			}
		});
		
		fc2.addPropertyChangeListener(event -> {
			if(event.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY){
				File file = (File)event.getNewValue();
				OutPath = file.getPath();
			}
		});
		
		b3.addActionListener(event -> {
			try{
				if(InPath == null){
					JDialog d = new JDialog(f, "您没有选择需要加密的文件!", true);
					JLabel la = new JLabel("请选择需要加密的文件!", JLabel.CENTER);
					d.add(la, BorderLayout.CENTER);
					d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					d.setSize(300, 100);
					d.setVisible(true);
				}
				
				else if(OutPath == null){
					JDialog d = new JDialog(f, "您没有选择保存的位置!", true);
					JLabel la = new JLabel("请选择需要保存的位置!", JLabel.CENTER);
					d.add(la, BorderLayout.CENTER);
					d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					d.setSize(300, 100);
					d.setVisible(true);
				}
				else{
					new EncVideo().encVideo(InPath, OutPath);
					JDialog d = new JDialog(f, "加密完毕!", false);
					JLabel la = new JLabel("加密完毕!", JLabel.CENTER);
					d.add(la, BorderLayout.CENTER);
					d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					d.setSize(300, 100);
					d.setVisible(true);
				}
			}
			catch(Exception e){
				e.printStackTrace();
			}
		});
		
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	public static void main(String[] args){
		new UI();
	}
}

运行效果(以test.mp4为例):

1、程序主界面


2、程序运行结果




二、解密视频DecVideo由以下几个模块组成:

1、Mac.java

获取MAC 同上

2、MD5.java

对MAC进行MD5加密 同上

3、DecVideo.java

负责对提取视频中的MD5

//提取视频中MAC
//提供一个方法 String getMacMD5(String path)
//返回视频中的MAC path:要打开的加密文件的路径
package org.tree.pla;

import java.io.RandomAccessFile;

public class DecVideo {
	public String getMacMD5(String path){
		String VideoMD5 = null;
		try(RandomAccessFile raf = new RandomAccessFile(path, "r")){
			long len = raf.length();
			raf.seek(len-32);
			byte[] b = new byte[32];
			raf.read(b);
			VideoMD5 = new String(b);
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return VideoMD5;
	}
}
4、PlayVideo.java

负责调用本地播放器播放视频

//播放视频
//提供两个方法 boolean CompareMD5(String path)
//比较视频中的MAC与本地MAC
//void Player(Sting path)
//播放视频
//提供一个类变量 int count 用来标识剩余授权次数
package org.tree.pla;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.RandomAccessFile;

public class PlayVideo {
	public static int count = 10;
	public boolean CompareMD5(String path){
		String VideoMD5 = new DecVideo().getMacMD5(path);
		String LocalMD5 = new MD5().getMD5();
		if(VideoMD5.equals(LocalMD5)){
			return true;
		}
		else{
			return false;
		}
	}
	
	public void Player(String path){
		if(new PlayVideo().CompareMD5(path)){
			try{
				FileInputStream in = new FileInputStream(path);
				FileOutputStream out = new FileOutputStream("C:\\tmp\\isctmp.avi");
				byte[] tmpb = new byte[1024];
				int index = 0;
				while((index = in.read(tmpb)) != -1){
					out.write(tmpb);
				}
				in.close();
				out.close();
				
				File f = new File("C:\\Users\\Public\\Documents\\IscInfo.ini");
				if(f.exists()){
					RandomAccessFile raf = new RandomAccessFile(f, "rw");
					byte[] b = new byte[4];
					raf.read(b);
					String result = new String(b);
					int num = Integer.parseInt(result.trim());
					if(num != 0 && num <= 10){
						raf.setLength(0);
						num--;
						PlayVideo.count = num;
						String numtmp = num + "";
						raf.write(numtmp.getBytes());
						
						Process pro = Runtime.getRuntime().exec("C:\\Program Files\\Windows Media Player\\wmplayer.exe " + "C:\\tmp\\isctmp.avi");
					}
					else{
						File inf = new File(path);
						inf.delete();
					}
					raf.close();
				}
				else{
					PlayVideo.count = 10;
					FileOutputStream out1 = new FileOutputStream(f.getPath());
					out1.write("10".getBytes());
					Process pro = Runtime.getRuntime().exec("C:\\Program Files\\Windows Media Player\\wmplayer.exe " + "C:\\tmp\\isctmp.avi");
					out1.close();
				}
			}
			catch(Exception e){
				e.printStackTrace();
			}
		}
		else{
			System.out.println("你不能播放这个视频");
		}
	}
}
6、UI.java

负责GUI,验证授权信息

package org.tree.pla;

import java.awt.BorderLayout;


import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;

public class UI {
	private String path = null;
	public UI(){
		JFrame f = new JFrame("播放加密视频");
		f.setSize(250, 100);
		f.setResizable(false);
		JButton b1 = new JButton("选择加密文件");
		JButton b2 = new JButton("播放");
		JFileChooser fc = new JFileChooser();
		f.add(b1, BorderLayout.CENTER);
		f.add(b2, BorderLayout.SOUTH);
		f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		f.setVisible(true);
		
		b1.addActionListener(event -> {
			fc.setDialogTitle("请选择需要打开的文件");
			fc.showOpenDialog(b1);
		});
		
		b2.addActionListener(event -> {
			if(path == null){
				JDialog d = new JDialog(f, "您没有选择打开的文件!", true);
				JLabel la = new JLabel("请选择需要打开的文件!", JLabel.CENTER);
				d.add(la, BorderLayout.CENTER);
				d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
				d.setSize(300, 100);
				d.setVisible(true);
			}
			if(new PlayVideo().CompareMD5(path)){
				if(PlayVideo.count <= 0){
					JDialog d = new JDialog(f, "权限不足", true);
					JLabel la = new JLabel("您的剩余授权次数不足!", JLabel.CENTER);
					d.add(la, BorderLayout.CENTER);
					d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					d.setSize(300, 100);
					d.setVisible(true);
					File file = new File(path);
					file.delete();
				}
				else{
					new PlayVideo().Player(path);
					JDialog d = new JDialog(f, "剩余使用次数");
					JLabel la = new JLabel("剩余使用次数为: " + PlayVideo.count, JLabel.CENTER);
					d.add(la, BorderLayout.CENTER);
					d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
					d.setSize(300, 100);
					d.setVisible(true);
				}
			}
			else{
				JDialog d = new JDialog(f, "权限不足", true);
				JLabel la = new JLabel("您没有别授权打开此文件!", JLabel.CENTER);
				d.add(la, BorderLayout.CENTER);
				d.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
				d.setSize(300, 100);
				d.setVisible(true);
				File file = new File(path);
				file.delete();
			}
		});
		
		fc.addPropertyChangeListener(event -> {
			if(event.getPropertyName() == JFileChooser.SELECTED_FILE_CHANGED_PROPERTY){
				File file = (File)event.getNewValue();
				path = file.getPath();
			}
		});
	
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				try{
					File file = new File("C:\\tmp\\isctmp.avi");
					file.delete();
				}
				catch(Exception ex){
					ex.printStackTrace();
				}
				System.exit(0);
			}
		});
	}


	public static void main(String[] args){
		new UI();
	}
}

程序运行结果:

1、程序主界面


2、程序运行界面



小结

简单的视频加密,不过现在的加密非常的脆弱,比如将.k改名为.avi等视频格式就可以正常播放,修改授权信息内容就可以无限次播放,将隐式转换成视频格式的文件复制一份也可以正常播放。要对抗这种方式的攻击就需要用到其他加密方法,这就不在本文讨论范围了QAQ(其实我会说我也不懂吗。。。我只负责这个模块,听说还有左右手识别,吧唧吧唧的什么的加密方法Orz)

PS.忽略我写的渣的JAVA代码。。新手...IO方面各种流乱用 还有GUI那写的更不能看了QAQ


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值