OLMAccount and OLMSession serialization
This commit is contained in:
parent
f505113fb7
commit
daab2a58af
8 changed files with 350 additions and 38 deletions
|
@ -9,7 +9,9 @@
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "OLMSerializable.h"
|
#import "OLMSerializable.h"
|
||||||
|
|
||||||
@interface OLMAccount : NSObject <OLMSerializable>
|
@class OLMSession;
|
||||||
|
|
||||||
|
@interface OLMAccount : NSObject <OLMSerializable, NSSecureCoding>
|
||||||
|
|
||||||
/** Creates new account */
|
/** Creates new account */
|
||||||
- (instancetype) initNewAccount;
|
- (instancetype) initNewAccount;
|
||||||
|
@ -18,11 +20,13 @@
|
||||||
- (NSDictionary*) identityKeys;
|
- (NSDictionary*) identityKeys;
|
||||||
|
|
||||||
/** signs message with ed25519 key for account */
|
/** signs message with ed25519 key for account */
|
||||||
- (NSData*) signMessage:(NSData*)messageData;
|
- (NSString*) signMessage:(NSData*)messageData;
|
||||||
|
|
||||||
/** Public parts of the unpublished one time keys for the account */
|
/** Public parts of the unpublished one time keys for the account */
|
||||||
- (NSDictionary*) oneTimeKeys;
|
- (NSDictionary*) oneTimeKeys;
|
||||||
|
|
||||||
|
- (BOOL) removeOneTimeKeysForSession:(OLMSession*)session;
|
||||||
|
|
||||||
/** Marks the current set of one time keys as being published. */
|
/** Marks the current set of one time keys as being published. */
|
||||||
- (void) markKeysAsPublished;
|
- (void) markKeysAsPublished;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#import "OLMAccount.h"
|
#import "OLMAccount.h"
|
||||||
#import "OLMAccount_Private.h"
|
#import "OLMAccount_Private.h"
|
||||||
|
#import "OLMSession.h"
|
||||||
|
#import "OLMSession_Private.h"
|
||||||
#import "OLMUtility.h"
|
#import "OLMUtility.h"
|
||||||
|
|
||||||
@import Security;
|
@import Security;
|
||||||
|
@ -34,7 +36,7 @@
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype) initNewAccount {
|
- (instancetype) init {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -43,6 +45,14 @@
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) initNewAccount {
|
||||||
|
self = [self init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
size_t randomLength = olm_create_account_random_length(_account);
|
size_t randomLength = olm_create_account_random_length(_account);
|
||||||
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
|
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
|
||||||
size_t accountResult = olm_create_account(_account, random.mutableBytes, random.length);
|
size_t accountResult = olm_create_account(_account, random.mutableBytes, random.length);
|
||||||
|
@ -114,5 +124,106 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) removeOneTimeKeysForSession:(OLMSession *)session {
|
||||||
|
NSParameterAssert(session != nil);
|
||||||
|
if (!session) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
size_t result = olm_remove_one_time_keys(self.account, session.session);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *error = olm_session_last_error(session.session);
|
||||||
|
NSAssert(NO, @"olm_remove_one_time_keys error: %s", error);
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark OLMSerializable
|
||||||
|
|
||||||
|
/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
|
||||||
|
- (instancetype) initWithSerializedData:(NSString*)serializedData key:(NSData*)key error:(NSError**)error {
|
||||||
|
self = [self init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSParameterAssert(key.length > 0);
|
||||||
|
NSParameterAssert(serializedData.length > 0);
|
||||||
|
if (key.length == 0 || serializedData.length == 0) {
|
||||||
|
if (error) {
|
||||||
|
*error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: @"Bad length."}];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
|
||||||
|
size_t result = olm_unpickle_account(_account, key.bytes, key.length, pickle.mutableBytes, pickle.length);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *olm_error = olm_account_last_error(_account);
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
if (error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Serializes and encrypts object data, outputs base64 blob */
|
||||||
|
- (NSString*) serializeDataWithKey:(NSData*)key error:(NSError**)error {
|
||||||
|
NSParameterAssert(key.length > 0);
|
||||||
|
size_t length = olm_pickle_account_length(_account);
|
||||||
|
NSMutableData *pickled = [NSMutableData dataWithLength:length];
|
||||||
|
size_t result = olm_pickle_account(_account, key.bytes, key.length, pickled.mutableBytes, pickled.length);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *olm_error = olm_account_last_error(_account);
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
if (error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
|
||||||
|
return pickleString;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark NSSecureCoding
|
||||||
|
|
||||||
|
+ (BOOL) supportsSecureCoding {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark NSCoding
|
||||||
|
|
||||||
|
- (id)initWithCoder:(NSCoder *)decoder {
|
||||||
|
NSString *version = [decoder decodeObjectOfClass:[NSString class] forKey:@"version"];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
|
||||||
|
if ([version isEqualToString:@"1"]) {
|
||||||
|
NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"];
|
||||||
|
NSData *key = [decoder decodeObjectOfClass:[NSData class] forKey:@"key"];
|
||||||
|
|
||||||
|
self = [self initWithSerializedData:pickle key:key error:&error];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSParameterAssert(error == nil);
|
||||||
|
NSParameterAssert(self != nil);
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)encoder {
|
||||||
|
NSData *key = [OLMUtility randomBytesOfLength:32];
|
||||||
|
NSError *error = nil;
|
||||||
|
NSString *pickle = [self serializeDataWithKey:key error:&error];
|
||||||
|
NSParameterAssert(pickle.length > 0 && error == nil);
|
||||||
|
|
||||||
|
[encoder encodeObject:pickle forKey:@"pickle"];
|
||||||
|
[encoder encodeObject:key forKey:@"key"];
|
||||||
|
[encoder encodeObject:@"1" forKey:@"version"];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -11,9 +11,9 @@
|
||||||
@protocol OLMSerializable <NSObject>
|
@protocol OLMSerializable <NSObject>
|
||||||
|
|
||||||
/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
|
/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
|
||||||
- (instancetype) initWithSerializedData:(NSData*)serializedData key:(NSData*)key error:(NSError**)error;
|
- (instancetype) initWithSerializedData:(NSString*)serializedData key:(NSData*)key error:(NSError**)error;
|
||||||
|
|
||||||
/** Serializes and encrypts object data */
|
/** Serializes and encrypts object data, outputs base64 blob */
|
||||||
- (NSData*) serializeDataWithKey:(NSData*)key;
|
- (NSString*) serializeDataWithKey:(NSData*)key error:(NSError**)error;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -11,9 +11,7 @@
|
||||||
#import "OLMAccount.h"
|
#import "OLMAccount.h"
|
||||||
#import "OLMMessage.h"
|
#import "OLMMessage.h"
|
||||||
|
|
||||||
@interface OLMSession : NSObject <OLMSerializable>
|
@interface OLMSession : NSObject <OLMSerializable, NSSecureCoding>
|
||||||
|
|
||||||
@property (nonatomic, strong) OLMAccount *account;
|
|
||||||
|
|
||||||
- (instancetype) initOutboundSessionWithAccount:(OLMAccount*)account theirIdentityKey:(NSString*)theirIdentityKey theirOneTimeKey:(NSString*)theirOneTimeKey;
|
- (instancetype) initOutboundSessionWithAccount:(OLMAccount*)account theirIdentityKey:(NSString*)theirIdentityKey theirOneTimeKey:(NSString*)theirOneTimeKey;
|
||||||
|
|
||||||
|
@ -27,8 +25,6 @@
|
||||||
|
|
||||||
- (BOOL) matchesInboundSessionFrom:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage;
|
- (BOOL) matchesInboundSessionFrom:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage;
|
||||||
|
|
||||||
- (BOOL) removeOneTimeKeys;
|
|
||||||
|
|
||||||
/** UTF-8 plaintext -> base64 ciphertext */
|
/** UTF-8 plaintext -> base64 ciphertext */
|
||||||
- (OLMMessage*) encryptMessage:(NSString*)message;
|
- (OLMMessage*) encryptMessage:(NSString*)message;
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,9 @@
|
||||||
#import "OLMSession.h"
|
#import "OLMSession.h"
|
||||||
#import "OLMUtility.h"
|
#import "OLMUtility.h"
|
||||||
#import "OLMAccount_Private.h"
|
#import "OLMAccount_Private.h"
|
||||||
|
#import "OLMSession_Private.h"
|
||||||
@import olm;
|
@import olm;
|
||||||
|
|
||||||
@interface OLMSession()
|
|
||||||
@property (nonatomic) OlmSession *session;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation OLMSession
|
@implementation OLMSession
|
||||||
|
|
||||||
- (void) dealloc {
|
- (void) dealloc {
|
||||||
|
@ -37,7 +34,7 @@
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype) initWithAccount:(OLMAccount*)account {
|
- (instancetype) init {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return nil;
|
return nil;
|
||||||
|
@ -46,6 +43,18 @@
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype) initWithAccount:(OLMAccount*)account {
|
||||||
|
self = [self init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSParameterAssert(account != nil && account.account != NULL);
|
||||||
|
if (account == nil || account.account == NULL) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
_account = account;
|
_account = account;
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -72,10 +81,6 @@
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
BOOL success = [self initializeSessionMemory];
|
|
||||||
if (!success) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
|
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
|
||||||
size_t result = olm_create_inbound_session(_session, account.account, otk.mutableBytes, oneTimeKeyMessage.length);
|
size_t result = olm_create_inbound_session(_session, account.account, otk.mutableBytes, oneTimeKeyMessage.length);
|
||||||
if (result == olm_error()) {
|
if (result == olm_error()) {
|
||||||
|
@ -91,10 +96,6 @@
|
||||||
if (!self) {
|
if (!self) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
BOOL success = [self initializeSessionMemory];
|
|
||||||
if (!success) {
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
NSData *idKey = [theirIdentityKey dataUsingEncoding:NSUTF8StringEncoding];
|
NSData *idKey = [theirIdentityKey dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
|
NSMutableData *otk = [NSMutableData dataWithData:[oneTimeKeyMessage dataUsingEncoding:NSUTF8StringEncoding]];
|
||||||
size_t result = olm_create_inbound_session_from(_session, account.account, idKey.bytes, idKey.length, otk.mutableBytes, otk.length);
|
size_t result = olm_create_inbound_session_from(_session, account.account, idKey.bytes, idKey.length, otk.mutableBytes, otk.length);
|
||||||
|
@ -143,16 +144,6 @@
|
||||||
return encryptedMessage;
|
return encryptedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) removeOneTimeKeys {
|
|
||||||
size_t result = olm_remove_one_time_keys(_account.account, _session);
|
|
||||||
if (result == olm_error()) {
|
|
||||||
const char *error = olm_session_last_error(_session);
|
|
||||||
NSAssert(NO, @"olm_remove_one_time_keys error: %s", error);
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSString*) decryptMessage:(OLMMessage*)message {
|
- (NSString*) decryptMessage:(OLMMessage*)message {
|
||||||
NSParameterAssert(message != nil);
|
NSParameterAssert(message != nil);
|
||||||
NSData *messageData = [message.ciphertext dataUsingEncoding:NSUTF8StringEncoding];
|
NSData *messageData = [message.ciphertext dataUsingEncoding:NSUTF8StringEncoding];
|
||||||
|
@ -180,4 +171,91 @@
|
||||||
return plaintext;
|
return plaintext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma mark OLMSerializable
|
||||||
|
|
||||||
|
/** Initializes from encrypted serialized data. Will throw error if invalid key or invalid base64. */
|
||||||
|
- (instancetype) initWithSerializedData:(NSString*)serializedData key:(NSData*)key error:(NSError**)error {
|
||||||
|
self = [self init];
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSParameterAssert(key.length > 0);
|
||||||
|
NSParameterAssert(serializedData.length > 0);
|
||||||
|
if (key.length == 0 || serializedData.length == 0) {
|
||||||
|
if (error) {
|
||||||
|
*error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: @"Bad length."}];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
|
||||||
|
size_t result = olm_unpickle_session(_session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
if (error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Serializes and encrypts object data, outputs base64 blob */
|
||||||
|
- (NSString*) serializeDataWithKey:(NSData*)key error:(NSError**)error {
|
||||||
|
NSParameterAssert(key.length > 0);
|
||||||
|
size_t length = olm_pickle_session_length(_session);
|
||||||
|
NSMutableData *pickled = [NSMutableData dataWithLength:length];
|
||||||
|
size_t result = olm_pickle_session(_session, key.bytes, key.length, pickled.mutableBytes, pickled.length);
|
||||||
|
if (result == olm_error()) {
|
||||||
|
const char *olm_error = olm_session_last_error(_session);
|
||||||
|
NSString *errorString = [NSString stringWithUTF8String:olm_error];
|
||||||
|
if (error && errorString) {
|
||||||
|
*error = [NSError errorWithDomain:@"org.matrix.olm" code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
|
||||||
|
return pickleString;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark NSSecureCoding
|
||||||
|
|
||||||
|
+ (BOOL) supportsSecureCoding {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark NSCoding
|
||||||
|
|
||||||
|
- (id)initWithCoder:(NSCoder *)decoder {
|
||||||
|
NSString *version = [decoder decodeObjectOfClass:[NSString class] forKey:@"version"];
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
|
||||||
|
if ([version isEqualToString:@"1"]) {
|
||||||
|
NSString *pickle = [decoder decodeObjectOfClass:[NSString class] forKey:@"pickle"];
|
||||||
|
NSData *key = [decoder decodeObjectOfClass:[NSData class] forKey:@"key"];
|
||||||
|
|
||||||
|
self = [self initWithSerializedData:pickle key:key error:&error];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSParameterAssert(error == nil);
|
||||||
|
NSParameterAssert(self != nil);
|
||||||
|
if (!self) {
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)encodeWithCoder:(NSCoder *)encoder {
|
||||||
|
NSData *key = [OLMUtility randomBytesOfLength:32];
|
||||||
|
NSError *error = nil;
|
||||||
|
NSString *pickle = [self serializeDataWithKey:key error:&error];
|
||||||
|
NSParameterAssert(pickle.length > 0 && error == nil);
|
||||||
|
|
||||||
|
[encoder encodeObject:pickle forKey:@"pickle"];
|
||||||
|
[encoder encodeObject:key forKey:@"key"];
|
||||||
|
[encoder encodeObject:@"1" forKey:@"version"];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
16
xcode/OLMKit/OLMSession_Private.h
Normal file
16
xcode/OLMKit/OLMSession_Private.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// OLMSession_Private.h
|
||||||
|
// olm
|
||||||
|
//
|
||||||
|
// Created by Chris Ballinger on 4/13/16.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
@import olm;
|
||||||
|
|
||||||
|
@interface OLMSession()
|
||||||
|
|
||||||
|
@property (nonatomic) OlmSession *session;
|
||||||
|
@property (nonatomic, strong) OLMAccount *account;
|
||||||
|
|
||||||
|
@end
|
|
@ -25,9 +25,7 @@
|
||||||
[super tearDown];
|
[super tearDown];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)testExample {
|
- (void)testAliceAndBob {
|
||||||
// This is an example of a functional test case.
|
|
||||||
// Use XCTAssert and related functions to verify your tests produce the correct results.
|
|
||||||
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
||||||
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
[bob generateOneTimeKeys:5];
|
[bob generateOneTimeKeys:5];
|
||||||
|
@ -50,9 +48,114 @@
|
||||||
OLMSession *bobSession = [[OLMSession alloc] initInboundSessionWithAccount:bob oneTimeKeyMessage:aliceToBobMsg.ciphertext];
|
OLMSession *bobSession = [[OLMSession alloc] initInboundSessionWithAccount:bob oneTimeKeyMessage:aliceToBobMsg.ciphertext];
|
||||||
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg];
|
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg];
|
||||||
XCTAssertEqualObjects(message, plaintext);
|
XCTAssertEqualObjects(message, plaintext);
|
||||||
BOOL success = [bobSession removeOneTimeKeys];
|
BOOL success = [bob removeOneTimeKeysForSession:bobSession];
|
||||||
XCTAssertTrue(success);
|
XCTAssertTrue(success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) testBackAndForth {
|
||||||
|
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
||||||
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
|
[bob generateOneTimeKeys:1];
|
||||||
|
NSDictionary *bobIdKeys = bob.identityKeys;
|
||||||
|
NSString *bobIdKey = bobIdKeys[@"curve25519"];
|
||||||
|
NSDictionary *bobOneTimeKeys = bob.oneTimeKeys;
|
||||||
|
NSParameterAssert(bobIdKey != nil);
|
||||||
|
NSParameterAssert(bobOneTimeKeys != nil);
|
||||||
|
__block NSString *bobOneTimeKey = nil;
|
||||||
|
NSDictionary *bobOtkCurve25519 = bobOneTimeKeys[@"curve25519"];
|
||||||
|
[bobOtkCurve25519 enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
|
||||||
|
bobOneTimeKey = obj;
|
||||||
|
}];
|
||||||
|
XCTAssert([bobOneTimeKey isKindOfClass:[NSString class]]);
|
||||||
|
|
||||||
|
OLMSession *aliceSession = [[OLMSession alloc] initOutboundSessionWithAccount:alice theirIdentityKey:bobIdKey theirOneTimeKey:bobOneTimeKey];
|
||||||
|
NSString *message = @"Hello I'm Alice!";
|
||||||
|
OLMMessage *aliceToBobMsg = [aliceSession encryptMessage:message];
|
||||||
|
|
||||||
|
OLMSession *bobSession = [[OLMSession alloc] initInboundSessionWithAccount:bob oneTimeKeyMessage:aliceToBobMsg.ciphertext];
|
||||||
|
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg];
|
||||||
|
XCTAssertEqualObjects(message, plaintext);
|
||||||
|
BOOL success = [bob removeOneTimeKeysForSession:bobSession];
|
||||||
|
XCTAssertTrue(success);
|
||||||
|
|
||||||
|
NSString *msg1 = @"Hello I'm Bob!";
|
||||||
|
NSString *msg2 = @"Isn't life grand?";
|
||||||
|
NSString *msg3 = @"Let's go to the opera.";
|
||||||
|
|
||||||
|
OLMMessage *eMsg1 = [bobSession encryptMessage:msg1];
|
||||||
|
OLMMessage *eMsg2 = [bobSession encryptMessage:msg2];
|
||||||
|
OLMMessage *eMsg3 = [bobSession encryptMessage:msg3];
|
||||||
|
|
||||||
|
NSString *dMsg1 = [aliceSession decryptMessage:eMsg1];
|
||||||
|
NSString *dMsg2 = [aliceSession decryptMessage:eMsg2];
|
||||||
|
NSString *dMsg3 = [aliceSession decryptMessage:eMsg3];
|
||||||
|
XCTAssertEqualObjects(msg1, dMsg1);
|
||||||
|
XCTAssertEqualObjects(msg2, dMsg2);
|
||||||
|
XCTAssertEqualObjects(msg3, dMsg3);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) testAccountSerialization {
|
||||||
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
|
[bob generateOneTimeKeys:5];
|
||||||
|
NSDictionary *bobIdKeys = bob.identityKeys;
|
||||||
|
NSDictionary *bobOneTimeKeys = bob.oneTimeKeys;
|
||||||
|
|
||||||
|
NSData *bobData = [NSKeyedArchiver archivedDataWithRootObject:bob];
|
||||||
|
|
||||||
|
OLMAccount *bob2 = [NSKeyedUnarchiver unarchiveObjectWithData:bobData];
|
||||||
|
NSDictionary *bobIdKeys2 = bob2.identityKeys;
|
||||||
|
NSDictionary *bobOneTimeKeys2 = bob.oneTimeKeys;
|
||||||
|
|
||||||
|
XCTAssertEqualObjects(bobIdKeys, bobIdKeys2);
|
||||||
|
XCTAssertEqualObjects(bobOneTimeKeys, bobOneTimeKeys2);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) testSessionSerialization {
|
||||||
|
OLMAccount *alice = [[OLMAccount alloc] initNewAccount];
|
||||||
|
OLMAccount *bob = [[OLMAccount alloc] initNewAccount];
|
||||||
|
[bob generateOneTimeKeys:1];
|
||||||
|
NSDictionary *bobIdKeys = bob.identityKeys;
|
||||||
|
NSString *bobIdKey = bobIdKeys[@"curve25519"];
|
||||||
|
NSDictionary *bobOneTimeKeys = bob.oneTimeKeys;
|
||||||
|
NSParameterAssert(bobIdKey != nil);
|
||||||
|
NSParameterAssert(bobOneTimeKeys != nil);
|
||||||
|
__block NSString *bobOneTimeKey = nil;
|
||||||
|
NSDictionary *bobOtkCurve25519 = bobOneTimeKeys[@"curve25519"];
|
||||||
|
[bobOtkCurve25519 enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
|
||||||
|
bobOneTimeKey = obj;
|
||||||
|
}];
|
||||||
|
XCTAssert([bobOneTimeKey isKindOfClass:[NSString class]]);
|
||||||
|
|
||||||
|
OLMSession *aliceSession = [[OLMSession alloc] initOutboundSessionWithAccount:alice theirIdentityKey:bobIdKey theirOneTimeKey:bobOneTimeKey];
|
||||||
|
NSString *message = @"Hello I'm Alice!";
|
||||||
|
OLMMessage *aliceToBobMsg = [aliceSession encryptMessage:message];
|
||||||
|
|
||||||
|
OLMSession *bobSession = [[OLMSession alloc] initInboundSessionWithAccount:bob oneTimeKeyMessage:aliceToBobMsg.ciphertext];
|
||||||
|
NSString *plaintext = [bobSession decryptMessage:aliceToBobMsg];
|
||||||
|
XCTAssertEqualObjects(message, plaintext);
|
||||||
|
BOOL success = [bob removeOneTimeKeysForSession:bobSession];
|
||||||
|
XCTAssertTrue(success);
|
||||||
|
|
||||||
|
NSString *msg1 = @"Hello I'm Bob!";
|
||||||
|
NSString *msg2 = @"Isn't life grand?";
|
||||||
|
NSString *msg3 = @"Let's go to the opera.";
|
||||||
|
|
||||||
|
OLMMessage *eMsg1 = [bobSession encryptMessage:msg1];
|
||||||
|
OLMMessage *eMsg2 = [bobSession encryptMessage:msg2];
|
||||||
|
OLMMessage *eMsg3 = [bobSession encryptMessage:msg3];
|
||||||
|
|
||||||
|
NSData *aliceData = [NSKeyedArchiver archivedDataWithRootObject:aliceSession];
|
||||||
|
OLMSession *alice2 = [NSKeyedUnarchiver unarchiveObjectWithData:aliceData];
|
||||||
|
|
||||||
|
NSString *dMsg1 = [alice2 decryptMessage:eMsg1];
|
||||||
|
NSString *dMsg2 = [alice2 decryptMessage:eMsg2];
|
||||||
|
NSString *dMsg3 = [alice2 decryptMessage:eMsg3];
|
||||||
|
XCTAssertEqualObjects(msg1, dMsg1);
|
||||||
|
XCTAssertEqualObjects(msg2, dMsg2);
|
||||||
|
XCTAssertEqualObjects(msg3, dMsg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
D9401CDC1CBF10BD003DD078 /* OLMSession_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D9401CDB1CBF10BD003DD078 /* OLMSession_Private.h */; };
|
||||||
D976E4411CB852E000F5C124 /* OLMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D976E4401CB852E000F5C124 /* OLMKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
D976E4411CB852E000F5C124 /* OLMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = D976E4401CB852E000F5C124 /* OLMKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
D976E4481CB852E000F5C124 /* OLMKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D976E43E1CB852E000F5C124 /* OLMKit.framework */; };
|
D976E4481CB852E000F5C124 /* OLMKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D976E43E1CB852E000F5C124 /* OLMKit.framework */; };
|
||||||
D976E44D1CB852E000F5C124 /* OLMKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D976E44C1CB852E000F5C124 /* OLMKitTests.m */; };
|
D976E44D1CB852E000F5C124 /* OLMKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D976E44C1CB852E000F5C124 /* OLMKitTests.m */; };
|
||||||
|
@ -37,6 +38,7 @@
|
||||||
0A0809C67039D4BDCE9CE9AF /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
|
0A0809C67039D4BDCE9CE9AF /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
235C5A0B708438C11BCE552C /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
235C5A0B708438C11BCE552C /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
81B8A7B31F3BA6548ACC45DE /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
|
81B8A7B31F3BA6548ACC45DE /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
D9401CDB1CBF10BD003DD078 /* OLMSession_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OLMSession_Private.h; sourceTree = "<group>"; };
|
||||||
D976E43E1CB852E000F5C124 /* OLMKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OLMKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
D976E43E1CB852E000F5C124 /* OLMKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OLMKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
D976E4401CB852E000F5C124 /* OLMKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OLMKit.h; sourceTree = "<group>"; };
|
D976E4401CB852E000F5C124 /* OLMKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OLMKit.h; sourceTree = "<group>"; };
|
||||||
D976E4421CB852E000F5C124 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
D976E4421CB852E000F5C124 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
@ -115,6 +117,7 @@
|
||||||
D976E4671CB8696100F5C124 /* OLMAccount_Private.h */,
|
D976E4671CB8696100F5C124 /* OLMAccount_Private.h */,
|
||||||
D976E4561CB8536500F5C124 /* OLMAccount.m */,
|
D976E4561CB8536500F5C124 /* OLMAccount.m */,
|
||||||
D976E4591CB8538300F5C124 /* OLMSession.h */,
|
D976E4591CB8538300F5C124 /* OLMSession.h */,
|
||||||
|
D9401CDB1CBF10BD003DD078 /* OLMSession_Private.h */,
|
||||||
D976E45A1CB8538300F5C124 /* OLMSession.m */,
|
D976E45A1CB8538300F5C124 /* OLMSession.m */,
|
||||||
D976E45D1CB8538E00F5C124 /* OLMUtility.h */,
|
D976E45D1CB8538E00F5C124 /* OLMUtility.h */,
|
||||||
D976E45E1CB8538E00F5C124 /* OLMUtility.m */,
|
D976E45E1CB8538E00F5C124 /* OLMUtility.m */,
|
||||||
|
@ -139,6 +142,7 @@
|
||||||
isa = PBXHeadersBuildPhase;
|
isa = PBXHeadersBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
D9401CDC1CBF10BD003DD078 /* OLMSession_Private.h in Headers */,
|
||||||
D976E45B1CB8538300F5C124 /* OLMSession.h in Headers */,
|
D976E45B1CB8538300F5C124 /* OLMSession.h in Headers */,
|
||||||
D976E4681CB8787D00F5C124 /* OLMAccount_Private.h in Headers */,
|
D976E4681CB8787D00F5C124 /* OLMAccount_Private.h in Headers */,
|
||||||
D976E4651CB8674900F5C124 /* OLMMessage.h in Headers */,
|
D976E4651CB8674900F5C124 /* OLMMessage.h in Headers */,
|
||||||
|
|
Loading…
Reference in a new issue