在即时通讯系统(IM)中,加密重要的通信消息,是一个常见的需求。尤其在一些政府部门的即时通信软件中(如税务系统),对即时聊天消息进行加密是非常重要的一个功能,因为谈话中可能会涉及到机密的数据。我在最新的GG 4.5中,增加了对即时聊天消息进行加密的功能,但这一功能并不是强制的,可以通过开关来进行控制。本文就从 为什么要加密消息、不加密有什么风险开始说起,一直到把GG即时通信系统中实现加密消息的完整实现介绍清楚。

想要直接下载体验的朋友请点击:下载中心

一.为什么要加密即时聊天消息?

  我们知道所有的消息在底层是以bytep[]进行传输的,如果文字聊天消息不加密,表示的意思是:直接将string使用utf-8或者unicode编码成byte[],然后,通过网络进行传送。如果在传送过程中的某个环节byte[]被恶意截取,则拦截者将byte[]使用utf-8或unicode进行解码,即可看到原来string的内容。这个过程如下图所示:

  

  对于某些重要的消息而言,这样明文传输的方式实在是太危险了。

  将聊天消息加密的意思是:将string使用utf-8或unicode编码成byte[]后,再做一次加密运算,得到一个新的byte[],然后将这个新的byte[]通过网络发送给对方;对方接收到byte[]后,先将其做解密运算,然后再用utf-8或unicode转为string。这个新过程如下图所示:

    

  这样,即使在网络传送过程中的某个环节byte[]被恶意截取了,拦截者也无法正确的解析它,如此就规避了原来方案的风险。

二.3DES加密

3DES(或称为Triple DES)是非常常用的对称加密算法,是对DES算法的增强,它相当于是对每个数据块应用三次DES加密算法。

在GG即时通信系统 4.5的客户端源码中,Des3Encryption类是实现3DES算法的类,我是根据3DES的算法原理实现的,可能与某些标准的3DES算法实现细节不一样,但是,使用其进行3DES加密、解密是完全能正常运作的。

   可以将Des3Encryption类作为一个工具类,从GG即时通信系统中抽离出来,复用在任何需要的地方。

三.加密/解密即时聊天消息

现在我们正式回到GG即时通信系统的文字聊天逻辑上面来,看看GG是怎么实现聊天消息的加密解密的。

1.准备工作

  GG2014客户端项目中,增加了Des3Encryption.cs文件,实现了3DES算法。

  GlobalResourceManager类增加了加密组件的设置:

    private static Des3Encryption des3Encryption = new Des3Encryption("abcd1234"); // null;
/// <summary>
/// 3DES加密。如果消息不需要加密,则返回null。
/// </summary>
public static Des3Encryption Des3Encryption
{
get { return des3Encryption; }
}

这里有一个开关的功能,即可以开启或关闭聊天消息加密功能。如果将des3Encryption设置为null,就表示不启用聊天消息加密。

2.发送聊天消息

  在GG即时通信系统中,聊天消息有两类,一类是1对1的聊天,另一类是群聊天。如果启用了加密,两类聊天消息都需要做相应的处理,它们的流程是一样的。

在得到聊天内容后,先进行简单的序列化,然后对序列化的结果进行3DES加密:(以1对1聊天的ChatForm窗口中的实现为例,源码的第866行)

    ChatBoxContent content = this.chatBoxSend.GetContent();  byte[] buff = CompactPropertySerializer.Default.Serialize(content);
byte[] encrypted = buff;
if (GlobalResourceManager.Des3Encryption != null)
{
encrypted = GlobalResourceManager.Des3Encryption.Encrypt(buff);
}

  然后,将加密的结果通过IRapidPassiveEngine发送出去。

3.处理接收到的聊天消息

接收到1对1的聊天消息或是群聊天消息后,首先要做的是解密,然后再反序列化:(以1对1聊天消息的实现为例,MainFormPartial.cs文件中的源码的第37行)

    byte[] decrypted = info;
if (GlobalResourceManager.Des3Encryption != null)
{
decrypted = GlobalResourceManager.Des3Encryption.Decrypt(info);
}
ChatBoxContent content = CompactPropertySerializer.Default.Deserialize<ChatBoxContent>(decrypted, );

之后,ChatBoxContent对象就可以在聊天窗中显示出来了。

4.处理离线消息

