Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Themis iOS and BoringSSL: Objective-C Implementation #336

Closed
CodeTeamLabs opened this issue Nov 11, 2018 · 20 comments
Closed

Themis iOS and BoringSSL: Objective-C Implementation #336

CodeTeamLabs opened this issue Nov 11, 2018 · 20 comments
Assignees
Labels
O-iOS 📱 Operating system: iOS question

Comments

@CodeTeamLabs
Copy link

CodeTeamLabs commented Nov 11, 2018

I have: implemented in viewDidLoad the keyGenerator:

@property (nonatomic, strong) NSData *privateKey;
@property (nonatomic, strong) NSData *publicKey;
 TSKeyGen * keygenRSA = [[TSKeyGen alloc] initWithAlgorithm:TSKeyGenAsymmetricAlgorithmRSA];
    
    if (!keygenRSA) {
        NSLog(@"%s Error occured while initialising object keygenRSA", sel_getName(_cmd));
        return;
    }
    _privateKey = keygenRSA.privateKey;
    _publicKey = keygenRSA.publicKey;

    NSLog(@"%@", keygenRSA.privateKey);

I see the NSLog with this error ... where I wrong?

/Pods/themis/src/soter/openssl/soter_rsa_key_pair_gen.c:65 - error: 1 <= EVP_PKEY_CTX_ctrl(ctx->pkey_ctx, -1, -1, EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP, 0, pub_exp)
/Users/fabiofloris/Desktop/Ium/Pods/themis/src/soter/openssl/soter_rsa_key_pair_gen.c:46 - error: soter_rsa_key_pair_gen_init(ctx, key_length)==SOTER_SUCCESS
/Users/fabiofloris/Desktop/Ium/Pods/themis/src/soter/openssl/soter_rsa_key_pair_gen.c:94 - error: ctx
/Users/fabiofloris/Desktop/Ium/Pods/themis/src/soter/openssl/soter_rsa_key_pair_gen.c:94 - error: ctx
/Users/fabiofloris/Desktop/Ium/Pods/themis/src/soter/openssl/soter_rsa_key_pair_gen.c:86 - error: ctx
2018-11-11 21:37:24.305916+0100 Ium[1663:420689] viewDidLoad Error occured while initialising object keygenRSA

Then I wanted to ask another question ... Are these two specific strings

NSString * serverPublicKeyString = @"VUVDMgAAAC2ELbj5Aue5xjiJWW3P2KNrBX+HkaeJAb+Z4MrK0cWZlAfpBUql";
NSString * clientPrivateKeyString = @"UkVDMgAAAC13PCVZAKOczZXUpvkhsC+xvwWnv3CLmlG0Wzy8ZBMnT+2yx/dg";

referring to something in particular? or are the values of keygenRSA.privateKey / keygenRSA.publicKey ???

Environment info

OS: iOS 12

Installation way:
install with pod 'Themis'

@vixentael vixentael self-assigned this Nov 11, 2018
@vixentael
Copy link
Contributor

@CodeTeamLabs you are doing everything right.

I've prepared small test project with themis 0.10.1 and generating keys in viewDidLoad, and tested it on both simulator and device (iOS11 & iOS12.1)

  1. Could you please download, try and let me know if it works?
    https://www.dropbox.com/s/6atin3xw5eiou14/themis-issue-336-example.zip?dl=0

  2. Moreover, there is large example project for ObjC in docs/examples/objc, have you tried it?

  3. Can you share your Podfile.lock with me please? If your app is using OpenSSL pod separately, I'm wondering which OpenSSL version do you use, theoretically it might be something related to exact OpenSSL version.

@CodeTeamLabs
Copy link
Author

CodeTeamLabs commented Nov 11, 2018

@vixentael Hi and thx!

in my podFile I have download Themis with : pod 'Themis' no with pod 'themis', '0.10.1'...

  1. i have download your test project from dropbox... With your project I no have an error in NSLog... In my project instead I have an error in NSLog.

2.I have seen the documentation with the examples but I could not understand well when we use

NSString * serverPublicKeyString = @ "VUVDMgAAAC2ELbj5Aue5xjiJWW3P2KNrBX + HkaeJAb + Z4MrK0cWZlAfpBUql";
NSString * clientPrivateKeyString = @ "UkVDMgAAAC13PCVZAKOczZXUpvkhsC + xvwWnv3CLmlG0Wzy8ZBMnT + 2yx / dg";

You can help me to understand ... I currently need to encrypt messages from a chat within my application and decrypt them for the recipient ...

I want to specify that I use Firebase Real Time Database.

  1. Sure... this is the link for download a podFile.lock https://ufile.io/vj6dr

@vixentael
Copy link
Contributor

vixentael commented Nov 11, 2018

Regarding keys:
encryption keys are binary data, but if you want to transfer them to another side (let say your backend), you should encode keys (for example, encode to base64).

In our examples we're using base64 encoded keys.

Generate keys and encode to base64:

