Encrypt sensitive data when sending to the server

Let’s say I have some sensitive data, e. g. an API key users have to add. I now want to send this key to the server and prevent any man-in-the-middle attacks. I’m using HTTPS for the communication, but I’m not sure if this is “enough” in such a scenario.

Would you recommend adding another encryption layer that is only known to the client and the server, and if so, what is the best way to implement this? The server should still be able to decrypt the key when needed.

Passwords and login tokens are sensitive data being exchanged between client and server in a regular meteor app

Yes, I know. But IIRC, passwords are already encrypted on client-side, right?

If you are concerned about mitm attacks, you can also not trust the client app itself that is being sent through the same channels

@waldgeist

1) Mongo Auto Field Encryption Package

2) Environment variables

API keys and other passwords are usually set as environment variables, that are only serverside. For example, here is adding some new environment variables at various platforms:

If there is some need to copy some environment variable to clientside, it’s possible by setting public variable:

Or if that environment variable is only needed serverside, it can stay at environment varible, or copied to private variable like Meteor.settings.headerLoginId .

API keys are usually needed to exist unencrypted at serverside.

3) User accounts

For user accounts, Meteor accounts packages save password in hashed format to database.

Before showing any sensitive data, it’s useful to check is user logged in:

if (Meteor.user()) {
...
}

4) Admin Panel

If at Admin Panel UI it’s needed to save some new password to database, it’s useful to just save it, for example with Meteor Method, but not load it back, not adding it to PubSub minimongo content.

2 Likes

Encrypt

import CryptoJS from 'crypto-js'. // this library is now deprectated but ... "Nowadays, NodeJS and modern browsers have a native Crypto module. " - Check the NPM details.

const passphrase = process.env.PHRASE // or your safe way to store a pass. This can also be a userId, session id, anything that you can pick up on the server for the same user. The userId can also be altered at both ends so that you cannot reverse engineer it.
return CryptoJS.AES.encrypt(string, passphrase).toString()

Decrypt

import CryptoJS from 'crypto-js'

const passphrase = '' // same as above
const bytes = CryptoJS.AES.decrypt(string, passphrase)

return bytes.toString(CryptoJS.enc.Utf8)

1 Like

You can generate a key pair: Public key + Private key.
Send the Private Public key to client, client will use this key to encrypt data then send to server.
On the server side, use private key to decrypt the data.

// Edit: Send the public key to the client, not the private one.

1 Like