I am working on a project and we need to encrypt some user credentials (username, password, userId, ect.) to pass to our server. We have decided to use AES256 in order to achieve this. Doing some research on this subject it was hard to avoid noticing a project out there, RNCryptor that claims to be an easy-to-use solution to this problem.
So I included the framework into my project and soon realized it was not as straight forward as I thought. I was hoping for a solution to where I could encrypt my credential strings by simply - (1) derive a key that I would like to encrypt my stringed credentials with, (2) pass the key and my string into the appropriate RNCryptor's method, (3) retrieve my encrypted string back from said method.
This would be too good to be true however.
The reality of RNCryptor is that it has methods like this:
[RNEncryptor encryptData:someData
withSettings:kRNCryptorAES256Settings
password:someString
error:&someError];
This is confusing because of the terminology.
WHAT IS PASSWORD?
This is never explained. A password for what? Is this for a user password I want to encrypt, the password key that I want to encrypt with, or the password to login to my computer (sarcasm).
ENCRYPT DATA?
Is this a UTF8 encoded string of what the user credentials that I want to encrypt? That is my best guess but again, not explained in the RNCryptor Github "documentation".
password is used to generate the encryption key, it is an NSString the data is encrypted with. encryptData is the data to encrypt and is an NSData.
Encryption works with data, that an array of 8-bit bytes. You need to convert whatever you have to an NSData. For an NSString there is the method:
NSData *dataToBeEncrypted = [myString dataUsingEncoding:NSUTF8StringEncoding];
and
NSString *myString = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];
Additionally it requires an encryption key, RNCryptor takes an NSString and derives an encryption key from it.
There are of course options and while most of these handles internally by RNCryptor there still some available to the developer using it.
There two main versions with more options, you are probably best off using the password version.
One taking a NSString password:
+ (NSData *)encryptData:(NSData *)data withSettings:(RNCryptorSettings)settings password:(NSString *)password error:(NSError **)error;
A second taking an NSData encryption key as well as a NSData authentication key.
+ (NSData *)encryptData:(NSData *)data withSettings:(RNCryptorSettings)settings encryptionKey:(NSData *)encryptionKey HMACKey:(NSData *)HMACKey error:(NSError **)error;
RNCryptor is you best choice, it handles key derivation from a password, a random IV, authentication of the encrypted data and padding.
Related
my iOS app is connected to a web service. App is written in objective-c. Server sending a string that has encrypted using AES encryption using a password string and IV string. I want to decrypt that string in this app side. How can I do it?
Please help me. Thanks
UPDATE
This is how I decrypt my string
NSData *url1Data = [strEncrypted dataUsingEncoding:NSUTF8StringEncoding];
NSData *url1DataDecrypt = [[StringEncryption alloc] decrypt:url1Data key:Hashkey iv:iv];
NSString * decryptedText = [[NSString alloc] initWithData:url1DataDecrypt encoding:NSUTF8StringEncoding];
You need generate Public key certificate & distribute to both side user FBEncrypt Library to decrypt data using AES Algorithm it is secure & Easy to implement FBEncrypt Library.
I am using Evernote SDK for iOS and I am saving the authentication token when the user has authorized access.
Once the user installs my application on a different device, I want to use that token to reauthenticate automatically, but it looks like SDK doesn't support that. Is there a way to do that?
I had the same issue last week, and their SDK indeed doesn't support it out-of-the-box, but after some research I found a solution that works perfectly. This solution mimics a valid authentication flow.
A little background:
When the ENSession class initializes, it retrieves the credentials that are saved on the keychain (unless [[ENSession sharedSession] unauthenticate] was called earlier). The problem is that the keychain is empty when using a different device, so our goal is to add a valid ENCredentials instance to the ENCredentialStore.
Solution:
Add the following imports to your code: ENCredentials.h and ENCredentialStore.h. We will need them later.
Initialize the ENSession like you already do, using setSharedSessionConsumerKey:(NSString *)key consumerSecret:(NSString *)secret optionalHost:(NSString *)host.
In order to create a valid ENCredentials object, we need to provide the following objects:
NSString * host
NSString * edamUserId
NSString * noteStoreUrl
NSString * webApiUrlPrefix
NSString * authenticationToken
NSDate * expirationDate
The host is always www.evernote.com (as defined in ENSession under ENSessionBootstrapServerBaseURLStringUS).
edamUserId is the user id you received when you got the original token. Same for the expirationDate. If you are not sure how to get them then you should use [[ENSession sharedSession].userStore getUserWithSuccess:^(EDAMUser *user) once authenticated.
So the only objects that are actually missing are noteStoreUrl and webApiUrlPrefix. Their format is always:
noteStoreUrl: https://www.evernote.com/shard/edam_shard/notestore
webApiUrlPrefix: https://www.evernote.com/shard/edam_shard/
Luckily, your token already contains edam_shared (value of S=, see this):
#"S=s161:U=5ce3f20:E=1561182201b:C=24eb9d000f8:P=285:A=app:V=2:H=e8ebf56eac26aaacdef2f3caed0bc309"
If you extract s161 and put it in the URLs above it will work (I am sure you know how to extract that, but let me know if you're having problems).
Now we are ready to authenticate using the token. First, expose the necessary functions from ENSession using a category:
#interface ENSession(Authentication)
- (void)startup;
- (void)addCredentials:(ENCredentials *)credentials;
#end
And authenticate using the token:
ENCredentials *credentials = [[ENCredentials alloc] initWithHost:ENSessionBootstrapServerBaseURLStringUS edamUserId:userId noteStoreUrl:noteStoreUrl webApiUrlPrefix:webApiUrlPrefix authenticationToken:token expirationDate:expirationDate];
[[ENSession sharedSession] addCredentials:credentials];
[[ENSession sharedSession] startup];
The last line is important in order to refresh the ENSession and retrieve the new stored credentials.
Now you are authenticated and ready to query the SDK. Good luck.
I'm creating an iPhone Objective-C app that uses secure communication between a server and a client. The protocol I want to follow goes like this:
The client is compiled and distributed with the Server's Public RSA key (hardcoded). Let's call this Kspub. (For Key Server Public)
The client generates an random AES key. Let's call this key Kcaes (for Key Client AES)
The client encrypts Kcaes using Kspub, and produces the encrypted text: Kspub(Kcaes)
The client sends Kspub(Kcaes) to the server.
The server decrypts Kspub(Kcaes) using the server's private key, Kspri. This recovers Kcaes. Now the client and the server both share a common AES key, Kcaes.
To verify this, the server encrypts Kcaes USING Kcaes. This produces encrypted text Kcaes(Kcaes).
The server sends Kcaes(Kcaes) to the client.
The client decrypts Kcaes(Kcaes) using the Kcaes key. This produces Kcaes. If this matches the original Kcaes, then the client knows it has established a secure connection.
The client and server can now securely exchange information using symmetrical key Kcaes.
I have already implemented server-side and client-side key generation, encryption, and decryption methods. Currently, keypairs generated on the iPhone are being stored in it's keychain. Here's the issue:
I cannot seem to find a method in Apple's Keychain or Security API to import a Public RSA key from a text file. How can I import a key through a text file and store it in a SecKeyRef object?
Thanks!
You do this via SecItemAdd, passing:
A dictionary containing an item class key-value pair (Keychain Item Class Keys and Values) and optional attribute key-value pairs (Attribute Item Keys and Values) specifying the item's attribute values.
OSStatus err = SecItemAdd((CFDictionaryRef)
[NSDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassKey, kSecClass,
kSecAttrKeyTypeRSA, kSecAttrKeyType,
keyTagUTF8, kSecAttrApplicationTag,
kSecAttrKeyClassPrivate, kSecAttrKeyClass,
keyData, kSecValueData,
nil],
NULL);
Ensure that the attributes to store and retrieve match exactly.
SecKeyCreateWithData will accept RSA data in PKCS#1 as well as the x509 public key format.
Because the question mentions a text as opposed to binary file I'll assume the public key is in the standard PEM format. First you'd strip the PEM headers and new lines:
NSMutableString *pemString = [textFileString mutableCopy];
[pemString replaceOccurrencesOfString:#"-----BEGIN PUBLIC KEY-----" withString:#"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [pemString length])];
[pemString replaceOccurrencesOfString:#"-----END PUBLIC KEY-----" withString:#"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [pemString length])];
[pemString replaceOccurrencesOfString:#"\n" withString:#"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [pemString length])];
Now you're left with a Base64 string which you can decode into binary data. I want to point out that Apple's native Base64 methods are not tolerant of padding issues and other standards.
CFDataRef data = (__bridge CFDataRef) [NSData dataWithBase64EncodedString... // Your preferred base64 method here
Now you can get the SecKeyRef via SecKeyCreateWithData.
if (data)
{
CFMutableDictionaryRef dictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 3, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
if (dictionary)
{
CFDictionarySetValue(dictionary, kSecAttrKeyClass, kSecAttrKeyClassPublic);
CFDictionarySetValue(dictionary, kSecAttrIsPermanent, kCFBooleanFalse);
CFDictionarySetValue(dictionary, kSecAttrKeyType, kSecAttrKeyTypeRSA);
CFErrorRef error = NULL;
SecKeyRef publicKey = SecKeyCreateWithData(data, dictionary, &error);
if (publicKey)
{
if (error)
{
CFShow(error);
CFRelease(error);
}
//...
CFRelease(publicKey);
}
CFRelease(dictionary);
}
}
From here you can either keep the reference around, or decide to save it in the keychain via SecItemAdd etc.
In my application I use online payment, for that i used PaySabar device (audio jack device) which reads magstrip data on credit card swipe.
I got credit data in encrypted format, all track1, track2 data are correct and perfect, but how to i send that data to USAePAY server. Please help.
I believe USAePay requires the encrypted data to be:
Encrypted with their public key
Formatted in a specific manner
Passed in magstripe or credit card number field
Because you are using their PaySaber hardware, see below for step 3.
USAePay Wiki - End To End Encryption:
If you are using idynamo library, here is what you need to do:
NSString *responseString = [mtSCRALib getResponseData];
NSData *responseData = [responseString dataUsingEncoding:NSASCIIStringEncoding];
NSString *encodedString = [NSString stringWithFormat:#"enc://%#", [^] [responseData base64Encoding]];
and then send encodedString to the gateway as MagStripe.
You will need to integrate your application with one of their transaction interfaces. You will also need a developer account for testing transaction responses.
They have a wide array of different integration solutions and source code examples to use, including an iOS library.
http://wiki.usaepay.com/developer/Support
i have a question about saving Keys within iOS applications.
Is there any way to save the public/private Key of an RSA-certificate within an app, not to save/store this in the iOS keychain.
Maybe someone tried this out before?
I found something similar with username and password. Its called "Keychainwrapper". There the app saves the login credentials within the app. Does this work for me with private/public keys?
Hopefully someone can help me.
Best regards,
Andi
Since you have to store only public and private key and not the whole certificate, can not use the internal keychain and the keys are generated on the device it would be sufficient if you save your public and private key in the NSUserDefaults:
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
//saving the data
[prefs setObject"<your public key data>" forKey:#"PublicKey"];
[prefs setObject"<your private key data>" forKey:#"PrivateKey"];
//reading the data
NSString *publicKey = [prefs stringForKey:#"PublicKey"];
NSString *privateKey = [prefs stringForKey:#"PrivateKey"];
This store is rather insecure, so I would suggest that you encrypt your data like this: iOS 5: Data encryption AES-256 EncryptWithKey: not found. Be aware, that symmetric encryption is not secure if you store the key in your application! You should use some user input to generate the key.
Hope this helps.