注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

Spark聊天信息加密插件第三部分E2EProtocal类,自己实现的简单加密协议  

2010-07-01 19:59:38|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

package papaya.guava.mango;

import java.io.IOException;

import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.spark.SparkManager;

//End-to-End Object Encryption in XMPP
//XMPP 的本身是有个E2E的标准加密协议的,
//但好像spark里面是没有实现的。
//这里只是一个简单加解密,并不是标准实现来的。
public class E2EProtocal {

private static final String ENCRYPTED_MESSAGE_HEAD = "O0o."; //数据 = RSA加密的数据,用于消息比较短时,
private static final String ENCRYPTED_MESSAGE_HEAD_2 = "O0oo"; //数据 = RSA加密的AES密码+ AES加密的数据,用于消息比较长时
private static final String KEY_REQUEST_MESSAGE_HEAD = "   \n \n   \n";
private static final String KEY_REPLY_MESSAGE_HEAD = ".O0o.";

private static String user_trace = "";
private static boolean IsEncryptedMessage(String message) {
   return message.startsWith(ENCRYPTED_MESSAGE_HEAD, 0);
}
private static boolean IsEncryptedMessage2(String message) {
   return message.startsWith(ENCRYPTED_MESSAGE_HEAD_2, 0);
}
private static boolean IsKeyRequestMessage(String message) {
   return message.startsWith(KEY_REQUEST_MESSAGE_HEAD, 0);
}
private static boolean IsKeyReplyMessage(String message) {
   return message.startsWith(KEY_REPLY_MESSAGE_HEAD, 0);
}
private static String AddEncryptedHeader(String message) {
   return ENCRYPTED_MESSAGE_HEAD + message;
}
private static String AddEncryptedHeader2(String message) {
   return ENCRYPTED_MESSAGE_HEAD_2 + message;
}

private static String AddKeyRequestHeader(String message) {
   return KEY_REQUEST_MESSAGE_HEAD + message;
}
private static String RemoveEncryptedHeader(String message) {
   return message.substring(ENCRYPTED_MESSAGE_HEAD.length());
}
private static String RemoveEncryptedHeader2(String message) {
   return message.substring(ENCRYPTED_MESSAGE_HEAD_2.length());
}
private static String RemoveKeyRequestHeader(String message) {
   return message.substring(KEY_REQUEST_MESSAGE_HEAD.length());
}
private static String RemoveKeyReplyHeader(String message) {
   return message.substring(KEY_REPLY_MESSAGE_HEAD.length());
}
private static String AddHeader(String message, String header) {
   return header + message;
}
private static String RemoveHeader(String message, String header) {
   return message.substring(header.length());
}
/***********************************************
* 用户名类似这种
* ddd@ddd.com/Spark
* 但 有时自己并不知道对方使用Spark,可能第一条消息就是用ddd@ddd.com这种
*调用一下这个是希望我们的的唯一用户标志
**********************************************/
private static String RemoveClientName(String user){
  
   String [] temp = user.split("/");
   String userName = temp[0];
   return userName;
}
//是不是第一条给user的消息
private static boolean IsFirstMessage(String user){

   String userExist = ":"+ user +":";
   if (user_trace.contains(userExist))
   {
    return false;
   }else {
    user_trace = user_trace + userExist ;
    return true;
   }
}
//清零用户发送消息数次
private static void NotFirstMessage(String user){

   String userExist = ":"+ user +":";
   if (user_trace.contains(userExist))
   {
    user_trace = user_trace.replace(userExist,"");
   }
}
private static boolean SendKeyToUser (String to, String from){
   Message message = new Message();
   message.setFrom(from);
   message.setTo(to);
   Encryptor enc = Encryptor.getInstance();
   if ( enc == null ){
    return false;
   }
   String body = KEY_REPLY_MESSAGE_HEAD + enc.GetMyPublicKey();
   message.setBody(body);
  
   return SendMessage(message);
  
  
}
/* 必须事先调用,下面3个办法设置Message的3个基本选项。
* message.setFrom(from);
* message.setTo(to);
* message.setBody(body);
* */
private static boolean SendMessage (Message message){
   message.setType(Message.Type.chat);
   String threadID = StringUtils.randomString(6);
   message.setThread(threadID);

   try {
    SparkManager.getConnection().sendPacket(message);
   }catch (Exception ex) {
             //Log.error("Error sending message", ex);
    return false;
   }
   return true;
}
/*
* 数据包的接收点,将在这里解密
*/
public static void MessageIn(Message message) {

   // ChatRoomImpl chatRoom = (ChatRoomImpl)room.getChatRoom();
   String toUser = message.getTo();
   String fromUser = message.getFrom();
   String currentBody = message.getBody();

   if (fromUser == null || fromUser.equals("")) {
    return;
   }

   Encryptor encryptor = Encryptor.getInstance();
   if (encryptor == null) {
    return;
   }
  
   if(IsEncryptedMessage(currentBody) ) {
    currentBody = RemoveEncryptedHeader(currentBody);
    try {
     //如果消息过长,这个RSA解密时间会比较长(超过2000长度估计几分钟都不行? 考虑用AES 加密方式把。)
     //但新的spark客户端是不允许这么长的长度的,问题不大。
     //防止恶意欺骗的假消息攻击造成客户端假死
     if (currentBody.length() > 1000){
      return;
     }
     currentBody = encryptor.DecryptMessage(currentBody);
     message.setBody(currentBody);
    } catch (IOException e) {
     // e.printStackTrace();
     if (e.getMessage() == "BadPadding"){
      //解密错误,重新给对方发送一下自己的public key
      boolean result = SendKeyToUser(fromUser,toUser);
      String text = result ? "\n解密消息错误,重新发送自己的public key给对方成功" : "\n解密消息错误,重新发送自己的public key给对方不成功";
      message.setBody(currentBody + text );
      return;
     }
    
     message.setBody(currentBody + "\n解密消息失败,未知错误");
     return;
    }
   }else if(IsEncryptedMessage2(currentBody) ) {
    currentBody = RemoveEncryptedHeader2(currentBody);
    try {
     int index = currentBody.indexOf("|");
     if (index < 0 ) {
      return;
     }
     String part1 = currentBody.substring(0, index);
     String part2 = currentBody.substring(index + 1);
     String pwd = encryptor.DecryptMessage(part1);
     currentBody = encryptor.DecryptMessageAES(pwd,part2);
     message.setBody(currentBody);
    
    } catch (IOException e) {
     // e.printStackTrace();
     if (e.getMessage() == "BadPadding" ||
        e.getMessage() == "InvalidKey" ){
      //解密错误,重新给对方发送一下自己的public key
      boolean result = SendKeyToUser(fromUser,toUser);
      String text = result ? "\n解密消息错误,重新发送自己的public key给对方成功" : "\n解密消息错误,重新发送自己的public key给对方不成功";
      message.setBody(currentBody + text );
      return;
     }
    
     message.setBody(currentBody + "\n解密消息失败,未知错误");
     return;
    }
   
   }
   else if (IsKeyRequestMessage(currentBody)){
     currentBody = RemoveKeyRequestHeader(currentBody);
     boolean result = SendKeyToUser(fromUser,toUser);
     String text = result ? ",key发送成功" : ",key发送不成功";
     message.setBody("对方请求public key" + text + "\n------\n" + currentBody);
    
      //重新重置计数器,以便等会给这个用户发送key请求
     //用于之前没有装了插件,但我们先给对方发了消息,然后对方装了插件的情况。
     String newUser =RemoveClientName(toUser);
     NotFirstMessage(newUser);
        
    
   } else if (IsKeyReplyMessage(currentBody)){
    String key = RemoveKeyReplyHeader(currentBody);
    fromUser = RemoveClientName(fromUser);
    boolean result = encryptor.AddKey(fromUser, key);
    if (result ){
     message.setBody("对方给你发来新的public key,以后发送给对方的消息都加密传送!");
    }else {
     message.setBody("对方给你发来新的public key,但添加失败!\n" + currentBody);
    }
   
      //重新重置计数器,以便等会给这个用户发送key请求
     //用于之前没有装了插件,但我们先给对方发了消息,然后对方装了插件的情况。
     String newUser =RemoveClientName(toUser);
     NotFirstMessage(newUser);
   } else {
    // 来自没使用本插件的客户端的,未经加密的消息
    return;
   }
  
}

/*
* 数据包的发送点,将在这里加密
*/
public static void MessageOut(Message message) {
   // ChatRoomImpl chatRoom = (ChatRoomImpl)room.getChatRoom();
   String toUser = message.getTo();
   String fromUser = message.getFrom();
   String currentBody = message.getBody();

   if (fromUser == null || fromUser.equals("")) {
    return;
   }

   if (toUser == null || toUser.equals("")) {
    return;
   }

   Encryptor encryptor = Encryptor.getInstance();
   if (encryptor == null) {
    return;
   }
  
   try {
    toUser =RemoveClientName(toUser);
    //短消息直接用RSA解密
    if (currentBody.length() < 247 * 2)
    {
     currentBody = encryptor.EncryptMessage(toUser, currentBody);
     currentBody = AddEncryptedHeader(currentBody);
     message.setBody(currentBody);
    }else { //长消息用 RSA + AES解密
     //获取16个随机字符串做为AES密码
     String pwd = StringUtils.randomString(16);
     String part1 = encryptor.EncryptMessage(toUser, pwd);
     String part2 = encryptor.EncryptMessageAES(pwd,currentBody);
     currentBody = part1 + "|" + part2;
     currentBody = AddEncryptedHeader2(currentBody);
     message.setBody(currentBody);
    }
   
   } catch (IOException e) {
    //e.printStackTrace();
    if (e.getMessage() == "NoKeyForThisUser")
    {
     if(IsFirstMessage(toUser)){
      currentBody = AddKeyRequestHeader(currentBody);
      message.setBody(currentBody);
     }
    }
    return;
   }


}
}

  评论这张
 
阅读(657)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017