Creating an RSA private key in iOS - ios

I'm trying to rewrite some Java (Android) code in ObjC on the iPhone. The code will do a basic web service call and needs to set some headers with authentication information.
One part of that information is an encrypted hash of the data I am sending over.
The Java version calculates an SHA256 signature using an RSA private key that is generated on the phone. The private key is generated using a seed that I have available.
The (simplified) java code is as follows:
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
Signature sig = Signature.getInstance("SHA256WithRSAEncryption");
// I get the private key bytes from an outside source
EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
sig.initSign(keyFactory.generatePrivate(privateKeySpec));
sig.update(/* insert my data here */);
return sig.sign();
Now I'm trying to recreate this in iOS and ObjC. Doing the SHA256 signature calculation is easy, but I don't see how to create a private RSA key easily. I would prefer to use the built-in API's if there are any available, but if I must use a third party library like OpenSSL then I can live with that as well.

Most people (citation needed) elect to go with the third party OpenSSL library, not only because rolling your own crypto is hard, but also because their is a good chance you'll create bad crypto if you're not already experienced with it.
That said, nothing prevents you from writing your own SHA256 hash, in straight C or C++ if you like, although I think you'll find your PRNG options lacking and find yourself spending altogether way too much time on entropy pools and the like.
If you do come across a good SHA256 primitive without all the extra baggage of OpenSSL, I'd love to learn about it too! But so far I haven't seen one.

Related

Where should I store my API key in IOS app [duplicate]

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

Swift protect hard coded string for privacy [duplicate]

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

Ruby way to Generate HMAC-SHA256 signature for Amazon Product Advertising API

I have been working with Amazon's Producct Advertising API for a while now. I was successful in integrating all features provided by this in my app. But the only one remaining is the Cart Create operation which requires an HMAC-SHA256 signature to be generated and used for all the cart actions to be performed. I have gone through the docs and all the threads available regarding this issue but nothing seems to me work in my case.
I have even gone through multiple gems but no one provides a solution for this. I am currently using Vacuum gem with Ruby 2.2.3, Rails 4.2.5.
Question: I mainly need to understand how to generate this HMAC signature so that I could use it in all cart related actions.
The HMAC signature can be created using Ruby's OpenSSL support. This must then be Base64 encoded so that it can be sent over the wire. The basic premise is as follows
require 'openssl'
require 'Base64'
key = "your-secret-access-key"
data = "data you want signed"
signature = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), key, data)).strip()
Adapting the above to your needs, the key is your AWS Access Key, and data is the string representation of the request you want to send, as described here.
How you construct the data string is implementation specific but a common approach is to build a canonical string from the actual request object (most commonly Net::HTTP:HTTPRequest). Hope this helps.

In iOS, how can I store a secret "key" that will allow me to communicate with my server?

