CCCrypto.m 16 KB

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