离线消息是当接收者不再时,将该聊天消息暂存在服务器上,等接收者上线时,再发送给他。所以,离线消息的解密处理与普通聊天消息的处理是一样的。(MainFormPartial.cs文件中的源码的第86行)

    if (informationType == InformationTypes.OfflineMessage)
{
byte[] bChatBoxContent = null;
OfflineMessage msg = CompactPropertySerializer.Default.Deserialize<OfflineMessage>(info, );
if (msg.InformationType == InformationTypes.Chat) //目前只处理离线的聊天消息
{
sourceUserID = msg.SourceUserID;
bChatBoxContent = msg.Information;
byte[] decrypted = bChatBoxContent;
if (GlobalResourceManager.Des3Encryption != null)
{
decrypted = GlobalResourceManager.Des3Encryption.Decrypt(bChatBoxContent);
}
ChatBoxContent content = CompactPropertySerializer.Default.Deserialize<ChatBoxContent>(decrypted, );
}
}

四.聊天记录要怎么处理了?   

根据上面的流程描述,我们可以知道,在服务端看到的聊天消息是经过加密的,而GG在服务端有将聊天记录存储到数据库中的功能,因此,数据库中聊天内容那一列存储的数据也是加密的。

  在GG即时通信系统中,服务端不需要查看聊天消息的真正内容,所以,服务端不需要使用到Des3Encryption类。

GG在客户端本地也有存储聊天记录(使用Sqlite),与服务器上数据库中存储的不一样的是,本地存储的是明文的。所以,在查看聊天记录时,要根据用户选择的是从本地查看还是从服务器查看来决定是否需要对数据进行解密:(对应ChatRecordForm窗体,源码177行)

    byte[] decrypted = record.Content;
if (this.skinRadioButton_Server.Checked)
{
if (GlobalResourceManager.Des3Encryption != null)
{
decrypted = GlobalResourceManager.Des3Encryption.Decrypt(decrypted);
}
}
ChatBoxContent content = CompactPropertySerializer.Default.Deserialize<ChatBoxContent>(decrypted, );

五.源码下载

GGTalk即时通信系统是可在广域网部署运行的C#开源即时通信系统,2013.8.7发布V1.0版本,至今最新是4.5版本,关于GG更详细的介绍,可以查看 可在广域网部署运行的QQ高仿版 -- GG2014总览

1.GG服务端和PC端源码  

源码下载:GG-V4.5.rar     网盘下载更快

  部署下载:GG V4.5 可直接部署版本    网盘下载更快

(压缩包中有 《部署说明.txt》 和 创建数据库的脚本 《GG2014.sql》)

2.GG安卓版源码

自从GG4.4版本开始,GG增加了安卓版本,其运行界面截图如下所示:

   

源码下载:GG-android.rar     网盘下载更快

若要测试,请先部署服务端,然后修改安卓源码中MainActivity中的服务器的IP和端口(如下图所示),并重新编译生成apk。

(若要和PC端联合测试,请关闭PC端那边的聊天消息加密功能:将PC客户端项目的GlobalResourceManager类的 des3Encryption 成员赋值为 null 即可!)

注:GG安卓版的源码质量不是很高,属于安卓初学者水平,很多地方有待改进,目前只是展示与PC打通的功能如何实现。若要将GG安卓版本的源码用于正式项目中,建议先对其进行重构。