I want to store a secret key ("abc123") that I will use in the header of my REST API requests. My server will check this secret key. If it matches "abc123", then allow the request to be made.
I'm thinking about a simple solution like:
let secret = "abc123"
But are there going to be any downfalls to this?
Crazy as it sounds, this is probably the best solution. Everything else is more complicated, but not much more secure. Any fancy obfuscation techniques you use are just going to be reverse engineered almost as quickly as they'll find this key. But this static key solution, while wildly insecure, is nearly as secure than the other solutions while imposing nearly no extra complexity. I love it.
It will be broken almost immediately, but so will all the other solutions. So keep it simple.
The one thing that you really want to do here is use HTTPS and pin your certificates. And I'd pick a long, random key that isn't a word. Ideally, it should be a completely random string of bytes, stored as raw values (not characters) so that it doesn't stand out so obviously in your binary. If you want to get crazy, apply a SHA256 to it before sending it (so the actual key never shows up in your binary). Again, this is trivial to break, but it's easy, and won't waste a lot of time developing.
It is unlikely that any effort longer than an hour will be worth the trouble to implement this feature. If you want lots more on the topic, see Secure https encryption for iPhone app to webpage and its links.
By hardcoding the string in your app, it's possible for attackers to decrypt your binary (via tools like dumpdecrypt) and get your string without much trouble (a simple hexdump would include any strings in your app).
There are a few workarounds for this. You could implement an endpoint on your REST API which returns your credentials, that you could then call on launch. Of course, this has its own non-trivial security concerns, and requires an extra HTTP call. I usually wouldn't do it this way.
Another option is to obfuscate the secret key somehow. By doing that, attackers won't be able to instantly recognize your key after decryption. cocoapods-keys is one option which uses this method.
There's no perfect solution here – the best you can do is make it as difficult as possible for an attacker to get a hold of your keys.
(Also, be sure to use HTTPS when sending requests, otherwise that's another good way to compromise your keys.)
While in-band tokens are commonly used for some schemes, you're probably eventually going to implement TLS to protect the network traffic and the tokens. This as Rob Napier mentions in another reply.
Using your own certificate chain here allows the use of existing TLS security and authentication mechanisms and the iOS keychain, and also gives you the option of revoking TLS credentials if (when?) that becomes necessary, and also allows the client to pin its connections to your servers and detect server spoofing if that becomes necessary.
Your own certificate authority and your own certificate chain is free, and your own certificates are — once you get the root certificate loaded into the client — are just as secure as commercially-purchased certificates.
In short, this certificate-based approach combines encryption and authentication, using the existing TLS mechanisms.
It looks like you are using access tokens. I would use Keychain for access tokens. For Client IDs, I would just keep them as a variable because client ids don't change while access tokens change per user, or even per refresh token and keychain is a safe place to store user credentials.
I have used the PFConfig object (a dictionary) that allows you to retrieve in your app values of variables stored as Server environment parameters.
Similar to the environment variables that can be retrieved using ENV in web sites server side programming like Ruby or PHP.
In my opinion this is about as secure as using Environment variables in Ruby or similar.
PFConfig.getConfigInBackgroundWithBlock{
(config: PFConfig?, error: NSError?) -> Void in
if error == nil {
if let mySecret = config["mySecret"] as? String {
// myFunction(mySecret)
}
}

Authenticating a Game Center player on an online game's servers

"Clash of Clans" uses Game Center to authenticate and link a player with an existing remotely stored game state.
From what I can see, a game is only provided a player identifier on client side. Is there a supported technique to securely authenticate a user instead of sending just the identifier (which is an equivalent of authenticating with just a username)?
Since I asked the question, Apple has introduced a new API and the answer is available on: Setting up third-party server to interact with Game Center (thank you, user2949759) and on a few other places.
Specifically, since iOS 7 (Apple documentation on Wayback Machine):
-[GKLocalPlayer generateIdentityVerificationSignatureWithCompletionHandler:]
Generates a signature that allows a third party server to authenticate the local player.
The relevant callback block's arguments include NSURL *publicKeyUrl, NSData *signature, NSData *salt, uint64_t timestamp. These, along with player's playerID and bundleID, should be shipped off to the server as the 'login information'.
At this point, one should, server-side, use publicKeyURL to obtain the public key
serverside, verify that this public key has been signed by Apple
serverside, concatenate UTF-8-encoded playerID, bundleID, big-endian uint64 timestamp, and verbatim salt
serverside, generate SHA-256 of the above to produce digest
serverside, verify the signature that was shipped to the server is correct, using the public key downloaded earlier, the signature and the digest
There's an example in pseudo-PHP, an example of how one would implement this in Objective-C (which makes little sense to use verbatim), a Go implementation, a Ruby implementation and there is an assortment of implementations in other languages on that same question.
Unsurprisingly, the implementation in Go seems particularly readable, but it doesn't verify that the public key was issued by Apple. Linked Ruby implementation contains a rather clear example of how to do that.
Since you are authenticating with your own server, this is something between your client and your server to implement. Game Center won't be able to help you.
A simple idea would be to calculate a hash from the playerID using a function that only you know, and have the server compare it to what the client is sending.
Avoid generating a random key when your client runs for the first time, because when the client is re-installed, the user will be locked out.

Resources