I have an architecture which requires a certain subset of data to be more heavily secured and encrypted. The main parameters which I believe meet the scope of the project are as follows:
- Data should be encrypted in transit
- Data should be encrypted at rest
- The API Server should never be handling unencrypted data of this type
- A developer/sysadmin/db admin should not have sufficient information in a vacuum to compromise encrypted data
- Data should only be decrypt-able by authenticated end users who have permissions to access those resources
Architecture
- A Mobile app on iOS/Android
- User sessions have a new RSA Key Pair after each log in/token expiration
- An API Server (secured vis TLS)
- The API Server has it's own private key for encrypting data to the database
- A Database Server
Initial Model
I've roughly conceived what I think will be a close fit for this system and would like to see how it stands up to some educated criticisms. The initial design is as follows:
Authentication
- A user logs into the mobile app (the client).
- After a successful authentication, the client generates an RSA Key Pair
- After a key pair is generated the private key is stored securely on the local device and the public key is sent to the api to be stored in the end users session.
Creating A Shared Encrypted Resource Group
- A logged in user sends an api request (via the client) to create a resource group
POST /resource-group
- The API receives the POST request and creates the resource-group, during creation the group is assigned it's own RSA Key Pair, that private key is encrypted with the server key for database storage AND encrypted with the clients public key and returned to the client
Creating A Shared Encrypted Resource In a Group
- A logged in user sends an api request (via the client) to create a new resource inside of a resource-group, the resource has data encrypted with the resource-group key
POST resource { groupId, dataEncryptedWithResourceGroupKey }
- The API receives the resource and re-encrypts the sensitive data using the server key before storing in the DB.
Retrieving A Shared Encrypted Resource From a Group
- A logged in user sends and api request (via the client) to get a resource from a resource-group they have access to.
GET resource [...resourceIds]
- The API receives the GET request and fetches the resource(s) from the database. The API uses the server key to decrypt the sensitive data resulting in sensitive data now only encrypted with the resource-group key (which the user has at this point and/or could request whenever necessary)
- The API encrypts the sensitive data with the end users public key and sends the resource to the end user and the end user finally decrypts the sensitive data using their private key followed by the resource-group key
Specific Questions / Unknowns
- My initial model doesn't take into account transient access. (ex. If user A had access to resource-group 1 yesterday and somehow stored the private key, then tomorrow no longer has access to that resource group) Is this a valid concern? Are there any good commonplace patterns to address this?
- Is this pattern sufficiently secure against MITM attacks? If not what vectors do you see being compromised?
- What bit size RSA key would be a good choice to balance security and performance. (I'm not storing any financial/identity data and the quantum computing gotcha is not interesting either)
- Any other criticisms are welcome. How can this be the best version of itself?