123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- ////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2014 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 "LabelViewController.h"
- #import <Realm/Realm.h>
- #import <Security/Security.h>
- // Model definition
- @interface StringObject : RLMObject
- @property NSString *stringProp;
- @end
- @implementation StringObject
- // Nothing needed
- @end
- @interface LabelViewController ()
- @property (nonatomic, strong) UITextView *textView;
- @end
- @implementation LabelViewController
- // Create a view to display output in
- - (void)loadView {
- CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
- UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame];
- contentView.backgroundColor = [UIColor whiteColor];
- self.view = contentView;
- self.textView = [[UITextView alloc] initWithFrame:applicationFrame];
- [self.view addSubview:self.textView];
- }
- - (void)viewDidAppear:(BOOL)animated {
- [super viewDidAppear:animated];
- // Use an autorelease pool to close the Realm at the end of the block, so
- // that we can try to reopen it with different keys
- @autoreleasepool {
- RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
- configuration.encryptionKey = [self getKey];
- RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration
- error:nil];
- // Add an object
- [realm beginWriteTransaction];
- StringObject *obj = [[StringObject alloc] init];
- obj.stringProp = @"abcd";
- [realm addObject:obj];
- [realm commitWriteTransaction];
- }
- // Opening with wrong key fails since it decrypts to the wrong thing
- @autoreleasepool {
- uint8_t buffer[64];
- int status = SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
- NSAssert(status == 0, @"Failed to generate random bytes for key");
- (void)status;
- NSError *error;
- RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
- configuration.encryptionKey = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];
- [RLMRealm realmWithConfiguration:configuration
- error:&error];
- [self log:@"Open with wrong key: %@", error];
- }
- // Opening wihout supplying a key at all fails
- @autoreleasepool {
- NSError *error;
- [RLMRealm realmWithConfiguration:[RLMRealmConfiguration defaultConfiguration] error:&error];
- [self log:@"Open with no key: %@", error];
- }
- // Reopening with the correct key works and can read the data
- @autoreleasepool {
- RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
- configuration.encryptionKey = [self getKey];
- RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration
- error:nil];
- [self log:@"Saved object: %@", [[[StringObject allObjectsInRealm:realm] firstObject] stringProp]];
- }
- }
- // Log a message to the screen since we can't just use NSLog() with no debugger attached
- - (void)log:(NSString *)format, ... {
- va_list args;
- va_start(args, format);
- NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
- va_end(args);
- self.textView.text = [[self.textView.text
- stringByAppendingString:str]
- stringByAppendingString:@"\n\n"];
- }
- - (NSData *)getKey {
- // Identifier for our keychain entry - should be unique for your application
- static const uint8_t kKeychainIdentifier[] = "io.Realm.EncryptionExampleKey";
- NSData *tag = [[NSData alloc] initWithBytesNoCopy:(void *)kKeychainIdentifier
- length:sizeof(kKeychainIdentifier)
- freeWhenDone:NO];
- // First check in the keychain for an existing key
- NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassKey,
- (__bridge id)kSecAttrApplicationTag: tag,
- (__bridge id)kSecAttrKeySizeInBits: @512,
- (__bridge id)kSecReturnData: @YES};
- CFTypeRef dataRef = NULL;
- OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef);
- if (status == errSecSuccess) {
- return (__bridge NSData *)dataRef;
- }
- // No pre-existing key from this application, so generate a new one
- uint8_t buffer[64];
- status = SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
- NSAssert(status == 0, @"Failed to generate random bytes for key");
- NSData *keyData = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];
- // Store the key in the keychain
- query = @{(__bridge id)kSecClass: (__bridge id)kSecClassKey,
- (__bridge id)kSecAttrApplicationTag: tag,
- (__bridge id)kSecAttrKeySizeInBits: @512,
- (__bridge id)kSecValueData: keyData};
- status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
- NSAssert(status == errSecSuccess, @"Failed to insert new key in the keychain");
- return keyData;
- }
- @end
|