RNEncryptor.m 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. //
  2. // RNEncryptor
  3. //
  4. // Copyright (c) 2012 Rob Napier
  5. //
  6. // This code is licensed under the MIT License:
  7. //
  8. // Permission is hereby granted, free of charge, to any person obtaining a
  9. // copy of this software and associated documentation files (the "Software"),
  10. // to deal in the Software without restriction, including without limitation
  11. // the rights to use, copy, modify, merge, publish, distribute, sublicense,
  12. // and/or sell copies of the Software, and to permit persons to whom the
  13. // Software is furnished to do so, subject to the following conditions:
  14. //
  15. // The above copyright notice and this permission notice shall be included in
  16. // all copies or substantial portions of the Software.
  17. //
  18. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. // FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
  21. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  24. // DEALINGS IN THE SOFTWARE.
  25. //
  26. #import "RNEncryptor.h"
  27. #import "RNCryptor+Private.h"
  28. #import "RNCryptorEngine.h"
  29. #import <CommonCrypto/CommonHMAC.h>
  30. @interface RNEncryptor ()
  31. @property (nonatomic, readwrite, strong) NSData *encryptionSalt;
  32. @property (nonatomic, readwrite, strong) NSData *HMACSalt;
  33. @property (nonatomic, readwrite, strong) NSData *IV;
  34. @property (nonatomic, readwrite, assign) BOOL haveWrittenHeader;
  35. @end
  36. @implementation RNEncryptor
  37. {
  38. CCHmacContext _HMACContext;
  39. }
  40. @synthesize encryptionSalt = _encryptionSalt;
  41. @synthesize HMACSalt = _HMACSalt;
  42. @synthesize IV = _IV;
  43. @synthesize haveWrittenHeader = _haveWrittenHeader;
  44. + (NSData *)encryptData:(NSData *)thePlaintext withSettings:(RNCryptorSettings)theSettings password:(NSString *)aPassword error:(NSError **)anError
  45. {
  46. RNEncryptor *cryptor = [[self alloc] initWithSettings:theSettings
  47. password:aPassword
  48. handler:^(RNCryptor *c, NSData *d) {}];
  49. return [self synchronousResultForCryptor:cryptor data:thePlaintext error:anError];
  50. }
  51. + (NSData *)encryptData:(NSData *)thePlaintext
  52. withSettings:(RNCryptorSettings)theSettings
  53. password:(NSString *)aPassword
  54. IV:(NSData *)anIV
  55. encryptionSalt:(NSData *)anEncryptionSalt
  56. HMACSalt:(NSData *)anHMACSalt
  57. error:(NSError **)anError
  58. {
  59. RNEncryptor *cryptor = [[self alloc] initWithSettings:theSettings
  60. password:aPassword
  61. IV:anIV
  62. encryptionSalt:anEncryptionSalt
  63. HMACSalt:anHMACSalt
  64. handler:^(RNCryptor *c, NSData *d) {}];
  65. return [self synchronousResultForCryptor:cryptor data:thePlaintext error:anError];
  66. }
  67. + (NSData *)encryptData:(NSData *)thePlaintext withSettings:(RNCryptorSettings)theSettings encryptionKey:(NSData *)anEncryptionKey HMACKey:(NSData *)anHMACKey error:(NSError **)anError {
  68. RNEncryptor *cryptor = [[self alloc] initWithSettings:theSettings
  69. encryptionKey:anEncryptionKey
  70. HMACKey:anHMACKey
  71. handler:^(RNCryptor *c, NSData *d) {}];
  72. return [self synchronousResultForCryptor:cryptor data:thePlaintext error:anError];
  73. }
  74. + (NSData *)encryptData:(NSData *)thePlaintext
  75. withSettings:(RNCryptorSettings)theSettings
  76. encryptionKey:(NSData *)anEncryptionKey
  77. HMACKey:(NSData *)anHMACKey
  78. IV:(NSData *)anIV
  79. error:(NSError **)anError
  80. {
  81. RNEncryptor *cryptor = [[self alloc] initWithSettings:theSettings
  82. encryptionKey:anEncryptionKey
  83. HMACKey:anHMACKey
  84. IV:anIV
  85. handler:^(RNCryptor *c, NSData *d) {}];
  86. return [self synchronousResultForCryptor:cryptor data:thePlaintext error:anError];
  87. }
  88. - (RNEncryptor *)initWithSettings:(RNCryptorSettings)theSettings
  89. encryptionKey:(NSData *)anEncryptionKey
  90. HMACKey:(NSData *)anHMACKey
  91. handler:(RNCryptorHandler)aHandler {
  92. return [self initWithSettings:kRNCryptorAES256Settings
  93. encryptionKey:anEncryptionKey
  94. HMACKey:anHMACKey
  95. IV:[[self class] randomDataOfLength:theSettings.IVSize]
  96. handler:aHandler];
  97. }
  98. - (RNEncryptor *)initWithSettings:(RNCryptorSettings)theSettings
  99. encryptionKey:(NSData *)anEncryptionKey
  100. HMACKey:(NSData *)anHMACKey
  101. IV:(NSData *)anIV
  102. handler:(RNCryptorHandler)aHandler
  103. {
  104. self = [super initWithHandler:aHandler];
  105. if (self) {
  106. self.IV = anIV;
  107. if (anHMACKey) {
  108. CCHmacInit(&_HMACContext, theSettings.HMACAlgorithm, anHMACKey.bytes, anHMACKey.length);
  109. self.HMACLength = theSettings.HMACLength;
  110. }
  111. NSError *error = nil;
  112. self.engine = [[RNCryptorEngine alloc] initWithOperation:kCCEncrypt
  113. settings:theSettings
  114. key:anEncryptionKey
  115. IV:self.IV
  116. error:&error];
  117. if (!self.engine) {
  118. [self cleanupAndNotifyWithError:error];
  119. self = nil;
  120. return nil;
  121. }
  122. }
  123. return self;
  124. }
  125. - (RNEncryptor *)initWithSettings:(RNCryptorSettings)theSettings password:(NSString *)aPassword handler:(RNCryptorHandler)aHandler {
  126. return [self initWithSettings:theSettings
  127. password:aPassword
  128. IV:[[self class] randomDataOfLength:theSettings.IVSize]
  129. encryptionSalt:[[self class] randomDataOfLength:theSettings.keySettings.saltSize]
  130. HMACSalt:[[self class] randomDataOfLength:theSettings.HMACKeySettings.saltSize]
  131. handler:aHandler];
  132. }
  133. - (RNEncryptor *)initWithSettings:(RNCryptorSettings)theSettings
  134. password:(NSString *)aPassword
  135. IV:(NSData *)anIV
  136. encryptionSalt:(NSData *)anEncryptionSalt
  137. HMACSalt:(NSData *)anHMACSalt
  138. handler:(RNCryptorHandler)aHandler;
  139. {
  140. NSParameterAssert(aPassword.length > 0); // We'll go forward, but this is undefined behavior for RNCryptor
  141. NSParameterAssert(anIV);
  142. NSParameterAssert(anEncryptionSalt);
  143. NSParameterAssert(anHMACSalt);
  144. NSData *encryptionKey = [[self class] keyForPassword:aPassword salt:anEncryptionSalt settings:theSettings.keySettings];
  145. NSData *HMACKey = [[self class] keyForPassword:aPassword salt:anHMACSalt settings:theSettings.HMACKeySettings];
  146. self = [self initWithSettings:theSettings
  147. encryptionKey:encryptionKey
  148. HMACKey:HMACKey
  149. IV:anIV
  150. handler:aHandler];
  151. if (self) {
  152. self.options |= kRNCryptorOptionHasPassword;
  153. self.encryptionSalt = anEncryptionSalt;
  154. self.HMACSalt = anHMACSalt;
  155. }
  156. return self;
  157. }
  158. - (NSData *)header
  159. {
  160. uint8_t header[2] = {kRNCryptorFileVersion, self.options};
  161. NSMutableData *headerData = [NSMutableData dataWithBytes:header length:sizeof(header)];
  162. if (self.options & kRNCryptorOptionHasPassword) {
  163. [headerData appendData:self.encryptionSalt];
  164. [headerData appendData:self.HMACSalt];
  165. }
  166. [headerData appendData:self.IV];
  167. return headerData;
  168. }
  169. - (void)addData:(NSData *)data
  170. {
  171. if (self.isFinished) {
  172. return;
  173. }
  174. dispatch_async(self.queue, ^{
  175. if (!self.haveWrittenHeader) {
  176. NSData *header = [self header];
  177. [self.outData setData:header];
  178. if (self.hasHMAC) {
  179. CCHmacUpdate(&_HMACContext, [header bytes], [header length]);
  180. }
  181. self.haveWrittenHeader = YES;
  182. }
  183. NSError *error = nil;
  184. NSData *encryptedData = [self.engine addData:data error:&error];
  185. if (!encryptedData) {
  186. [self cleanupAndNotifyWithError:error];
  187. }
  188. if (self.hasHMAC) {
  189. CCHmacUpdate(&_HMACContext, encryptedData.bytes, encryptedData.length);
  190. }
  191. [self.outData appendData:encryptedData];
  192. dispatch_sync(self.responseQueue, ^{
  193. self.handler(self, self.outData);
  194. });
  195. [self.outData setLength:0];
  196. });
  197. }
  198. - (void)finish
  199. {
  200. if (self.isFinished) {
  201. return;
  202. }
  203. dispatch_async(self.queue, ^{
  204. NSError *error = nil;
  205. NSData *encryptedData = [self.engine finishWithError:&error];
  206. [self.outData appendData:encryptedData];
  207. if (self.hasHMAC) {
  208. CCHmacUpdate(&_HMACContext, encryptedData.bytes, encryptedData.length);
  209. NSMutableData *HMACData = [NSMutableData dataWithLength:self.HMACLength];
  210. CCHmacFinal(&_HMACContext, [HMACData mutableBytes]);
  211. [self.outData appendData:HMACData];
  212. }
  213. [self cleanupAndNotifyWithError:error];
  214. });
  215. }
  216. @end