How to store encrypted data by SecureEnclave persistently - ios

I have heard about Secure Enclave. In which after key generation, data can be encrypted by SecKeyCreateEncryptedData method.
My Use Case: I want to store some sensitive data persistently. For security purposes, I have encrypted data by above method using Secure Enclave.
Now just want to know is it a legal way to store encrypted data in NSUserDefaults or Keychain. or there is something else that should be done.
Any help would be much appreciated!

Since the data is encrypted you can store it anyway you want. Without the key inside the Secure Enclave the data is worthless.
There are several approaches you can go for: save it to UserDefaults, create a JSON inside documents directory etc.
Let's assume you want to save it to UserDefaults then have a look at this link:
How can I use UserDefaults in Swift?
Valuable article about secure enclave and cryptokit:
https://www.andyibanez.com/posts/cryptokit-secure-enclave/

Related

Best way to store OAuth token iOS?

I am writing an iOS app that uses Twitch.tv's API to allow my app to access their users content. They use the OAuth 2.0 protocol for authentication. I need to use this access token every time I make a request to access a users info.
My question is where should I store it?
Should I make a class that has it as a property? In that class I could also store my Redirect URI and Client_ID to keep things in one place.
I thought about NSUserDefaults, but I read it's not very secure.
What is the best design pattern for this approach on iOS?
Thanks.
The way your question is worded you seem to be confusing the use of the word store to mean two entirely different things. If you use NSUSerDefaults then the token would be stored to file and would persist if the app is killed. If you make it a property of a class it is being temporarily stored in memory and would not persist if the app is killed. Your question is therefore asking should I use Apples or Oranges.
If you need persistent storage for sensitive data then you should not use NSUserDefaults, instead use the iOS keychain.Use of the keychain is a bit too lengthy to describe here.
The keychain is encrypted but only using the user's 4 digit pin code, which could potentially be brute forced cracked. So you could also potentially encrypt it.

How to securely store user passwords for an external application?

I'm building an application with Rails and will be pulling timesheets from Harvest, a timetracking app. I'm using an API wrapper called harvested. To be able to interface with their API, I need to provide a subdomain, username and password.
Right now, I'm just storing the passwords as plain strings and have not done any encryption. Would like to encrypt them before storing in the DB. If I encrypt the passwords before storing, can I still use the encrypted password for authenticating with the Harvester API?
OAuth exists for this very reason. Storing plaintext is obviously a bad idea, but storing something encrypted that you then decrypt is ALSO a bad idea.
Modern password flows use one-way encryption: encrypting the password and then comparing it an already encrypted value in the database. This allows use of algorithms that can encrypt easily but are essentially impossible to decrypt. Using an algorithm that allows your application to easily decrypt database fields will also allow an attacker to do the same.
With a one-way flow (encryption only), even if a user gets ahold of your encrypted passwords, they are unusable since anything entered in the password box will be passed through the encryption again before testing for validity.
TL;DR
Use OAuth as someone else pointed out: https://github.com/harvesthq/api/blob/master/Authentication/OAuth%202.0.md

Core Data Encryption