NSData * publicKey = keygenEC.publicKey;
NSString *base64PublicKey = [publicKey base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];

Decode keys from base64:

NSString * keybase64 = @"UkVDMgAAAC1FsVa6AMGljYqtNWQ+7r4RjXTabLZxZ/14EXmi6ec2e1vrCmyR";
NSData * key = [[NSData alloc] initWithBase64EncodedString:keybase64 options:NSDataBase64DecodingIgnoreUnknownCharacters];

Server public and client private keys

Secure Message helps to encrypt and sign data.

We always show example when one party ("client") encrypts data for other party ("server"). In this case, each party generates a key pair: private and public keys, and exchange their public keys. Exchanged keys are usually encoded in base64.

To encrypt data on "client" side you use client's private key and server's public key:

// init keygen
TSKeyGen * clientKeyGen = [[TSKeyGen alloc] initWithAlgorithm:TSKeyGenAsymmetricAlgorithmRSA];

// send public key to server somehow
NSString * clientPublicKeyBase64 = [clientKeyGen.publicKey base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
[self sendPublicKeyToServer:clientPublicKeyBase64];

...

// get this key from exchange with server side, usually via network request
NSString * serverPublicKeyString = [self getKeyInBase64FromServer];
NSData * serverPublicKey = [[NSData alloc] initWithBase64EncodedString:serverPublicKeyString
                                                               options:NSDataBase64DecodingIgnoreUnknownCharacters];

TSMessage * encrypter = [[TSMessage alloc] initInEncryptModeWithPrivateKey:clientKeyGen.privateKey peerPublicKey:serverPublicKey];

// encrypt data
NSString * dataFromClient = @"client data";
NSError * e;
NSData * encryptedMessage = [encrypter wrapData:[dataFromClient dataUsingEncoding:NSUTF8StringEncoding] error:&e];

// send encryptedMessage to server-side

Server-side receives encrypted data from client and decrypts it using own private key and client's public key:

// init keygen
TSKeyGen * serverKeyGen = [[TSKeyGen alloc] initWithAlgorithm:TSKeyGenAsymmetricAlgorithmRSA];

// send public key to client somehow
NSString * serverPublicKeyBase64 = [serverKeyGen.publicKey base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
[self sendPublicKeyToClient:serverPublicKeyBase64];

...

// get this key from exchange with client side, usually via network request
NSString * clientPublicKeyString = [self getKeyInBase64FromClient];
NSData * clientPublicKey = [[NSData alloc] initWithBase64EncodedString:clientPublicKeyString
                                                               options:NSDataBase64DecodingIgnoreUnknownCharacters];

...

// get encrypted message from server
NSData *encryptedMessage = [self getDataFromClient];

// decrypt data
TSMessage * decrypter = [[TSMessage alloc] initInEncryptModeWithPrivateKey:serverKeyGen.privateKey peerPublicKey:clientPublicKey];

NSError * e;
NSData * decryptedMessage = [decrypter unwrapData:encryptedMessage error:&e];
NSString * resultString = [[NSString alloc] initWithData:decryptedMessage encoding:NSUTF8StringEncoding];

@vixentael
Copy link
Contributor

@CodeTeamLabs

Thank you, from Podfile.lock I see that you're using BoringSSL (probably Firebase has BoringSSL as dependency).

Can you try to deintegrate pods and to link to Themis with BoringSSL?

pod 'themis/themis-boringssl'

Let's test if this is an issue of using both OpenSSL and BoringSSL in one project 🤔

If this won't help, could you please send your example project to our email dev@cossacklabs.com? I'll try to debug and to check other dependencies.

@CodeTeamLabs
Copy link
Author

CodeTeamLabs commented Nov 11, 2018

@vixentael ok but NSString * base64key = @"UkVDMgAAAC13PCVZAKOczZXUpvkhsC+xvwWnv3CLmlG0Wzy8ZBMnT+2yx/dg";
is equal to keygenRSA.privateKey ???

Now I have insert pod 'themis/themis-boringssl' in my podFile but when run the App show 10 error like this Implicit declaration of function 'EVP_PKEY_CTX_ctrl' is invalid in C99

@vixentael
Copy link
Contributor

Keys are generated as binary (NSData), to transfer them via network or to show in docs, we encode binary to base64.

From NSData to base64:

NSData * publicKey = keygenEC.publicKey;
NSString *base64PublicKey = [publicKey base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];

From base64 to NSData:

NSString * keybase64 = @"UkVDMgAAAC1FsVa6AMGljYqtNWQ+7r4RjXTabLZxZ/14EXmi6ec2e1vrCmyR";
NSData * key = [[NSData alloc] initWithBase64EncodedString:keybase64 options:NSDataBase64DecodingIgnoreUnknownCharacters];

So, yes, technically, when docs says "clientPrivateKeyString" it means that client generated this key using keygenRSA.privateKey.

@vixentael
Copy link
Contributor

App show 10 error like this Implicit declaration of function 'EVP_PKEY_CTX_ctrl' is invalid in C99

Deintegrating pod, removing DerivedData and cleaning the project should help.

@vixentael
Copy link
Contributor

DerivedData is a temp/cache folder where Xcode stores project cached files. How to delete derived data.

Usually, removing pod, removing DerivedData, adding pod back and cleaning project helps to solve temporary issues.

@CodeTeamLabs
Copy link
Author

CodeTeamLabs commented Nov 12, 2018

ok ... now work ... I see the key in NSLog and no have error... now I just need to try playing with themis to learn and manage with firebase: D .. I hope I understand ... I'm sorry for my stupid questions.. now work only pod 'themis/themis-boringssl' without pod 'themis' :D

@vixentael
Copy link
Contributor

Yay, great that it helped! 👍

I have a separate example with Themis and Firebase that I used for my workshop.

https://github.com/vixentael/zka-example

It's a simple Notes application that uses Firebase database as storage. First, students were encrypting their notes and storing them in Firebase. We used Themis Secure Cell to encrypt notes.

Then, students were sharing encryption keys with each other to decrypt their friends' notes. Sharing encryption keys in plaintext is always a bad idea, so before sharing they encrypted their keys using Themis Secure Message (using own private key and friend's public key), so only their friend could decrypt their notes.

Although it's not a chat, but you might find this example useful for your case.

@CodeTeamLabs
Copy link
Author

I follow the Themis/Firebase tutorial in your documentation and I read this...

This example has many security flaws, especially in storing secret and public keys. Please don't use it as production-ready system. It's just an illustration of ZKA approach.

Of course, Firebase configuration should be changed: use private database, do not publish credentials (API keys).

can I ask what you mean by this message? Should I save the keys in a keyring such as a third-party library like SSKaychain?

@vixentael
Copy link
Contributor

Block "Next steps" has numerous suggestions how to improve security, including key management.

Should I save the keys in a keyring such as a third-party library like SSKaychain?

Yes, it's important to store encryption keys in Keychain. You might use native Keychain API or external library for that.

@CodeTeamLabs
Copy link
Author

Perfect @vixentael ...thanks you have been very kind to me ... Thanks again ... if I have 'other problems I will open a new post: D

@CodeTeamLabs
Copy link
Author

CodeTeamLabs commented Nov 12, 2018

@vixentael last question! :D ... sendPublicKeyToServer:.. did you mean?
The Public server/client key should save into the firebase Database?

Public key ---> save in Database
Private Key ---> save in keychain

right?

@vixentael
Copy link
Contributor

In short, yes.

In longterm, read about public key infrastructure (PKI) — architecture how to store and manage public keys, so attackers won’t easily change them.

@CodeTeamLabs
Copy link
Author

@vixentael in fact I was just reading the part where advice keybase.io ... and it 's here that I'm having a lot of difficulty to understand ... I would ask you 2,000 questions because I'm just exploding ... this part of the cryptography for me is completely new ... I can not make clear all the steps I have to do ... besides keybase.io I've never used it ... it's frustrating: D

@CodeTeamLabs
Copy link
Author

but Keybase.io is a chat??

@vixentael
Copy link
Contributor

@CodeTeamLabs this is an issue tracker for Themis, but not a public chat about cryptography and secure chats :)