即时通信系统中如何实现:聊天消息加密,让通信更安全? 【低调赠送:QQ高仿版GG 4.5 最新源码】的更多相关文章

  1. QQ揭秘:如何实现托盘闪动消息提醒?【低调赠送:QQ高仿版GG 4.1 最新源码】

    当QQ收到好友的消息时,托盘的图标会变成好友的头像,并闪动起来,点击托盘,就会弹出与好友的聊天框,随即,托盘恢复成QQ的图标,不再闪动.当然,如果还有其它的好友的消息没有提取,托盘的图标会变成另一个好 ...

  2. 如何实现:录制视频聊天的全过程? 【低调赠送:QQ高仿版GG 4.3 最新源码】

    前段时间做个项目,客户需要将视频对话的整个过程录制下来,这样,以后就可以随时观看.想来录制整个视频聊天的过程这样的功能应该是个比较常见的需求,比如,基于网络语音视频的1:1的英语口语辅导,如果能将辅导 ...

  3. 即时通信系统中如何实现:全局系统通知,并与Web后台集成?【低调赠送:QQ高仿版GGTalk 5.1 最新源码】

    像QQ这样的即时通信软件,时不时就会从桌面的右下角弹出一个小窗口,或是显示一个广告.或是一个新闻.或是一个公告等.在这里,我们将其统称为“全局系统通知”.很多使用GGTalk的朋友都建议我加上一个类似 ...

  4. 即时通信系统中实现聊天消息加密,让通信更安全【低调赠送:C#开源即时通讯系统(支持广域网)——GGTalk4.5 最新源码】

    在即时通讯系统(IM)中,加密重要的通信消息,是一个常见的需求.尤其在一些政府部门的即时通信软件中(如税务系统),对即时聊天消息进行加密是非常重要的一个功能,因为谈话中可能会涉及到机密的数据.我在最新 ...

  5. 即时通信系统中实现全局系统通知,并与Web后台集成【附C#开源即时通讯系统(支持广域网)——QQ高仿版IM最新源码】

    像QQ这样的即时通信软件,时不时就会从桌面的右下角弹出一个小窗口,或是显示一个广告.或是一个新闻.或是一个公告等.在这里,我们将其统称为“全局系统通知”.很多使用C#开源即时通讯系统——GGTalk的 ...

  6. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.7,优化视频聊天、控制更多相关细节

    在广域网中,由于网络的结构纷繁复杂.而且其实时状况又是千变万化的,所以,要使广域网中的视频聊天达到一个令人满意的效果,存在诸多挑战.这次发布的GG 3.7版本尝试在这一方向上做一些努力,据我自己测试, ...

  7. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.2,增加离线消息、离线文件功能(源码)

    (几句题外话:虽然就如何将GG发展为一个有商业价值的产品,我还没有很清晰明确的思路,但是从GG发布以来,通过GG认识了一些朋友,也接了一些小单子,赚了一点小钱.有了一点甜头,目前和2.3个好朋友一起做 ...

  8. 可在广域网部署运行的QQ高仿版 -- GG叽叽V3.6,增加语音消息、语音留言等功能

    自从微信出来后,语音消息和语音留言变得非常流行,按下一个键说话,比打字要方便多了.GG在V3.6版本增加了对语音消息和语音留言(或称为离线语音消息)的支持.这两个功能的实现已经很完整,只是比较遗憾的一 ...

  9. 即时通信系统Openfire分析之四:消息路由

    两个人的孤独 两个人的孤独,大抵是,你每发出去一句话,都要经由无数网络.由几百个计算机处理后,出在他的面前,而他就在你不远处. 连接管理之后 Openfire使用MINA网络框架,并设置Connect ...

随机推荐

  1. MacDev.Mach-O.Programming-Part-III:MachOView-v2.4.9200.dmg-crash

    MachOView-v2.4.9200.dmg Crash 在OS X(其版本号: 10.11.6 (15G31))下载MachOView-2.4.9200.dmg后,打开Fat Binary后,Ma ...

  2. Xcode7以后 使用空模板

    Xcode7以后的版本没有空模板可以选择 习惯使用空模版的 可以自己拷贝空模版文件夹 放到模版的位置 重启就可以使用了 1:首先 需要有一个空模版 没有空模板的可以在下面路径下下载一个 并解压 htt ...

  3. U盘启动盘 安装双系统 详细教程

    U盘启动盘 安装win7+linux双系统 最近在看鸟哥的linux 私房菜 ,看到多重系统那部分,自然的安装多重系统的激情由此而燃.在网上看了很多资料,感觉都不全.经过艰辛的摸索,终于被我发现了一个 ...

  4. linux 定时清理session

    php session 运营想让用户登陆网站就能永久保持登陆会话,感觉这是扯淡,因为视频播放1小时,所以我设置了两小时过期. 但是用户过多,导致session文件大量存储.产生上百万千万.服务器空间很 ...

  5. 总结30个CSS选择器

    或许大家平时总是在用的选择器都是:#id  .class  以及标签选择器.可是这些还远远不够,为了在开发中更加得心应手,本文总结了30个CSS3选择器,希望对大家有所帮助. 1 *:通用选择器 * ...

  6. Sublime Text 安装Emmet

    1.简单的安装方法 从菜单 View - Show Console 或者 ctrl + ~ 快捷键,调出 console.将以下 Python 代码粘贴进去并 enter 执行,不出意外即完成安装.以 ...

  7. 15.Xcode8 升级遇到的问题

    一:注释快捷键cmd+/不能用,解决方法: 1. Swift_3.0 没法快捷键(command+/)注释的原因:这个是因为苹果解决xcode ghost,把插件屏蔽了. 2. 解决办法: (1) 终 ...

  8. Python小练习二

    # 以正确的宽度在居中的"盒子"内打印一个句子 # 注意,整数除法运算符(//)只能用在Python 2.2及后续版本,在之前的版本中,只使用普通除法(/) sentence = ...

  9. easyUI datagraid的列排序

    在给datagraid做多列排序时请注意: 首先,做的是后台排序,那么需要设置: remoteSort:'true', 然后,不要添加 multiSort:'true',这个是多列一起排序无法实现.. ...

  10. Popup - 弹出层

    //图片类快捷弹出层 <a href="" target="_blank"> <div class="panlifang1" ...