EncryptionTests.mm 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2015 Realm Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. //
  17. ////////////////////////////////////////////////////////////////////////////
  18. #import "RLMTestCase.h"
  19. #import "RLMObjectSchema_Private.h"
  20. #import "RLMRealmConfiguration_Private.h"
  21. #import "RLMRealm_Private.h"
  22. #import "RLMSchema_Private.h"
  23. #import "RLMUtil.hpp"
  24. @interface EncryptionTests : RLMTestCase
  25. @end
  26. @implementation EncryptionTests
  27. - (RLMRealmConfiguration *)configurationWithKey:(NSData *)key {
  28. RLMRealmConfiguration *configuration = [[RLMRealmConfiguration alloc] init];
  29. configuration.fileURL = RLMDefaultRealmURL();
  30. configuration.encryptionKey = key;
  31. return configuration;
  32. }
  33. - (RLMRealm *)realmWithKey:(NSData *)key {
  34. return [RLMRealm realmWithConfiguration:[self configurationWithKey:key] error:nil];
  35. }
  36. #pragma mark - Key validation
  37. - (void)testBadEncryptionKeys {
  38. XCTAssertThrows([RLMRealm.defaultRealm writeCopyToURL:RLMTestRealmURL() encryptionKey:NSData.data error:nil]);
  39. }
  40. - (void)testValidEncryptionKeys {
  41. XCTAssertNoThrow([RLMRealm.defaultRealm writeCopyToURL:RLMTestRealmURL() encryptionKey:self.nonLiteralNil error:nil]);
  42. NSData *key = [[NSMutableData alloc] initWithLength:64];
  43. XCTAssertNoThrow([RLMRealm.defaultRealm writeCopyToURL:RLMTestRealmURL() encryptionKey:key error:nil]);
  44. }
  45. #pragma mark - realmWithURL:
  46. - (void)testReopenWithSameKeyWorks {
  47. NSData *key = RLMGenerateKey();
  48. @autoreleasepool {
  49. RLMRealm *realm = [self realmWithKey:key];
  50. [realm transactionWithBlock:^{
  51. [IntObject createInRealm:realm withValue:@[@1]];
  52. }];
  53. }
  54. @autoreleasepool {
  55. RLMRealm *realm = [self realmWithKey:key];
  56. XCTAssertEqual(1U, [IntObject allObjectsInRealm:realm].count);
  57. }
  58. }
  59. - (void)testReopenWithNoKeyThrows {
  60. NSData *key = RLMGenerateKey();
  61. @autoreleasepool {
  62. [self realmWithKey:key];
  63. }
  64. @autoreleasepool {
  65. RLMAssertThrowsWithError([RLMRealm defaultRealm],
  66. @"Unable to open a realm at path",
  67. RLMErrorFileAccess,
  68. @"invalid mnemonic");
  69. }
  70. }
  71. - (void)testReopenWithWrongKeyThrows {
  72. @autoreleasepool {
  73. NSData *key = RLMGenerateKey();
  74. [self realmWithKey:key];
  75. }
  76. @autoreleasepool {
  77. NSData *key = RLMGenerateKey();
  78. RLMAssertThrowsWithError([self realmWithKey:key],
  79. @"Unable to open a realm at path",
  80. RLMErrorFileAccess,
  81. @"Realm file decryption failed");
  82. }
  83. }
  84. - (void)testOpenUnencryptedWithKeyThrows {
  85. @autoreleasepool {
  86. [RLMRealm defaultRealm];
  87. }
  88. @autoreleasepool {
  89. NSData *key = RLMGenerateKey();
  90. // FIXME: Should throw a "Realm file decryption failed" exception
  91. // https://github.com/realm/realm-cocoa-private/issues/347
  92. XCTAssertThrows([self realmWithKey:key]);
  93. // RLMAssertThrowsWithError([self realmWithKey:key],
  94. // @"Unable to open a realm at path",
  95. // RLMErrorFileAccess,
  96. // @"Realm file decryption failed");
  97. }
  98. }
  99. - (void)testOpenWithNewKeyWhileAlreadyOpenThrows {
  100. [self realmWithKey:RLMGenerateKey()];
  101. RLMAssertThrows([self realmWithKey:RLMGenerateKey()], @"already opened with different encryption key");
  102. }
  103. #pragma mark - writeCopyToURL:
  104. - (void)testWriteCopyToPathWithNoKeyWritesDecrypted {
  105. NSData *key = RLMGenerateKey();
  106. @autoreleasepool {
  107. RLMRealm *realm = [self realmWithKey:key];
  108. [realm transactionWithBlock:^{
  109. [IntObject createInRealm:realm withValue:@[@1]];
  110. }];
  111. [realm writeCopyToURL:RLMTestRealmURL() encryptionKey:nil error:nil];
  112. }
  113. @autoreleasepool {
  114. RLMRealm *realm = [self realmWithTestPath];
  115. XCTAssertEqual(1U, [IntObject allObjectsInRealm:realm].count);
  116. }
  117. }
  118. - (void)testWriteCopyToPathWithNewKey {
  119. NSData *key1 = RLMGenerateKey();
  120. NSData *key2 = RLMGenerateKey();
  121. @autoreleasepool {
  122. RLMRealm *realm = [self realmWithKey:key1];
  123. [realm transactionWithBlock:^{
  124. [IntObject createInRealm:realm withValue:@[@1]];
  125. }];
  126. [realm writeCopyToURL:RLMTestRealmURL() encryptionKey:key2 error:nil];
  127. }
  128. @autoreleasepool {
  129. RLMRealmConfiguration *config = [self configurationWithKey:key2];
  130. config.fileURL = RLMTestRealmURL();
  131. RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
  132. XCTAssertEqual(1U, [IntObject allObjectsInRealm:realm].count);
  133. }
  134. }
  135. #pragma mark - Migrations
  136. - (void)createRealmRequiringMigrationWithKey:(NSData *)key migrationRun:(BOOL *)migrationRun {
  137. // Create an object schema which requires migration to the shared schema
  138. RLMObjectSchema *objectSchema = [RLMObjectSchema schemaForObjectClass:IntObject.class];
  139. objectSchema.properties = @[];
  140. RLMSchema *schema = [[RLMSchema alloc] init];
  141. schema.objectSchema = @[objectSchema];
  142. // Create the Realm file on disk
  143. @autoreleasepool {
  144. RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
  145. config.encryptionKey = key;
  146. config.customSchema = schema;
  147. [RLMRealm realmWithConfiguration:config error:nil];
  148. }
  149. RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
  150. config.schemaVersion = 1;
  151. config.migrationBlock = ^(__unused RLMMigration *migration, __unused uint64_t oldSchemaVersion) {
  152. *migrationRun = YES;
  153. };
  154. [RLMRealmConfiguration setDefaultConfiguration:config];
  155. }
  156. - (void)testImplicitMigration {
  157. NSData *key = RLMGenerateKey();
  158. BOOL migrationRan = NO;
  159. [self createRealmRequiringMigrationWithKey:key migrationRun:&migrationRan];
  160. XCTAssertThrows([RLMRealm defaultRealm]);
  161. XCTAssertFalse(migrationRan);
  162. RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
  163. config.encryptionKey = key;
  164. XCTAssertNoThrow([RLMRealm realmWithConfiguration:config error:nil]);
  165. XCTAssertTrue(migrationRan);
  166. }
  167. - (void)testExplicitMigration {
  168. NSData *key = RLMGenerateKey();
  169. __block BOOL migrationRan = NO;
  170. [self createRealmRequiringMigrationWithKey:key migrationRun:&migrationRan];
  171. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  172. configuration.schemaVersion = 1;
  173. configuration.migrationBlock = ^(__unused RLMMigration *migration, __unused uint64_t oldSchemaVersion) {
  174. migrationRan = YES;
  175. };
  176. XCTAssertFalse([RLMRealm performMigrationForConfiguration:configuration error:nil]);
  177. XCTAssertFalse(migrationRan);
  178. configuration.encryptionKey = key;
  179. XCTAssertTrue([RLMRealm performMigrationForConfiguration:configuration error:nil]);
  180. XCTAssertTrue(migrationRan);
  181. }
  182. @end