I agree that cryptography is very exciting! I’d be glad to answer to your questions in my spare time, but it’s limited. If project you're working on has a commercial substance, you might want to talk to our sales team on security consulting.

@vixentael vixentael changed the title Objective C Implementation Themis iOS and BoringSSL: Objective-C Implementation Nov 12, 2018
@CodeTeamLabs
Copy link
Author

no will not be released by payment but the only monetization of the app will be the publicity within it ... But in case the keys are saved in the DB of Firebase why should I have risks ??? the keys are encrypted and therefore protected .. wrong?

@CodeTeamLabs
Copy link
Author

CodeTeamLabs commented Nov 14, 2018

@vixentael hi! I'm trying to figure out how I should use the key to save public keys? can you help me in this? What operations to do to save the public key in keybase as you suggested? Are there any documentations, examples or videos that can help me to understand? I'm looking on the net but I can not find something useful..

also I was thinking of one thing ... if I save the private keys in a keychain and the public keys on Firebase I would have security problems because the private keys can be easily used right?

Looking at the Firebase security text we have the ability to set rules for each json node so I was thinking ...

If I changed the rules of my node (eg userKeys) forbidding reading and writing to the world but only to the user who did you access my app by going through the Firebase authentication process? in this case the data of the Public Key would be visible only to those who have logged in ...

Could it be a valid solution for you?

I show you the setting of the Firebase rules to make you better understand what I mean

{
   "rule": {
     "user": {
       "$ uid": {
         ".write": "$ uid === auth.uid"
       }
     }
   }
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-iOS 📱 Operating system: iOS question
Projects
None yet
Development

No branches or pull requests

2 participants