I have a question about Core Data encryption. I'm storing some sensitive user data in a Core Data SQLite database. The critical values are all transformables and I'm using AES256 to encrypt and decrypt them 'on the fly', including an individual IV for every value. The encryption key is the SHA512 hash of the password the user has chosen. This works very well so far.
Now about the user password. When the user launches the app he is asked for his password. The password is being hashed with SHA512 and stored in the iOS keychain. For every write or read operation the NSValueTransformer will get the password from the keychain. If the app is being closed, I delete the password hash from the keychain.
In my Core Data database I have a special entity which has a random number != 0 as it's only value. To test if the user has entered the correct password I fetch this entity and read the number. If it is =! 0, I know that the password was correct because when the decryption fails the NSValueTransformer always returns 0.
Now my actual questions: Would you consider this a good approach on encryption? How else would you test if the entered password is correct?
I'm a little concerned that storing the password hash in the keychain while the app is running makes everything slower, because the NSValueTransformer has to access the keychain all the time. Would it be sufficiently secure to just keep the password hash in memory, so it'll be deleted when the app closes?
You shouldn't use the hash of the password, hashes are designed to be fast so it's (comparatively) easy to do a brute-force attack. Use a key derivation function like PBKDF2.
Don't use a key directly derived from the password as an encryption key. If the user changes the password, you need to reencrypt all data and backups become worthless. Use a randomly generated encryption key that you encrypt with a key encryption key based on the password.
I'm not so sure about storing the hash in the keychain instead of just holding it in memory. The last time I looked into this, it was comparetively easy to decrypt the keychain. And every attacker that can read the memory of your running app will most likely be able to snoop on the keychain access or the decrypted data. Just keep it in memory and make sure to wipe the memory if the app suspends into background etc. This holds obviously also true for every piece of decrypted data.
[EDIT: #JeffLockhart to clarify the procedure for a master encryption key]
you generate a random key to encrypt your data, let's call it key A. You could use SecRandomCopyBytes to generate key A, see Apple's CryptoExcercise for a usage example. You use key A to encrypt the user data. To save key A, you have to encrypt key A with a second key B. You shouldn't use the password directly as key B, because of fast brute-force or dictionary attacks. So you derive a key from the password with a PBKDF, like in this
stackoverflow answer. You then encrypt key A with key B, e.g. using CCCrypt. You save the encrypted key A and the salt used to derive key B it.
To decrypt, the user enters the password, you derive key B using the password and the salt. You decrypt key A using the derived key B. Hope that clarifies.
You could have a look at this:
Secure Incremental Store
They have implemented a NSIncrementalStore subclass which is using an encrypted SQLite-Database. This is a drop-in replacement for Apple's SQLite Store. Comes with a price tag as well.

Storing user-generated text in database securely (Ruby/Rails)

I'm trying to figure out a way to store user-generated text securely in a database (so that only the user is the one who can access his/her stored text). I could have Rails encrypt and decrypt the user's text entries using the user's password as the key, but if the user ever forgot their password there would be no way to ever decrypt their previous content/text (since the Rails app uses BCrypt to store only a hash of the password).
Does anyone know how that could be done? It looks like Dropbox does something like it: "All files stored on Dropbox servers are encrypted (AES-256) and are inaccessible without your account password." (http://www.dropbox.com/help/27) Yet they allow you to reset your password and I'm assuming they don't store your plain text password anywhere.
What am I missing? Any suggestions would be greatly appreciated. Thanks!
Logic dictates that are only two options:
You encrypt using a key known to the server (user's key hash or some other identifier). Intruders can potentially read all the encrypted data, but the user can never lose the encryption token because it is on your server.
You encrypt the data using a key known to the user only (e.g. his password). Then intruders will not be able to read encrypted data, but if the user loses his key, the data is as good as a pile of random bits.
It's clear that Dropbox has chosen (1) from the fact that they allow to reset your password.
Build on Gintautas' Option 1 with a two-prong encryption plan:
Apply option 1, with a key that is known to the server, and
Store the database on disk in an encrypted format with a key that is known only to the server. E.g., in an encrypted volume. When the server starts up, the key must be manually entered in order to access the database.
This "static security" provided by part 2 protects against an intruder in the system gaining access to the database files. Maybe not 100% the exact security you're after, but getting closer.

Rails database - how to store encrypted data using the user's password?

I have a database that will be holding sensitive data, so it should be encrypted in the database. Basically the sensitive data are credentials to another web site. So I want to encrypt them with the users password + salt.
To decrypt the credentials one would need the password.
I see two ways:
On login, I could decrypt the credentials, and then store them in the session? Is that safe?
OR
Harder on the user would be to ask again for the password before decrypting the stored passwords/ids?
We don't want to have any ability to use the stored credentials ourselves.
I highly recommend "Security on Rails" for this. It's a tricky topic, so you'll need to spend some time reading up in order to get it right. They cover exactly this topic, including how to salt the encrypted data, unit test to make sure it is encrypted, and more.
Their sample code shows how to add class methods to ActiveRecord::Base so that you can make any database column encrypted in one line of code. Definitely an idiomatic Rails approach.
It's an awesome read - the unit tests blew me away, so seriously ... go get it.
By the way, when you said
We don't want to have any ability to
use the stored credentials ourselves.
you realize that because your code receives the unencrypted data from the user's browser, you do have access to the data in memory before it is encrypted on disk, or when it is unencrypted when the user wants to use that data later. And bad people could get access to that data if they root your box, sneak something into a Ruby eval(), etc.
Encrypting the data does help a lot, though. SQL injection attacks can't get the decrypted data, for example.

Resources