Merge pull request #70 from matrix-org/manuroe/objc_pk

OLMKit: Add objc wrappers for pk encryption/decryption
This commit is contained in:
manuroe 2018-10-22 08:25:41 +02:00 committed by GitHub
commit 2784e49595
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 697 additions and 1 deletions

BIN
.DS_Store vendored

Binary file not shown.

View file

@ -114,7 +114,7 @@ size_t olm_clear_pk_decryption(
/** Get the number of bytes required to store an olm private key
*/
size_t olm_pk_private_key_length();
size_t olm_pk_private_key_length(void);
/** DEPRECATED: Use olm_pk_private_key_length()
*/

View file

@ -7,6 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
3244277D2175EF700023EDF1 /* OLMKitPkTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3244277C2175EF700023EDF1 /* OLMKitPkTests.m */; };
3274F6021D9A633A005282E4 /* OLMKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3274F5F81D9A633A005282E4 /* OLMKit.framework */; };
3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3274F6061D9A633A005282E4 /* OLMKitTests.m */; };
3274F6131D9A698E005282E4 /* OLMKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 3274F6121D9A698E005282E4 /* OLMKit.h */; };
@ -27,6 +28,7 @@
/* Begin PBXFileReference section */
1B226B371526F2782C9D6372 /* Pods-OLMKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OLMKit.release.xcconfig"; path = "Pods/Target Support Files/Pods-OLMKit/Pods-OLMKit.release.xcconfig"; sourceTree = "<group>"; };
3244277C2175EF700023EDF1 /* OLMKitPkTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OLMKitPkTests.m; sourceTree = "<group>"; };
3274F5F81D9A633A005282E4 /* OLMKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OLMKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3274F5FC1D9A633A005282E4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3274F6011D9A633A005282E4 /* OLMKitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OLMKitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@ -105,6 +107,7 @@
3274F6051D9A633A005282E4 /* OLMKitTests */ = {
isa = PBXGroup;
children = (
3244277C2175EF700023EDF1 /* OLMKitPkTests.m */,
3274F6061D9A633A005282E4 /* OLMKitTests.m */,
32A151301DABDD4300400192 /* OLMKitGroupTests.m */,
3274F6081D9A633A005282E4 /* Info.plist */,
@ -279,6 +282,7 @@
buildActionMask = 2147483647;
files = (
3274F6071D9A633A005282E4 /* OLMKitTests.m in Sources */,
3244277D2175EF700023EDF1 /* OLMKitPkTests.m in Sources */,
32A151311DABDD4300400192 /* OLMKitGroupTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View file

@ -193,6 +193,7 @@
}
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_account(_account, key.bytes, key.length, pickle.mutableBytes, pickle.length);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) {
const char *olm_error = olm_account_last_error(_account);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
@ -219,6 +220,7 @@
return nil;
}
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
return pickleString;
}

View file

@ -227,6 +227,7 @@
}
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_inbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) {
const char *olm_error = olm_inbound_group_session_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
@ -253,6 +254,7 @@
return nil;
}
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
return pickleString;
}

View file

@ -26,6 +26,8 @@
#import <OLMKit/OLMUtility.h>
#import <OLMKit/OLMInboundGroupSession.h>
#import <OLMKit/OLMOutboundGroupSession.h>
#import <OLMKit/OLMPkEncryption.h>
#import <OLMKit/OLMPkDecryption.h>
@interface OLMKit : NSObject

View file

@ -148,6 +148,7 @@
}
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_outbound_group_session(session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) {
const char *olm_error = olm_outbound_group_session_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
@ -174,6 +175,7 @@
return nil;
}
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
return pickleString;
}

View file

@ -0,0 +1,42 @@
/*
Copyright 2018 New Vector Ltd
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.0OLMPKEncryption
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 <Foundation/Foundation.h>
#import "OLMPkMessage.h"
NS_ASSUME_NONNULL_BEGIN
@interface OLMPkEncryption : NSObject
/**
Set the recipient's public key for encrypting to.
@param recipientKey the recipient's public key.
*/
- (void)setRecipientKey:(NSString*)recipientKey;
/**
Encrypt a plaintext for the recipient.
@param message the message to encrypt.
@param error the error if any.
@return the encrypted message.
*/
- (OLMPkMessage *)encryptMessage:(NSString*)message error:(NSError* _Nullable *)error;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,111 @@
/*
Copyright 2018 New Vector Ltd
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 "OLMPkEncryption.h"
#include "olm/olm.h"
#include "olm/pk.h"
#include "OLMUtility.h"
@interface OLMPkEncryption ()
{
OlmPkEncryption *session;
}
@end
@implementation OLMPkEncryption
- (void)dealloc {
olm_clear_pk_encryption(session);
free(session);
}
- (instancetype)init {
self = [super init];
if (self) {
session = (OlmPkEncryption *)malloc(olm_pk_encryption_size());
olm_pk_encryption(session);
}
return self;
}
- (void)setRecipientKey:(NSString*)recipientKey {
NSData *recipientKeyData = [recipientKey dataUsingEncoding:NSUTF8StringEncoding];
olm_pk_encryption_set_recipient_key(session, recipientKeyData.bytes, recipientKeyData.length);
}
- (OLMPkMessage *)encryptMessage:(NSString *)message error:(NSError *__autoreleasing _Nullable *)error {
NSData *plaintextData = [message dataUsingEncoding:NSUTF8StringEncoding];
size_t randomLength = olm_pk_encrypt_random_length(session);
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
if (!random) {
return nil;
}
size_t ciphertextLength = olm_pk_ciphertext_length(session, plaintextData.length);
NSMutableData *ciphertext = [NSMutableData dataWithLength:ciphertextLength];
if (!ciphertext) {
return nil;
}
size_t macLength = olm_pk_mac_length(session);
NSMutableData *macData = [NSMutableData dataWithLength:macLength];
if (!ciphertext) {
return nil;
}
size_t ephemeralKeyLength = olm_pk_key_length();
NSMutableData *ephemeralKeyData = [NSMutableData dataWithLength:ephemeralKeyLength];
if (!ciphertext) {
return nil;
}
size_t result = olm_pk_encrypt(session,
plaintextData.bytes, plaintextData.length,
ciphertext.mutableBytes, ciphertext.length,
macData.mutableBytes, macLength,
ephemeralKeyData.mutableBytes, ephemeralKeyLength,
random.mutableBytes, randomLength);
if (result == olm_error()) {
const char *olm_error = olm_pk_encryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
NSLog(@"[OLMPkEncryption] encryptMessage: olm_group_encrypt error: %@", errorString);
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_group_encrypt error: %@", errorString]
}];
}
return nil;
}
OLMPkMessage *encryptedMessage = [[OLMPkMessage alloc]
initWithCiphertext:[[NSString alloc] initWithData:ciphertext encoding:NSUTF8StringEncoding]
mac:[[NSString alloc] initWithData:macData encoding:NSUTF8StringEncoding]
ephemeralKey:[[NSString alloc] initWithData:ephemeralKeyData encoding:NSUTF8StringEncoding]];
return encryptedMessage;
}
@end

View file

@ -0,0 +1,64 @@
/*
Copyright 2018 New Vector Ltd
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 <Foundation/Foundation.h>
#import "OLMSerializable.h"
#import "OLMPkMessage.h"
NS_ASSUME_NONNULL_BEGIN
@interface OLMPkDecryption : NSObject <OLMSerializable, NSSecureCoding>
/**
Initialise the key from the private part of a key as returned by `privateKey`.
Note that the pubkey is a base64 encoded string, but the private key is
an unencoded byte array.
@param privateKey the private key part.
@param error the error if any.
@return the associated public key.
*/
- (NSString *)setPrivateKey:(NSData*)privateKey error:(NSError* _Nullable *)error;
/**
Generate a new key to use for decrypting messages.
@param error the error if any.
@return the public part of the generated key.
*/
- (NSString *)generateKey:(NSError* _Nullable *)error;
/**
Get the private key.
@return the private key;
*/
- (NSData *)privateKey;
/**
Decrypt a ciphertext.
@param message the cipher message to decrypt.
@param error the error if any.
@return the decrypted message.
*/
- (NSString *)decryptMessage:(OLMPkMessage*)message error:(NSError* _Nullable *)error;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,295 @@
/*
Copyright 2018 New Vector Ltd
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 "OLMPkDecryption.h"
#include "olm/olm.h"
#include "olm/pk.h"
#include "OLMUtility.h"
@interface OLMPkDecryption ()
{
OlmPkDecryption *session;
}
@end
@implementation OLMPkDecryption
- (void)dealloc {
olm_clear_pk_decryption(session);
free(session);
}
- (instancetype)init {
self = [super init];
if (self) {
session = (OlmPkDecryption *)malloc(olm_pk_decryption_size());
olm_pk_decryption(session);
}
return self;
}
- (NSString *)setPrivateKey:(NSData *)privateKey error:(NSError *__autoreleasing _Nullable *)error {
size_t publicKeyLength = olm_pk_key_length();
NSMutableData *publicKeyData = [NSMutableData dataWithLength:publicKeyLength];
if (!publicKeyData) {
return nil;
}
size_t result = olm_pk_key_from_private(session,
publicKeyData.mutableBytes, publicKeyLength,
(void*)privateKey.bytes, privateKey.length);
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSLog(@"[OLMPkDecryption] setPrivateKey: olm_pk_key_from_private error: %s", olm_error);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_pk_key_from_private error: %@", errorString]
}];
}
return nil;
}
NSString *publicKey = [[NSString alloc] initWithData:publicKeyData encoding:NSUTF8StringEncoding];
return publicKey;
}
- (NSString *)generateKey:(NSError *__autoreleasing _Nullable *)error {
size_t randomLength = olm_pk_private_key_length();
NSMutableData *random = [OLMUtility randomBytesOfLength:randomLength];
if (!random) {
return nil;
}
size_t publicKeyLength = olm_pk_key_length();
NSMutableData *publicKeyData = [NSMutableData dataWithLength:publicKeyLength];
if (!publicKeyData) {
return nil;
}
size_t result = olm_pk_key_from_private(session,
publicKeyData.mutableBytes, publicKeyData.length,
random.mutableBytes, randomLength);
[random resetBytesInRange:NSMakeRange(0, randomLength)];
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSLog(@"[OLMPkDecryption] generateKey: olm_pk_key_from_private error: %s", olm_error);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_pk_key_from_private error: %@", errorString]
}];
}
return nil;
}
NSString *publicKey = [[NSString alloc] initWithData:publicKeyData encoding:NSUTF8StringEncoding];
return publicKey;
}
- (NSData *)privateKey {
size_t privateKeyLength = olm_pk_private_key_length();
NSMutableData *privateKeyData = [NSMutableData dataWithLength:privateKeyLength];
if (!privateKeyData) {
return nil;
}
size_t result = olm_pk_get_private_key(session,
privateKeyData.mutableBytes, privateKeyLength);
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSLog(@"[OLMPkDecryption] privateKey: olm_pk_get_private_key error: %s", olm_error);
return nil;
}
NSData *privateKey = [privateKeyData copy];
[privateKeyData resetBytesInRange:NSMakeRange(0, privateKeyData.length)];
return privateKey;
}
-(NSString *)decryptMessage:(OLMPkMessage *)message error:(NSError *__autoreleasing _Nullable *)error {
NSData *messageData = [message.ciphertext dataUsingEncoding:NSUTF8StringEncoding];
NSData *macData = [message.mac dataUsingEncoding:NSUTF8StringEncoding];
NSData *ephemeralKeyData = [message.ephemeralKey dataUsingEncoding:NSUTF8StringEncoding];
if (!messageData || !macData || !ephemeralKeyData) {
return nil;
}
NSMutableData *mutMessage = messageData.mutableCopy;
size_t maxPlaintextLength = olm_pk_max_plaintext_length(session, mutMessage.length);
if (maxPlaintextLength == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
NSLog(@"[OLMPkDecryption] decryptMessage: olm_pk_max_plaintext_length error: %@", errorString);
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_pk_max_plaintext_length error: %@", errorString]
}];
}
return nil;
}
mutMessage = messageData.mutableCopy;
NSMutableData *plaintextData = [NSMutableData dataWithLength:maxPlaintextLength];
size_t plaintextLength = olm_pk_decrypt(session,
ephemeralKeyData.bytes, ephemeralKeyData.length,
macData.bytes, macData.length,
mutMessage.mutableBytes, mutMessage.length,
plaintextData.mutableBytes, plaintextData.length);
if (plaintextLength == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
NSLog(@"[OLMPkDecryption] decryptMessage: olm_pk_decrypt error: %@", errorString);
if (error && olm_error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain
code:0
userInfo:@{
NSLocalizedDescriptionKey: errorString,
NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:@"olm_decrypt error: %@", errorString]
}];
}
return nil;
}
plaintextData.length = plaintextLength;
NSString *plaintext = [[NSString alloc] initWithData:plaintextData encoding:NSUTF8StringEncoding];
[plaintextData resetBytesInRange:NSMakeRange(0, plaintextData.length)];
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 *__autoreleasing *)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:OLMErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: @"Bad length."}];
}
return nil;
}
size_t ephemeralLength = olm_pk_key_length();
NSMutableData *ephemeralBuffer = [NSMutableData dataWithLength:ephemeralLength];
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_pk_decryption(session,
key.bytes, key.length,
pickle.mutableBytes, pickle.length,
ephemeralBuffer.mutableBytes, ephemeralLength);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
if (error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain 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_pk_decryption_length(session);
NSMutableData *pickled = [NSMutableData dataWithLength:length];
size_t result = olm_pickle_pk_decryption(session,
key.bytes, key.length,
pickled.mutableBytes, pickled.length);
if (result == olm_error()) {
const char *olm_error = olm_pk_decryption_last_error(session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
if (error && errorString) {
*error = [NSError errorWithDomain:OLMErrorDomain code:0 userInfo:@{NSLocalizedDescriptionKey: errorString}];
}
return nil;
}
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
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

View file

@ -0,0 +1,31 @@
/*
Copyright 2018 New Vector Ltd
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 <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface OLMPkMessage : NSObject
@property (nonatomic, copy, readonly) NSString *ciphertext;
@property (nonatomic, copy, readonly,) NSString *mac;
@property (nonatomic, copy, readonly) NSString *ephemeralKey;
- (instancetype) initWithCiphertext:(NSString*)ciphertext mac:(NSString*)mac ephemeralKey:(NSString*)ephemeralKey;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,32 @@
/*
Copyright 2018 New Vector Ltd
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 "OLMPkMessage.h"
@implementation OLMPkMessage
- (instancetype)initWithCiphertext:(NSString *)ciphertext mac:(NSString *)mac ephemeralKey:(NSString *)ephemeralKey {
self = [super init];
if (!self) {
return nil;
}
_ciphertext = [ciphertext copy];
_mac = [mac copy];
_ephemeralKey = [ephemeralKey copy];
return self;
}
@end

View file

@ -309,6 +309,7 @@
}
NSMutableData *pickle = [serializedData dataUsingEncoding:NSUTF8StringEncoding].mutableCopy;
size_t result = olm_unpickle_session(_session, key.bytes, key.length, pickle.mutableBytes, pickle.length);
[pickle resetBytesInRange:NSMakeRange(0, pickle.length)];
if (result == olm_error()) {
const char *olm_error = olm_session_last_error(_session);
NSString *errorString = [NSString stringWithUTF8String:olm_error];
@ -335,6 +336,7 @@
return nil;
}
NSString *pickleString = [[NSString alloc] initWithData:pickled encoding:NSUTF8StringEncoding];
[pickled resetBytesInRange:NSMakeRange(0, pickled.length)];
return pickleString;
}

View file

@ -0,0 +1,107 @@
/*
Copyright 2018 New Vector Ltd
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 <XCTest/XCTest.h>
#import <OLMKit/OLMKit.h>
/**
Tests are inspired from js tests.
*/
@interface OLMKitPkTests : XCTestCase {
OLMPkEncryption *encryption;
OLMPkDecryption *decryption;
}
@end
@implementation OLMKitPkTests
- (void)setUp {
encryption = [OLMPkEncryption new];
decryption = [OLMPkDecryption new];
}
- (void)tearDown {
encryption = nil;
decryption = nil;
}
- (void)testImportExportKeys {
UInt8 alicePrivateBytes[] = {
0x77, 0x07, 0x6D, 0x0A, 0x73, 0x18, 0xA5, 0x7D,
0x3C, 0x16, 0xC1, 0x72, 0x51, 0xB2, 0x66, 0x45,
0xDF, 0x4C, 0x2F, 0x87, 0xEB, 0xC0, 0x99, 0x2A,
0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
};
NSData *alicePrivate = [NSData dataWithBytes:alicePrivateBytes length:sizeof(alicePrivateBytes)];
NSError *error;
NSString *alicePublic = [decryption setPrivateKey:alicePrivate error:&error];
XCTAssertNil(error);
XCTAssertEqualObjects(alicePublic, @"hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo");
NSData *alicePrivateOut = decryption.privateKey;
XCTAssertNil(error);
XCTAssertEqualObjects(alicePrivateOut, alicePrivate);
}
- (void)testEncryptAndDecrypt {
NSString *pubKey = [decryption generateKey:nil];
NSLog(@"Ephemeral Key: %@", pubKey);
XCTAssertNotNil(pubKey);
NSString *TEST_TEXT = @"têst1";
NSError *error;
[encryption setRecipientKey:pubKey];
OLMPkMessage *message = [encryption encryptMessage:TEST_TEXT error:&error];
NSLog(@"message: %@ %@ %@", message.ciphertext, message.mac, message.ephemeralKey);
XCTAssertNil(error);
XCTAssertNotNil(message);
XCTAssertNotNil(message.ciphertext);
XCTAssertNotNil(message.mac);
XCTAssertNotNil(message.ephemeralKey);
NSString *decrypted = [decryption decryptMessage:message error:&error];
XCTAssertNil(error);
XCTAssertEqualObjects(decrypted, TEST_TEXT);
TEST_TEXT = @"hot beverage: ☕";
[encryption setRecipientKey:pubKey];
message = [encryption encryptMessage:TEST_TEXT error:&error];
decrypted = [decryption decryptMessage:message error:&error];
XCTAssertEqualObjects(decrypted, TEST_TEXT);
}
- (void)testOLMPkDecryptionSerialization {
NSString *TEST_TEXT = @"têst1";
NSString *pubKey = [decryption generateKey:nil];
[encryption setRecipientKey:pubKey];
OLMPkMessage *encrypted = [encryption encryptMessage:TEST_TEXT error:nil];
NSData *pickle = [NSKeyedArchiver archivedDataWithRootObject:decryption];
decryption = nil;
OLMPkDecryption *newDecryption = [NSKeyedUnarchiver unarchiveObjectWithData:pickle];
NSError *error;
NSString *decrypted = [newDecryption decryptMessage:encrypted error:&error];
XCTAssertEqualObjects(decrypted, TEST_TEXT);
}
@end