You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
220 lines
7.4 KiB
220 lines
7.4 KiB
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright 2015 Realm Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
#import "RLMTestCase.h"
|
|
|
|
#import "RLMObjectSchema_Private.h"
|
|
#import "RLMRealmConfiguration_Private.h"
|
|
#import "RLMRealm_Private.h"
|
|
#import "RLMSchema_Private.h"
|
|
#import "RLMUtil.hpp"
|
|
|
|
@interface EncryptionTests : RLMTestCase
|
|
@end
|
|
|
|
@implementation EncryptionTests
|
|
|
|
- (RLMRealmConfiguration *)configurationWithKey:(NSData *)key {
|
|
RLMRealmConfiguration *configuration = [[RLMRealmConfiguration alloc] init];
|
|
configuration.fileURL = RLMDefaultRealmURL();
|
|
configuration.encryptionKey = key;
|
|
return configuration;
|
|
}
|
|
|
|
- (RLMRealm *)realmWithKey:(NSData *)key {
|
|
return [RLMRealm realmWithConfiguration:[self configurationWithKey:key] error:nil];
|
|
}
|
|
|
|
#pragma mark - Key validation
|
|
|
|
- (void)testBadEncryptionKeys {
|
|
XCTAssertThrows([RLMRealm.defaultRealm writeCopyToURL:RLMTestRealmURL() encryptionKey:NSData.data error:nil]);
|
|
}
|
|
|
|
- (void)testValidEncryptionKeys {
|
|
XCTAssertNoThrow([RLMRealm.defaultRealm writeCopyToURL:RLMTestRealmURL() encryptionKey:self.nonLiteralNil error:nil]);
|
|
NSData *key = [[NSMutableData alloc] initWithLength:64];
|
|
XCTAssertNoThrow([RLMRealm.defaultRealm writeCopyToURL:RLMTestRealmURL() encryptionKey:key error:nil]);
|
|
}
|
|
|
|
#pragma mark - realmWithURL:
|
|
|
|
- (void)testReopenWithSameKeyWorks {
|
|
NSData *key = RLMGenerateKey();
|
|
@autoreleasepool {
|
|
RLMRealm *realm = [self realmWithKey:key];
|
|
[realm transactionWithBlock:^{
|
|
[IntObject createInRealm:realm withValue:@[@1]];
|
|
}];
|
|
}
|
|
|
|
@autoreleasepool {
|
|
RLMRealm *realm = [self realmWithKey:key];
|
|
XCTAssertEqual(1U, [IntObject allObjectsInRealm:realm].count);
|
|
}
|
|
}
|
|
|
|
- (void)testReopenWithNoKeyThrows {
|
|
NSData *key = RLMGenerateKey();
|
|
@autoreleasepool {
|
|
[self realmWithKey:key];
|
|
}
|
|
|
|
@autoreleasepool {
|
|
RLMAssertThrowsWithError([RLMRealm defaultRealm],
|
|
@"Unable to open a realm at path",
|
|
RLMErrorFileAccess,
|
|
@"invalid mnemonic");
|
|
}
|
|
}
|
|
|
|
- (void)testReopenWithWrongKeyThrows {
|
|
@autoreleasepool {
|
|
NSData *key = RLMGenerateKey();
|
|
[self realmWithKey:key];
|
|
}
|
|
|
|
@autoreleasepool {
|
|
NSData *key = RLMGenerateKey();
|
|
RLMAssertThrowsWithError([self realmWithKey:key],
|
|
@"Unable to open a realm at path",
|
|
RLMErrorFileAccess,
|
|
@"Realm file decryption failed");
|
|
}
|
|
}
|
|
|
|
- (void)testOpenUnencryptedWithKeyThrows {
|
|
@autoreleasepool {
|
|
[RLMRealm defaultRealm];
|
|
}
|
|
|
|
@autoreleasepool {
|
|
NSData *key = RLMGenerateKey();
|
|
// FIXME: Should throw a "Realm file decryption failed" exception
|
|
// https://github.com/realm/realm-cocoa-private/issues/347
|
|
XCTAssertThrows([self realmWithKey:key]);
|
|
// RLMAssertThrowsWithError([self realmWithKey:key],
|
|
// @"Unable to open a realm at path",
|
|
// RLMErrorFileAccess,
|
|
// @"Realm file decryption failed");
|
|
}
|
|
}
|
|
|
|
- (void)testOpenWithNewKeyWhileAlreadyOpenThrows {
|
|
[self realmWithKey:RLMGenerateKey()];
|
|
RLMAssertThrows([self realmWithKey:RLMGenerateKey()], @"already opened with different encryption key");
|
|
}
|
|
|
|
#pragma mark - writeCopyToURL:
|
|
|
|
- (void)testWriteCopyToPathWithNoKeyWritesDecrypted {
|
|
NSData *key = RLMGenerateKey();
|
|
@autoreleasepool {
|
|
RLMRealm *realm = [self realmWithKey:key];
|
|
[realm transactionWithBlock:^{
|
|
[IntObject createInRealm:realm withValue:@[@1]];
|
|
}];
|
|
[realm writeCopyToURL:RLMTestRealmURL() encryptionKey:nil error:nil];
|
|
}
|
|
|
|
@autoreleasepool {
|
|
RLMRealm *realm = [self realmWithTestPath];
|
|
XCTAssertEqual(1U, [IntObject allObjectsInRealm:realm].count);
|
|
}
|
|
}
|
|
|
|
- (void)testWriteCopyToPathWithNewKey {
|
|
NSData *key1 = RLMGenerateKey();
|
|
NSData *key2 = RLMGenerateKey();
|
|
|
|
@autoreleasepool {
|
|
RLMRealm *realm = [self realmWithKey:key1];
|
|
[realm transactionWithBlock:^{
|
|
[IntObject createInRealm:realm withValue:@[@1]];
|
|
}];
|
|
[realm writeCopyToURL:RLMTestRealmURL() encryptionKey:key2 error:nil];
|
|
}
|
|
|
|
@autoreleasepool {
|
|
RLMRealmConfiguration *config = [self configurationWithKey:key2];
|
|
config.fileURL = RLMTestRealmURL();
|
|
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
|
|
XCTAssertEqual(1U, [IntObject allObjectsInRealm:realm].count);
|
|
}
|
|
}
|
|
|
|
#pragma mark - Migrations
|
|
|
|
- (void)createRealmRequiringMigrationWithKey:(NSData *)key migrationRun:(BOOL *)migrationRun {
|
|
// Create an object schema which requires migration to the shared schema
|
|
RLMObjectSchema *objectSchema = [RLMObjectSchema schemaForObjectClass:IntObject.class];
|
|
objectSchema.properties = @[];
|
|
|
|
RLMSchema *schema = [[RLMSchema alloc] init];
|
|
schema.objectSchema = @[objectSchema];
|
|
|
|
// Create the Realm file on disk
|
|
@autoreleasepool {
|
|
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
|
|
config.encryptionKey = key;
|
|
config.customSchema = schema;
|
|
[RLMRealm realmWithConfiguration:config error:nil];
|
|
}
|
|
|
|
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
|
|
config.schemaVersion = 1;
|
|
config.migrationBlock = ^(__unused RLMMigration *migration, __unused uint64_t oldSchemaVersion) {
|
|
*migrationRun = YES;
|
|
};
|
|
[RLMRealmConfiguration setDefaultConfiguration:config];
|
|
}
|
|
|
|
- (void)testImplicitMigration {
|
|
NSData *key = RLMGenerateKey();
|
|
BOOL migrationRan = NO;
|
|
[self createRealmRequiringMigrationWithKey:key migrationRun:&migrationRan];
|
|
|
|
XCTAssertThrows([RLMRealm defaultRealm]);
|
|
XCTAssertFalse(migrationRan);
|
|
|
|
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
|
|
config.encryptionKey = key;
|
|
XCTAssertNoThrow([RLMRealm realmWithConfiguration:config error:nil]);
|
|
XCTAssertTrue(migrationRan);
|
|
}
|
|
|
|
- (void)testExplicitMigration {
|
|
NSData *key = RLMGenerateKey();
|
|
__block BOOL migrationRan = NO;
|
|
[self createRealmRequiringMigrationWithKey:key migrationRun:&migrationRan];
|
|
|
|
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
|
|
configuration.schemaVersion = 1;
|
|
configuration.migrationBlock = ^(__unused RLMMigration *migration, __unused uint64_t oldSchemaVersion) {
|
|
migrationRan = YES;
|
|
};
|
|
|
|
XCTAssertFalse([RLMRealm performMigrationForConfiguration:configuration error:nil]);
|
|
XCTAssertFalse(migrationRan);
|
|
|
|
configuration.encryptionKey = key;
|
|
XCTAssertTrue([RLMRealm performMigrationForConfiguration:configuration error:nil]);
|
|
XCTAssertTrue(migrationRan);
|
|
}
|
|
|
|
@end
|
|
|