CCCrypto.m 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. //
  2. // CCCrypto.m
  3. // Crypto Cloud Technology Nextcloud
  4. //
  5. // Created by Marino Faggiana on 10/08/16.
  6. // Copyright (c) 2017 TWS. All rights reserved.
  7. //
  8. // Author Marino Faggiana <m.faggiana@twsweb.it>
  9. //
  10. // This program is free software: you can redistribute it and/or modify
  11. // it under the terms of the GNU General Public License as published by
  12. // the Free Software Foundation, either version 3 of the License, or
  13. // (at your option) any later version.
  14. //
  15. // This program is distributed in the hope that it will be useful,
  16. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. // GNU General Public License for more details.
  19. //
  20. // You should have received a copy of the GNU General Public License
  21. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. //
  23. #import "CCCrypto.h"
  24. #import "NCBridgeSwift.h"
  25. @implementation CCCrypto
  26. //Singleton
  27. + (id)sharedManager {
  28. static CCCrypto *CCCrypto = nil;
  29. static dispatch_once_t onceToken;
  30. dispatch_once(&onceToken, ^{
  31. CCCrypto = [[self alloc] init];
  32. });
  33. return CCCrypto;
  34. }
  35. #pragma --------------------------------------------------------------------------------------------
  36. #pragma mark ===== Encryption function =====
  37. #pragma --------------------------------------------------------------------------------------------
  38. // return password
  39. - (NSString *)getKeyPasscode:(NSString *)uuid
  40. {
  41. NSString *key;
  42. NSString *passcode = [CCUtility getKeyChainPasscodeForUUID:uuid];
  43. if (passcode) key = [AESCrypt encrypt:uuid password:passcode];
  44. return key;
  45. }
  46. - (void)autoInsertPasscodeUUID:(NSString *)uuid text:(NSString *)text
  47. {
  48. NSString *key;
  49. NSString *passcode;
  50. // if return the passcode the UUID it has already entered
  51. if ([[CCUtility getKeyChainPasscodeForUUID:uuid] length] > 0)
  52. return;
  53. // verify if the password of the UUID insert is good (OPTIMIZATION)
  54. passcode = [CCUtility getKeyChainPasscodeForUUID:[CCUtility getUUID]];
  55. key = [AESCrypt encrypt:uuid password:passcode];
  56. // if the decryption it's ok insert UUID with Passcode in KeyChain
  57. if([AESCrypt decrypt:text password:key])
  58. [CCUtility setKeyChainPasscodeForUUID:uuid conPasscode:passcode];
  59. }
  60. - (BOOL)verifyPasscode:(NSString *)passcode uuid:(NSString*)uuid text:(NSString *)text
  61. {
  62. NSString *key;
  63. key = [AESCrypt encrypt:uuid password:passcode];
  64. NSString *textDecrypted = [AESCrypt decrypt:text password:key];
  65. if([textDecrypted length]) return true;
  66. else return false;
  67. }
  68. - (BOOL)createFilePlist:(NSString *)fileNamePath title:(NSString *)title len:(NSUInteger)len directory:(BOOL)directory uuid:(NSString *)uuid nameCurrentDevice:(NSString *)nameCurrentDevice icon:(NSString *)icon
  69. {
  70. NSMutableDictionary *data;
  71. NSString *hint = [CCUtility getHint];
  72. // se non ha già l'estensione plist aggiungila
  73. if([fileNamePath rangeOfString:@".plist"].location == NSNotFound) fileNamePath = [fileNamePath stringByAppendingString:@".plist"];
  74. if ([[NSFileManager defaultManager] fileExistsAtPath:fileNamePath])
  75. data = [[NSMutableDictionary alloc] initWithContentsOfFile:fileNamePath];
  76. else
  77. data = [[NSMutableDictionary alloc] init];
  78. [data setObject: [NSNumber numberWithBool:directory] forKey:@"dir"];
  79. if ([hint length] > 0) [data setObject:[AESCrypt encrypt:hint password:k_UUID_SIM] forKey:@"hint"];
  80. if ([icon length] > 0) [data setObject:icon forKey:@"icon"];
  81. [data setObject: [NSString stringWithFormat:@"%li", (unsigned long)len] forKey:@"len"];
  82. [data setObject: nameCurrentDevice forKey:@"namecurrentdevice"];
  83. [data setObject: k_versionProtocolPlist forKey:@"protocol"];
  84. [data setObject: title forKey:@"title"];
  85. [data setObject: k_metadataType_file forKey:@"type"];
  86. [data setObject: uuid forKey:@"uuid"];
  87. [data setObject: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] forKey:@"version"];
  88. return [data writeToFile:fileNamePath atomically:YES];
  89. }
  90. - (void)addPlistImage:(NSString *)fileNamePath fileNamePathImage:(NSString *)fileNamePathImage
  91. {
  92. NSMutableDictionary *plist = [[NSMutableDictionary alloc] initWithContentsOfFile:fileNamePath];
  93. if (plist) {
  94. UIImage *image = [UIImage imageWithContentsOfFile:fileNamePathImage];
  95. if (image) {
  96. NSData *dataImage = UIImagePNGRepresentation(image);
  97. NSError *error;
  98. NSString *passcode = [self getKeyPasscode:[CCUtility getUUID]];
  99. if (passcode) dataImage = [RNEncryptor encryptData:dataImage withSettings:kRNCryptorAES256Settings password:passcode error:&error];
  100. else dataImage = nil;
  101. if (dataImage && error == nil) {
  102. [plist setObject:dataImage forKey:@"image"];
  103. [plist writeToFile:fileNamePath atomically:YES];
  104. }
  105. }
  106. }
  107. }
  108. - (BOOL)updateTitleFilePlist:(NSString *)fileName title:(NSString *)title directoryUser:(NSString *)directoryUser
  109. {
  110. // if not plist extension add it
  111. if([fileName rangeOfString:@".plist"].location == NSNotFound) fileName = [fileName stringByAppendingString:@".plist"];
  112. // open file plist
  113. NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", directoryUser, fileName]];
  114. if (data) {
  115. [data setObject:title forKey:@"title"];
  116. [data writeToFile:[NSTemporaryDirectory() stringByAppendingString:fileName] atomically:YES];
  117. return YES;
  118. }
  119. return NO;
  120. }
  121. - (NSString *)createFileDirectoryPlist:(tableMetadata *)metadata
  122. {
  123. NSMutableDictionary *data;
  124. NSString *fileName = [self createFilenameEncryptor:metadata.fileNamePrint uuid:metadata.uuid];
  125. NSString *title = [AESCrypt encrypt:metadata.fileNamePrint password:[self getKeyPasscode:metadata.uuid]];
  126. NSString *fileNamePath = [NSString stringWithFormat:@"%@%@.plist", NSTemporaryDirectory(), fileName];
  127. NSString *hint = [CCUtility getHint];
  128. if ([[NSFileManager defaultManager] fileExistsAtPath:fileNamePath])
  129. data = [[NSMutableDictionary alloc] initWithContentsOfFile:fileNamePath];
  130. else
  131. data = [[NSMutableDictionary alloc] init];
  132. [data setObject: [NSNumber numberWithBool:true] forKey:@"dir"];
  133. if ([hint length] > 0) [data setObject: [AESCrypt encrypt:hint password:k_UUID_SIM] forKey:@"hint"];
  134. [data setObject: @"0" forKey:@"len"];
  135. [data setObject: metadata.nameCurrentDevice forKey:@"namecurrentdevice"];
  136. [data setObject: k_versionProtocolPlist forKey:@"protocol"];
  137. [data setObject: title forKey:@"title"];
  138. [data setObject: k_metadataType_file forKey:@"type"];
  139. [data setObject: metadata.uuid forKey:@"uuid"];
  140. [data setObject: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] forKey:@"version"];
  141. if ([data writeToFile:fileNamePath atomically:YES]) return fileName;
  142. else return nil;
  143. }
  144. - (BOOL)createTemplatesPlist:(NSString *)nameFile title:(NSString *)title uuid:(NSString *)uuid icon:(NSString *)icon model:(NSString *)model dictionary:(NSMutableDictionary*)dictionary
  145. {
  146. NSString *encrypted;
  147. NSString *passcode = [self getKeyPasscode:uuid];
  148. NSString *fileNamePath = [NSTemporaryDirectory() stringByAppendingString:nameFile];
  149. NSString *fileCryptoPath = [NSTemporaryDirectory() stringByAppendingString:[CCUtility trasformedFileNamePlistInCrypto:nameFile]];
  150. NSString *hint = [CCUtility getHint];
  151. NSMutableDictionary *data = [[NSMutableDictionary alloc] init];
  152. for (NSString *key in [dictionary allKeys]) {
  153. encrypted = [CCUtility stringValueForKey:key conDictionary:dictionary];
  154. if ([encrypted length] == 0) encrypted = @"";
  155. else encrypted = [AESCrypt encrypt:encrypted password:passcode];
  156. [dictionary setObject:encrypted forKey:key];
  157. }
  158. [data setObject: dictionary forKey:@"field"];
  159. if ([hint length] > 0) [data setObject: [AESCrypt encrypt:hint password:k_UUID_SIM] forKey:@"hint"];
  160. [data setObject: icon forKey:@"icon"];
  161. [data setObject: model forKey:@"model"];
  162. [data setObject: [CCUtility getNameCurrentDevice] forKey:@"namecurrentdevice"];
  163. [data setObject: k_versionProtocolPlist forKey:@"protocol"];
  164. [data setObject: title forKey:@"title"];
  165. [data setObject: k_metadataType_template forKey:@"type"];
  166. [data setObject: uuid forKey:@"uuid"];
  167. [data setObject: [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"] forKey:@"version"];
  168. BOOL ritorno = [data writeToFile:fileNamePath atomically:YES];
  169. if (ritorno)
  170. [CCUtility copyFileAtPath:fileNamePath toPath:fileCryptoPath];
  171. return ritorno;
  172. }
  173. - (NSMutableDictionary *)getDictionaryEncrypted:(NSString *)fileName uuid:(NSString *)uuid isLocal:(BOOL)isLocal directoryUser:(NSString *)directoryUser
  174. {
  175. NSMutableDictionary *data;
  176. NSString *clearText;
  177. NSString *passcode = [self getKeyPasscode:uuid];
  178. NSString *serverUrl;
  179. if (isLocal) serverUrl = [CCUtility getDirectoryLocal];
  180. else serverUrl = directoryUser;
  181. NSString *fileNamePath = [NSString stringWithFormat:@"%@/%@", serverUrl, fileName];
  182. if (![[NSFileManager defaultManager] fileExistsAtPath:fileNamePath])
  183. return nil;
  184. data = [[NSMutableDictionary alloc] initWithContentsOfFile:fileNamePath];
  185. if (!data)
  186. return nil;
  187. NSMutableDictionary *dictionary = [data objectForKey:@"field"];
  188. for (NSString *key in [dictionary allKeys]) {
  189. NSString *valore = [dictionary objectForKey:key];
  190. if ([valore length]) clearText = [AESCrypt decrypt:valore password:passcode];
  191. else clearText = @"";
  192. if ([clearText length]) [dictionary setObject:clearText forKey:key];
  193. }
  194. return dictionary;
  195. }
  196. - (NSString *)getHintFromFile:(NSString *)fileName isLocal:(BOOL)isLocal directoryUser:(NSString *)directoryUser
  197. {
  198. NSString *serverUrl;
  199. if (isLocal) serverUrl = [CCUtility getDirectoryLocal];
  200. else serverUrl = directoryUser;
  201. NSString *filePath = [NSString stringWithFormat:@"%@/%@", serverUrl, fileName];
  202. if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
  203. return nil;
  204. NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath];
  205. if (!data)
  206. return nil;
  207. NSString *hintCryptated = [data objectForKey:@"hint"];
  208. if ([hintCryptated length] > 0) return [AESCrypt decrypt:hintCryptated password:k_UUID_SIM];
  209. else return nil;
  210. }
  211. - (NSString *)createFilenameEncryptor:(NSString *)fileName uuid:(NSString *)uuid
  212. {
  213. NSMutableString *cryptoString = [NSMutableString stringWithCapacity: 64];
  214. NSString *letters = @"0J7pfXHaCPTasxQDFsUDcSDiHJmVjgzsqDUUQU75IPYrT13YKNJpvvEq0hH2uDD06mhNxvb8";
  215. NSString *temp = [NSString stringWithFormat:@"%@|%@|%@", fileName, uuid, uuid];
  216. temp = [temp substringToIndex:64];
  217. for (int i=0; i<64; i++){
  218. NSString *numero = [temp substringWithRange:NSMakeRange(i, 1)];
  219. NSInteger index = [numero integerValue];
  220. if (index > 0) [cryptoString appendFormat: @"%C", [letters characterAtIndex:index]];
  221. else [cryptoString appendFormat: @"%C", [letters characterAtIndex:i]];
  222. }
  223. return [NSString stringWithFormat:@"%@crypto", cryptoString];
  224. }
  225. #pragma --------------------------------------------------------------------------------------------
  226. #pragma mark ===== Encypt =====
  227. #pragma---------------------------------------------------------------------------------------------
  228. - (NSString *)encryptWithCreatePlist:(NSString *)fileName fileNameEncrypted:(NSString*)fileNameEncrypted passcode:(NSString *)passcode directoryUser:(NSString *)directoryUser
  229. {
  230. NSString *uuid = [CCUtility getUUID];
  231. NSString *nameCurrentDevice = [CCUtility getNameCurrentDevice];
  232. NSString *title = [AESCrypt encrypt:fileName password:passcode];
  233. NSString *fileNameCrypto = [self createFilenameEncryptor:fileNameEncrypted uuid:uuid];
  234. NSError *error;
  235. NSUInteger lenData = (NSUInteger)[[[NSFileManager defaultManager] attributesOfItemAtPath:[NSString stringWithFormat:@"%@/%@", directoryUser, fileName] error:nil] fileSize];
  236. NSUInteger lenEncryptedData;
  237. @autoreleasepool {
  238. NSData *encryptedData = [RNEncryptor encryptData:[NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/%@", directoryUser, fileName]] withSettings:kRNCryptorAES256Settings password:passcode error:&error];
  239. lenEncryptedData = encryptedData.length;
  240. if (!error && lenEncryptedData > 0)
  241. [encryptedData writeToFile:[NSString stringWithFormat:@"%@/%@", directoryUser, fileNameCrypto] atomically:YES];
  242. }
  243. if (error || lenEncryptedData == 0 || lenData == 0) {
  244. [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@", directoryUser, fileNameEncrypted] error:nil];
  245. NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"_encrypt_error_", nil), fileName, [error localizedDescription]];
  246. NSLog(@"[LOG] Error encrypt file %@ Err. %@", fileName, msg);
  247. return nil;
  248. }
  249. [self createFilePlist:[NSString stringWithFormat:@"%@/%@", directoryUser, fileNameCrypto] title:title len:lenData directory:NO uuid:uuid nameCurrentDevice:nameCurrentDevice icon:nil];
  250. return fileNameCrypto;
  251. }
  252. #pragma --------------------------------------------------------------------------------------------
  253. #pragma mark ===== Decrypt =====
  254. #pragma---------------------------------------------------------------------------------------------
  255. - (NSUInteger)decrypt:(NSString *)fileName fileNameDecrypted:(NSString*)fileNameDecrypted fileNamePrint:(NSString *)fileNamePrint password:(NSString *)password directoryUser:(NSString *)directoryUser
  256. {
  257. NSError *error;
  258. NSUInteger len;
  259. @autoreleasepool {
  260. NSData *decryptedData = [RNDecryptor decryptData:[NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/%@.crypt", directoryUser, fileName]] withSettings:kRNCryptorAES256Settings password:password error:&error];
  261. len = decryptedData.length;
  262. if (!error && decryptedData > 0)
  263. [decryptedData writeToFile:[NSString stringWithFormat:@"%@/%@", directoryUser, fileNameDecrypted] atomically:YES];
  264. }
  265. if (error || len == 0) {
  266. [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@", directoryUser, fileNameDecrypted] error:nil];
  267. NSString *msg = [NSString stringWithFormat:NSLocalizedString(@"_decrypt_error_", nil), fileNamePrint, [error localizedDescription]];
  268. NSLog(@"[LOG] Error decrypt file %@ Err. %@", fileName, msg);
  269. return 0;
  270. }
  271. return len;
  272. }
  273. #pragma --------------------------------------------------------------------------------------------
  274. #pragma mark ===== SHA512 =====
  275. #pragma---------------------------------------------------------------------------------------------
  276. - (NSString *)createSHA512:(NSString *)string
  277. {
  278. const char *cstr = [string cStringUsingEncoding:NSUTF8StringEncoding];
  279. NSData *data = [NSData dataWithBytes:cstr length:string.length];
  280. uint8_t digest[CC_SHA512_DIGEST_LENGTH];
  281. CC_SHA512(data.bytes, (unsigned int)data.length, digest);
  282. NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA512_DIGEST_LENGTH * 2];
  283. for(int i = 0; i < CC_SHA512_DIGEST_LENGTH; i++)
  284. [output appendFormat:@"%02x", digest[i]];
  285. return output;
  286. }
  287. @end