LabelViewController.m 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. ////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2014 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 "LabelViewController.h"
  19. #import <Realm/Realm.h>
  20. #import <Security/Security.h>
  21. // Model definition
  22. @interface StringObject : RLMObject
  23. @property NSString *stringProp;
  24. @end
  25. @implementation StringObject
  26. // Nothing needed
  27. @end
  28. @interface LabelViewController ()
  29. @property (nonatomic, strong) UITextView *textView;
  30. @end
  31. @implementation LabelViewController
  32. // Create a view to display output in
  33. - (void)loadView {
  34. CGRect applicationFrame = [[UIScreen mainScreen] applicationFrame];
  35. UIView *contentView = [[UIView alloc] initWithFrame:applicationFrame];
  36. contentView.backgroundColor = [UIColor whiteColor];
  37. self.view = contentView;
  38. self.textView = [[UITextView alloc] initWithFrame:applicationFrame];
  39. [self.view addSubview:self.textView];
  40. }
  41. - (void)viewDidAppear:(BOOL)animated {
  42. [super viewDidAppear:animated];
  43. // Use an autorelease pool to close the Realm at the end of the block, so
  44. // that we can try to reopen it with different keys
  45. @autoreleasepool {
  46. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  47. configuration.encryptionKey = [self getKey];
  48. RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration
  49. error:nil];
  50. // Add an object
  51. [realm beginWriteTransaction];
  52. StringObject *obj = [[StringObject alloc] init];
  53. obj.stringProp = @"abcd";
  54. [realm addObject:obj];
  55. [realm commitWriteTransaction];
  56. }
  57. // Opening with wrong key fails since it decrypts to the wrong thing
  58. @autoreleasepool {
  59. uint8_t buffer[64];
  60. int status = SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
  61. NSAssert(status == 0, @"Failed to generate random bytes for key");
  62. (void)status;
  63. NSError *error;
  64. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  65. configuration.encryptionKey = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];
  66. [RLMRealm realmWithConfiguration:configuration
  67. error:&error];
  68. [self log:@"Open with wrong key: %@", error];
  69. }
  70. // Opening wihout supplying a key at all fails
  71. @autoreleasepool {
  72. NSError *error;
  73. [RLMRealm realmWithConfiguration:[RLMRealmConfiguration defaultConfiguration] error:&error];
  74. [self log:@"Open with no key: %@", error];
  75. }
  76. // Reopening with the correct key works and can read the data
  77. @autoreleasepool {
  78. RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
  79. configuration.encryptionKey = [self getKey];
  80. RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration
  81. error:nil];
  82. [self log:@"Saved object: %@", [[[StringObject allObjectsInRealm:realm] firstObject] stringProp]];
  83. }
  84. }
  85. // Log a message to the screen since we can't just use NSLog() with no debugger attached
  86. - (void)log:(NSString *)format, ... {
  87. va_list args;
  88. va_start(args, format);
  89. NSString *str = [[NSString alloc] initWithFormat:format arguments:args];
  90. va_end(args);
  91. self.textView.text = [[self.textView.text
  92. stringByAppendingString:str]
  93. stringByAppendingString:@"\n\n"];
  94. }
  95. - (NSData *)getKey {
  96. // Identifier for our keychain entry - should be unique for your application
  97. static const uint8_t kKeychainIdentifier[] = "io.Realm.EncryptionExampleKey";
  98. NSData *tag = [[NSData alloc] initWithBytesNoCopy:(void *)kKeychainIdentifier
  99. length:sizeof(kKeychainIdentifier)
  100. freeWhenDone:NO];
  101. // First check in the keychain for an existing key
  102. NSDictionary *query = @{(__bridge id)kSecClass: (__bridge id)kSecClassKey,
  103. (__bridge id)kSecAttrApplicationTag: tag,
  104. (__bridge id)kSecAttrKeySizeInBits: @512,
  105. (__bridge id)kSecReturnData: @YES};
  106. CFTypeRef dataRef = NULL;
  107. OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &dataRef);
  108. if (status == errSecSuccess) {
  109. return (__bridge NSData *)dataRef;
  110. }
  111. // No pre-existing key from this application, so generate a new one
  112. uint8_t buffer[64];
  113. status = SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
  114. NSAssert(status == 0, @"Failed to generate random bytes for key");
  115. NSData *keyData = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];
  116. // Store the key in the keychain
  117. query = @{(__bridge id)kSecClass: (__bridge id)kSecClassKey,
  118. (__bridge id)kSecAttrApplicationTag: tag,
  119. (__bridge id)kSecAttrKeySizeInBits: @512,
  120. (__bridge id)kSecValueData: keyData};
  121. status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
  122. NSAssert(status == errSecSuccess, @"Failed to insert new key in the keychain");
  123. return keyData;
  124. }
  125. @end