CCCrypto.m 16 KB

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