JXMsgUtil.m 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. //
  2. // JXMsgUtil.m
  3. // shiku_im
  4. //
  5. // Created by p on 2019/7/31.
  6. // Copyright © 2019 Reese. All rights reserved.
  7. //
  8. #import "JXMsgUtil.h"
  9. #import "ECkeyUtils.h"
  10. #import "MD5Util.h"
  11. #import "AESUtil.h"
  12. #import "JXUserPublicKeyObj.h"
  13. @interface JXMsgUtil()
  14. @end
  15. @implementation JXMsgUtil
  16. +(instancetype)sharedManager {
  17. static dispatch_once_t onceToken;
  18. static JXMsgUtil *instance;
  19. dispatch_once(&onceToken, ^{
  20. instance = [[JXMsgUtil alloc] init];
  21. });
  22. return instance;
  23. }
  24. - (instancetype)init {
  25. if ([super init]) {
  26. self.verifyFailedDic = [NSMutableDictionary dictionary];
  27. self.getDHListIds = [NSMutableArray array];
  28. [g_notify addObserver:self selector:@selector(newMsgCome:) name:kXMPPNewMsgNotifaction object:nil];//收到了一条新消息
  29. }
  30. return self;
  31. }
  32. #pragma mark 接受新消息广播
  33. -(void)newMsgCome:(NSNotification *)notifacation {
  34. JXMessageObject *msg = notifacation.object;
  35. if ([msg.type intValue] == kWCMessageTypeUpdateFriendPublicKey) {
  36. NSArray *keys = [msg.content componentsSeparatedByString:@","];
  37. if (keys.count > 0) {
  38. // 更新好友的DH和RSA公钥
  39. JXUserObject *user = [[JXUserObject sharedInstance] getUserById:msg.fromUserId];
  40. user.publicKeyDH = keys.firstObject;
  41. user.publicKeyRSARoom = keys.lastObject;
  42. [user updateDHPublicKeyAndRSAPublicKey];
  43. // 插入到公钥表
  44. JXUserPublicKeyObj *keyObj = [[JXUserPublicKeyObj alloc] init];
  45. keyObj.userId = msg.fromUserId;
  46. keyObj.publicKey = keys.firstObject;
  47. keyObj.keyCreateTime = msg.timeSend;
  48. [keyObj insert];
  49. }
  50. }
  51. }
  52. - (void)setDhPublicKey:(NSString *)dhPublicKey {
  53. _dhPublicKey = dhPublicKey;
  54. _dhPublicPem = [ECkeyUtils getPemKeyFromKey:dhPublicKey isPrivate:NO];
  55. }
  56. - (void)setDhPrivateKey:(NSString *)dhPrivateKey{
  57. _dhPrivateKey = dhPrivateKey;
  58. _dhPrivatePem = [ECkeyUtils getPemKeyFromKey:dhPrivateKey isPrivate:YES];
  59. }
  60. - (void)setDhPublicPem:(NSString *)dhPublicPem {
  61. _dhPublicPem = dhPublicPem;
  62. _dhPublicKey = [ECkeyUtils getKeyFromPemKey:dhPublicPem isPrivate:NO];
  63. }
  64. - (void)setDhPrivatePem:(NSString *)dhPrivatePem {
  65. _dhPrivatePem = dhPrivatePem;
  66. _dhPrivateKey = [ECkeyUtils getKeyFromPemKey:dhPrivatePem isPrivate:YES];
  67. }
  68. // 生成DH秘钥对
  69. - (void) generatekeyPairsDH {
  70. ECkeyUtils *keyUtils = [[ECkeyUtils alloc] init];
  71. [keyUtils generatekeyPairs];
  72. self.dhPrivatePem = keyUtils.eckeyPairs.privatePem;
  73. self.dhPrivateKey = keyUtils.eckeyPairs.privateKey;
  74. self.dhPublicPem = keyUtils.eckeyPairs.publicPem;
  75. self.dhPublicKey = keyUtils.eckeyPairs.publicKey;
  76. }
  77. // 生成群组使用的RSA秘钥对
  78. - (void) generatekeyPairsRSA {
  79. SecKeyRef privateKey = [g_securityUtil getRSAPrivateKey];
  80. SecKeyRef publicKey = [g_securityUtil getRSAPublicKeyWithPrivateKey:privateKey];
  81. NSData *privateData = [g_securityUtil getKeyBitsFromKey:privateKey];
  82. NSData *publicData = [g_securityUtil getKeyBitsFromKey:publicKey];
  83. NSString *privateStr = [privateData base64EncodedStringWithOptions:0];
  84. self.rsaPrivateKey = privateStr;
  85. self.rsaPublicKey = [g_securityUtil getKeyForJavaServer:publicData];
  86. }
  87. // 获取对称秘钥S
  88. - (NSData *)getMsgContentKeyWithMsgId:(NSString *)msgId key:(NSString *)key; {
  89. NSMutableString *appendStr = [NSMutableString string];
  90. [appendStr appendString:APIKEY];
  91. [appendStr appendString:msgId];
  92. [appendStr appendString:key];
  93. NSData *data = [MD5Util getMD5DataWithString:appendStr];
  94. return data;
  95. }
  96. // 获取单聊存储本地数据库aes加密后的content
  97. - (NSString *)encryptInsertChatMsgContent:(NSString *)content msgId:(NSString *)msgId {
  98. NSMutableString *appendStr = [NSMutableString string];
  99. [appendStr appendString:APIKEY];
  100. [appendStr appendString:msgId];
  101. NSData *keyData= [MD5Util getMD5DataWithString:appendStr];
  102. NSData *aesData = [AESUtil encryptAESData:[content dataUsingEncoding:NSUTF8StringEncoding] key:keyData];
  103. NSString *aesStr = [aesData base64EncodedStringWithOptions:0];
  104. return aesStr;
  105. }
  106. // 获取单聊存储本地数据库aes解密后的content
  107. - (NSString *)decryptInsertChatMsgContent:(NSString *)content msgId:(NSString *)msgId {
  108. if (!content || content.length <= 0) {
  109. return @"";
  110. }
  111. NSMutableString *appendStr = [NSMutableString string];
  112. [appendStr appendString:APIKEY];
  113. [appendStr appendString:msgId];
  114. NSData *keyData= [MD5Util getMD5DataWithString:appendStr];
  115. NSData *contentData = [[NSData alloc] initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
  116. NSData *aesData = [AESUtil decryptAESData:contentData key:keyData];
  117. NSString *aesStr = [[NSString alloc] initWithData:aesData encoding:NSUTF8StringEncoding];
  118. return aesStr;
  119. }
  120. // 获取单聊消息验参
  121. - (NSString *)getChatMsgMacWithContent:(NSString *)content fromUserId:(NSString *)fromUserId toUserId:(NSString *)toUserId isEncrypt:(NSInteger)isEncrypt msgId:(NSString *)msgId publicKey:(NSString *)publicKey {
  122. NSString *pubPem = [ECkeyUtils getPemKeyFromKey:publicKey isPrivate:NO];
  123. NSString *shareKey = [ECkeyUtils getShareKeyFromPeerPubPem:pubPem privatePem:g_msgUtil.dhPrivatePem length:32];
  124. if (!shareKey || shareKey.length <= 0) {
  125. return nil;
  126. }
  127. NSData *keyData = [self getMsgContentKeyWithMsgId:msgId key:shareKey];
  128. NSString *msgKey = [keyData base64EncodedStringWithOptions:0];
  129. NSMutableString *appendStr = [NSMutableString string];
  130. [appendStr appendString:fromUserId];
  131. [appendStr appendString:toUserId];
  132. [appendStr appendString:[NSString stringWithFormat:@"%ld",(long)isEncrypt]];
  133. [appendStr appendString:msgId];
  134. [appendStr appendString:msgKey];
  135. NSData *macData = [g_securityUtil getHMACMD5:[content dataUsingEncoding:NSUTF8StringEncoding] key:[appendStr dataUsingEncoding:NSUTF8StringEncoding]];
  136. NSString *mac = [macData base64EncodedStringWithOptions:0];
  137. return mac;
  138. }
  139. // 获取群聊存储本地数据库aes加密后的对称秘钥
  140. - (NSString *)encryptRoomMsgKey:(NSString *)roomJid randomKey:(NSString *)randomKey {
  141. NSMutableString *appendStr = [NSMutableString string];
  142. [appendStr appendString:APIKEY];
  143. [appendStr appendString:roomJid];
  144. NSData *keyData= [MD5Util getMD5DataWithString:appendStr];
  145. NSData *aesData = [AESUtil encryptAESData:[randomKey dataUsingEncoding:NSUTF8StringEncoding] key:keyData];
  146. NSString *aesStr = [aesData base64EncodedStringWithOptions:0];
  147. return aesStr;
  148. }
  149. // 获取群聊存储本地数据库aes解密后的对称秘钥
  150. - (NSString *)decryptRoomMsgKey:(NSString *)roomJid randomKey:(NSString *)randomKey {
  151. NSMutableString *appendStr = [NSMutableString string];
  152. [appendStr appendString:APIKEY];
  153. [appendStr appendString:roomJid];
  154. NSData *keyData= [MD5Util getMD5DataWithString:appendStr];
  155. NSData *randomData = [[NSData alloc] initWithBase64EncodedString:randomKey options:NSDataBase64DecodingIgnoreUnknownCharacters];
  156. NSData *data = [AESUtil decryptAESData:randomData key:keyData];
  157. NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  158. return str;
  159. }
  160. // 获取群聊消息验参
  161. - (NSString *)getRoomMsgMacWithContent:(NSString *)content fromUserId:(NSString *)fromUserId isEncrypt:(NSInteger)isEncrypt msgId:(NSString *)msgId randomKey:(NSString *)randomKey {
  162. NSMutableString *appendStr = [NSMutableString string];
  163. [appendStr appendString:fromUserId];
  164. [appendStr appendString:[NSString stringWithFormat:@"%ld",(long)isEncrypt]];
  165. [appendStr appendString:msgId];
  166. [appendStr appendString:randomKey];
  167. NSData *macData = [g_securityUtil getHMACMD5:[content dataUsingEncoding:NSUTF8StringEncoding] key:[appendStr dataUsingEncoding:NSUTF8StringEncoding]];
  168. NSString *mac = [macData base64EncodedStringWithOptions:0];
  169. return mac;
  170. }
  171. // 单聊发消息加密
  172. - (NSString *)encryptContentWithPublicKey:(NSString *)publicKey content:(NSString *)content msgId:(NSString *)msgId{
  173. NSString *pubPem = [ECkeyUtils getPemKeyFromKey:publicKey isPrivate:NO];
  174. NSString *shareKey = [ECkeyUtils getShareKeyFromPeerPubPem:pubPem privatePem:g_msgUtil.dhPrivatePem length:32];
  175. if (!shareKey || shareKey.length <= 0) {
  176. return nil;
  177. }
  178. NSData *keyData = [self getMsgContentKeyWithMsgId:msgId key:shareKey];
  179. NSData *encryptData = [AESUtil encryptAESData:[content dataUsingEncoding:NSUTF8StringEncoding] key:keyData];
  180. NSString *encryptStr = [encryptData base64EncodedStringWithOptions:0];
  181. return encryptStr;
  182. }
  183. // 单聊发消息解密
  184. - (NSString *)decryptContentWithPublicKey:(NSString *)publicKey content:(NSString *)content msgId:(NSString *)msgId {
  185. NSString *pubPem = [ECkeyUtils getPemKeyFromKey:publicKey isPrivate:NO];
  186. NSString *shareKey = [ECkeyUtils getShareKeyFromPeerPubPem:pubPem privatePem:g_msgUtil.dhPrivatePem length:32];
  187. NSData *keyData = [self getMsgContentKeyWithMsgId:msgId key:shareKey];
  188. NSData *contentData = [[NSData alloc] initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
  189. NSData *decryptData = [AESUtil decryptAESData:contentData key:keyData];
  190. NSString *decryptStr = [[NSString alloc]initWithData:decryptData encoding:NSUTF8StringEncoding];
  191. return decryptStr;
  192. }
  193. // 群聊消息加密
  194. - (NSString *)encryptRoomContentWithUser:(JXUserObject *)user content:(NSString *)content {
  195. NSString *chatKeyGroup = [g_msgUtil decryptRoomMsgKey:user.roomId randomKey:user.chatKeyGroup];
  196. NSData *encryptData = [AESUtil encryptAESData:[content dataUsingEncoding:NSUTF8StringEncoding] key:[chatKeyGroup dataUsingEncoding:NSUTF8StringEncoding]];
  197. NSString *encryptStr = [encryptData base64EncodedStringWithOptions:0];
  198. return encryptStr;
  199. }
  200. // 群聊消息解密
  201. - (NSString *)decryptRoomContentWithUser:(JXUserObject *)user content:(NSString *)content {
  202. NSString *chatKeyGroup = [g_msgUtil decryptRoomMsgKey:user.roomId randomKey:user.chatKeyGroup];
  203. NSData *contentData = [[NSData alloc] initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
  204. NSData *decryptData = [AESUtil decryptAESData:contentData key:[chatKeyGroup dataUsingEncoding:NSUTF8StringEncoding]];
  205. NSString *decryptStr = [[NSString alloc]initWithData:decryptData encoding:NSUTF8StringEncoding];
  206. return decryptStr;
  207. }
  208. // 获取好友公钥list
  209. - (void)getDHPublicKeyWithUserId:(NSString *)userId {
  210. [g_server authkeysGetDHMsgKeyListWithUserId:userId toView:self];
  211. }
  212. // 获取群组的消息秘钥
  213. - (void)getChatKeyGroupWithRoomId:(NSString *)roomId {
  214. [g_server getRoom:roomId toView:self];
  215. }
  216. - (void)didServerResultSucces:(JXConnection *)task dict:(NSDictionary *)dict array:(NSArray *)array1{
  217. if ([task.action isEqualToString:act_AuthkeysGetDHMsgKeyList]) {
  218. NSString *userId = [NSString stringWithFormat:@"%@",[dict objectForKey:@"userId"]];
  219. NSArray *publicKeyList = [dict objectForKey:@"publicKeyList"];
  220. for (NSInteger i = 0; i < publicKeyList.count; i ++) {
  221. NSDictionary *dic = publicKeyList[i];
  222. [[JXUserPublicKeyObj sharedManager] deletePublicKeyWIthUserId:userId];
  223. JXUserPublicKeyObj *obj =[[JXUserPublicKeyObj alloc] init];
  224. obj.userId = userId;
  225. obj.publicKey = [dic objectForKey:@"key"];
  226. obj.keyCreateTime = [NSDate dateWithTimeIntervalSince1970:[[dic objectForKey:@"time"] doubleValue]];
  227. [obj insert];
  228. }
  229. JXUserObject *user = [[JXUserObject sharedInstance] getUserById:userId];
  230. if (!user.publicKeyDH || user.publicKeyDH.length > 0) {
  231. [g_server getUser:userId toView:self];
  232. }
  233. // 获取好友公钥表
  234. NSMutableArray *keys = [[JXUserPublicKeyObj sharedManager] fetchPublicKeyWithUserId:userId];
  235. NSArray *msgArr = [g_msgUtil.verifyFailedDic objectForKey:userId];
  236. for (NSInteger i = 0; i < msgArr.count; i ++) {
  237. JXMessageObject *msg = msgArr[i];
  238. BOOL flag = NO;
  239. // 公钥表里公钥依次解密
  240. for (NSInteger i = 0; i < keys.count; i ++) {
  241. JXUserPublicKeyObj *obj = keys[i];
  242. if (obj.publicKey && obj.publicKey.length > 0) {
  243. NSString *signature = [g_msgUtil getChatMsgMacWithContent:msg.content fromUserId:msg.fromUserId toUserId:msg.toUserId isEncrypt:[msg.isEncrypt integerValue] msgId:msg.messageId publicKey:obj.publicKey];
  244. if ([signature isEqualToString:msg.signature]) {
  245. flag = YES;
  246. msg.content = [g_msgUtil decryptContentWithPublicKey:obj.publicKey content:msg.content msgId:msg.messageId];
  247. [msg update];
  248. break;
  249. }
  250. }
  251. }
  252. // if (flag) {
  253. // [msg update];
  254. // }else {
  255. // [msg delete];
  256. // }
  257. }
  258. [g_msgUtil.verifyFailedDic removeObjectForKey:userId];
  259. NSInteger index = 0;
  260. for (NSInteger i = 0; i < g_msgUtil.getDHListIds.count; i ++) {
  261. NSString *str = g_msgUtil.getDHListIds[i];
  262. if ([str isEqualToString:userId]) {
  263. index = i;
  264. break;
  265. }
  266. }
  267. [g_msgUtil.getDHListIds removeObjectAtIndex:index];
  268. }
  269. if ([task.action isEqualToString:act_UserGet]) {
  270. JXUserObject* user = [[JXUserObject alloc]init];
  271. user.userId = [dict objectForKey:@"userId"];
  272. user.publicKeyDH = [[dict objectForKey:@"friends"] objectForKey:@"dhMsgPublicKey"];
  273. user.publicKeyRSARoom = [[dict objectForKey:@"friends"] objectForKey:@"rsaMsgPublicKey"];
  274. [user updateDHPublicKeyAndRSAPublicKey];
  275. }
  276. if ([task.action isEqualToString:act_roomGet]) {
  277. JXUserObject* user = [[JXUserObject alloc]init];
  278. [user getDataFromDict:dict];
  279. [user updateChatKeyGroup];
  280. NSArray *msgArr = [g_msgUtil.verifyFailedDic objectForKey:user.userId];
  281. for (NSInteger i = 0; i < msgArr.count; i ++) {
  282. JXMessageObject *msg = msgArr[i];
  283. NSString *chatKeyGroup = [g_msgUtil decryptRoomMsgKey:user.roomId randomKey:user.chatKeyGroup];
  284. NSString *encryptStr = [g_msgUtil encryptRoomContentWithUser:user content:msg.content];
  285. NSString *signature = [g_msgUtil getRoomMsgMacWithContent:encryptStr fromUserId:msg.fromUserId isEncrypt:[msg.isEncrypt integerValue] msgId:msg.messageId randomKey:chatKeyGroup];
  286. if ([signature isEqualToString:msg.signature]) {
  287. msg.content = [g_msgUtil decryptRoomContentWithUser:user content:msg.content];
  288. [msg update];
  289. }
  290. }
  291. [g_msgUtil.verifyFailedDic removeObjectForKey:user.userId];
  292. NSInteger index = 0;
  293. for (NSInteger i = 0; i < g_msgUtil.getDHListIds.count; i ++) {
  294. NSString *str = g_msgUtil.getDHListIds[i];
  295. if ([str isEqualToString:user.userId]) {
  296. index = i;
  297. break;
  298. }
  299. }
  300. [g_msgUtil.getDHListIds removeObjectAtIndex:index];
  301. }
  302. }
  303. -(int) didServerResultFailed:(JXConnection*)aDownload dict:(NSDictionary*)dict{
  304. return hide_error;
  305. }
  306. -(int) didServerConnectError:(JXConnection*)aDownload error:(NSError *)error{
  307. return hide_error;
  308. }
  309. -(void) didServerConnectStart:(JXConnection*)aDownload{
  310. }
  311. @end