当前正快速进入崭新的移动互联网时代,移动即时通信是厂商在移动互联网领域争夺的重点,但是与此同时,智能手机的安全性、私密性等问题逐渐引起大家的重视。本文实现了一个安全即时视频通信软件,其通过对即使通信的视频信息进行AES加密,保证了即时通信视频的的安全性和私密性。
总体设计
1.总体方案
Android智能终端安全视频通信采用客户端对客户端架构,具体模块划分如图1所示。总的来说,通过AES密钥设定,加解密模块为用户提供安全保障;通过界面模块给用户带来更好的UI和使用体验。
图1系统架构图
2.客户端部分
1)通信模块
客户端通信模块实现视频的通信以及其他相关功能。该模块在发送数据时,从摄像头提取数据,将数据按照自定义的协议(由协议处理模块处理)进行封装,并利用UDP协议将数据传送给对方;在接收数据时,首先利用UDP协议通过socket通信接收数据,然后将数据按照自定义的协议进行解析,解析之后,将视频数据通过话筒/屏幕显示出来。
2)AES设定模块
从客户端界面输入AES密钥,通过密钥获取比较,确定通话双方会话所用的AES密钥。
3)加解密模块
客户端加解密模块用于对传输的视频信息进行端对端的加解密。需要在保证传输信息机密性的同时考虑系统工作效率,为此,我们采用了128位的AES加密算法。在每次视频之前,视频双方都会通过密钥获取比较模块来确定AES密钥。
4)UI模块
该模块为用户尽可能提供友好的人机交流UI界面,其中主要界面有:主界面、操作界面(视频操作功能)、呼叫界面(静音、免提、挂断功能)、接听界面(视频通信显示)。
1.详细操作流程
用户在打开客户端进入主界面后,输入对方的手机的ip,然后开始进行视频邀请,当接收方同意后,自动开启密钥获取比较流程进行密钥比较,在密钥比较成功后可以进行视频通话.
2.系统代码详细设计
1)输入AES密钥
privatevoidopenFirendPopup(finalStringname,finalintphoto,intflag){ Viewview=LayoutInflater.from(this).inflate( R.layout.aesput,null); Buttonsendase=(Button)view.findViewById(R.id.sendase); finalAlertDialogalertDialog = new AlertDialog.Builder(this).setView(view).create(); sendase.setOnClickListener(newView.OnClickListener(){ publicvoidonClick(Viewv){ if(!.equals(getaes())){ Key_Deal.setFlag(Key_Deal.VIDEO_FLAG); MainHandler.sendRequestForVideo(name); MainHandler.startVideoActivity(name,photo); alertDialog.dismiss(); }} }); if(flag==0){ sendase.setEnabled(false); } alertDialog.show(); }
在弹出的界面中,输入AES密钥,当输入框不为空时,点击发送按钮,则可以邀请对方开视频,然后界面消失。
2)输入AES并接受好友视频的邀请
privatevoidinitClick(){ accept.setOnClickListener(newView.OnClickListener(){ publicvoidonClick(Viewv){ if(flag== Key_Deal.VIDEO_FLA.equals(getaes())) {startVideoActivity(); Key_Deal.setFlag(Key_Deal.VIDEO_FLAG); Video_Info.setIP(IP); Voice_Info.setIP(IP); Key_Info.setIP(IP); } } });
当点击发送按钮时,邀请好友开视频。当好友收到邀请后,输入AES密钥,点击接受,密钥比较线程则开始进行密钥比较,当双方输入的AES密钥相等时,则设定为此次双方进行视频的会话密钥。
3)密钥线程开始进行密钥获取及比较
publicstaticvoidbeginKeyThread(Stringip){ Video_Info.setIP(ip); Key_Info.setIP(ip); Key_InfosendInfo=newKey_Info(); sendInfo.setHead(newbyte[]{0x00}); Key_Thread.send(sendInfo); } publicstaticvoidsendPartOfAesOne(){ ase=FriendList_Activity.getaes(); byte[]byase1=MyKey.parseHexStr2Byte(ase); MyKey.setAesPassword1(byase1); MyKey.setAesKey(byase1); Key_Infokey_Info=newKey_Info(); byte[]head=newbyte[]{0x02}; key_Info.setHead(head); key_Info.setPartOfPassword(byase1); Key_Thread.send(key_Info); } privatestaticvoiddeal0x02(byte[]password1){ MyKey.setAesPassword1(password1); MainHandler.sendPartOfAesTwo(); MyKey.initAESKey(); } publicstaticvoidsendPartOfAesTwo(){ ase=BeCalled_Activity.getaes(); byte[]byase2=MyKey.parseHexStr2Byte(ase); MyKey.setAesPassword2(byase2); Key_Infokey_Info=newKey_Info(); byte[]head=newbyte[]{0x03}; key_Info.setHead(head); key_Info.setPartOfPassword(byase2); Key_Thread.send(key_Info); } privatestaticvoiddeal0x03(byte[]password2){ MyKey.setAesPassword2(password2); MyKey.initAESKey(); } publicstaticvoidinitAESKey(){ if(aesPassword1.length==0aesPassword2.length==0) return; aes1=parseByte2HexStr(aesPassword1); aes2=parseByte2HexStr(aesPassword2); if(aes1.equals(aes2)){ aesKey=parseHexStr2Byte(aes1); } } publicstaticStringparseByte2HexStr(bytebuf[]){ StringBuffersb=newStringBuffer(); for(inti=0;i<buf.length;i++){ Stringhex=Integer.toHexString(buf[i]0xFF); if(hex.length()==1){ hex='0'+hex; } sb.append(hex.toUpperCase()); } returnsb.toString(); } publicstaticbyte[]parseHexStr2Byte(StringhexStr){ if(hexStr.length()<1) returnnull; byte[]result=newbyte[hexStr.length()/2]; for(inti=0;i<hexStr.length()/2;i++){ inthigh=Integer.parseInt(hexStr.substring(i*2,i*2+1),16); intlow=Integer.parseInt(hexStr.substring(i*2+1,i*2+2),16); result[i]=(byte)(high*16+low); } returnresult; }
以上代码是将16进制转换为二进制,也就是将string类型转换为字节型。通信所需要的AES密钥是byte型,所以需要将从edittext中获取的string型密钥转换为byte,然后为通信进行加密。
4)AES加密
publicstaticbyte[]AESencrypt(byte[]byteContent){ if(aesKey==null) returnnull; try{ SecretKeySpeckey=newSecretKeySpec(aesKey,AES); Ciphercipher=Cipher.getInstance(AES); cipher.init(Cipher.ENCRYPT_MODE,key); byte[]result=cipher.doFinal(byteContent); returnresult; }catch(NoSuchAlgorithmExceptione){ e.printStackTrace(); }catch(NoSuchPaddingExceptione){ e.printStackTrace(); }catch(InvalidKeyExceptione){ e.printStackTrace(); }catch(IllegalBlockSizeExceptione){ e.printStackTrace(); }catch(BadPaddingExceptione){ e.printStackTrace(); } returnnull; }
此段代码是AES加密。首先创建密码器,接着初始化,然后对将要发送出去的要加密的视频数据流内容进行加密。
5)AES解密
publicstaticbyte[]AESdecrypt(byte[]content){ if(aesKey==null) returnnull; try{ byte[]enCodeFormat=aesKey; SecretKeySpeckey=newSecretKeySpec(enCodeFormat,AES); Ciphercipher=Cipher.getInstance(AES); cipher.init(Cipher.DECRYPT_MODE,key); byte[]result=cipher.doFinal(content); returnresult; }catch(NoSuchAlgorithmExceptione){ e.printStackTrace(); }catch(NoSuchPaddingExceptione){ e.printStackTrace(); }catch(InvalidKeyExceptione){ e.printStackTrace(); }catch(IllegalBlockSizeExceptione){ e.printStackTrace(); }catch(BadPaddingExceptione){ e.printStackTrace(); } returnnull; }
此段代码是AES解密。先创建密码器,接着初始化,然后对从对方发送过来要解密的视频数据流内容进行解密。
3.视频加密通信测试
1)在正常“保密视频”通信的情况下,发送方使用视频之前确定的AES密钥进行加密,接收方使用AES密钥对视频数据包进行解密,可见双方能够正常进行视频通信,如图3所示。
2)在“攻击者截获视频数据包”的情况下,由于攻击者无法获取AES密钥,因而无法对视频数据包进行解密。攻击者所看到的视频信息只是毫无意义的乱码,如图4所示。