Signing blockchain transaction using a key stored in Google Cloud KMS - google-cloud-kms

I have a requirement to secure the private key which is used for signing a blockchain transaction. While we are evaluating option of using HSM (Hardware Security Module), I was equally wondering about the applicability of Google Cloud KMS. Your help will be highly appreciated if you can answer my following queries :)
Can we save a key in Google Cloud KMS which may have been generated outside?
Assume that I have already saved my private key in Google Cloud KMS, which one of the following is true/possible?
Using an API call, the key stored in KMS is retrieved first and then it can be used to sign the blockchain transaction. But in this case, security can be compromised once the key is outside the KMS.
The key never leaves Google Cloud KMS once stored. Instead, a blockchain transaction can be sent to Google Cloud KMS for signing the transaction using the key managed by it. Here I assume that KMS may provide me some customization features so that I can execute the signing process or KMS may have capability to execute a piece of code.
Google Cloud KMS can't execute specialized tasks (like signing a Blockchain transaction), it just does the encryption/decryption only.

Cloud KMS doesn't store keys for retrieval; instead, it stores keys and keeps them secret. I believe your third bullet is closest to the situation.
In your situation, I would suggest wrapping the blockchain private key with a KMS key and then storing the wrapped private key somewhere. To sign a transaction, the app would use KMS to unwrap the key then sign it in software locally.
Yes, this exposes the calling app to the private key and makes you responsible for that security.
A question: what algorithm would you like signing support for? Google NEXT is next week, look for some announcements from us that you might be interested in.

Related

Google Cloud Function: Expose Secret as Environment Variable?

I have set up a few Google Cloud Functions that access various APIs in their implementation. Naturally, these APIs require tokens or username/passwords to work. I have created these secrets in Google Cloud Secret Manager and can successfully access them via the Cloud Function using the Google Cloud Console UI.
My question is not about implementation but what the difference is between reference methods:
Mounting Secret as a volume?
Exposing Secret as environment variable?
All my functions use the second option. Is this a bad practice and/or does this create a security leak? I did a search and couldn't find anything definitive and Google's documentation doesn't mention anything about the differences. The word "expose" has me worried, thinking that my Secrets would be accessible by others. I would love a pros/cons of each that I and future users could reference.
Thank you!
Using Secret Manager is a good practice.
The primary difference between mounting a secret as a volume versus as an environment variable is the access method and when the secret is read from Secret Manager.
Mounting a secret as a volume reads the secret each time the volume/file is read. If you are referencing the latest tag, updates to secrets will update the secret in Functions the next time you read the volume/file.
Exposing a secret as an environment variable reads the secret at instance cold start. That means if you update the secret, the Function instance will continue to use the last value even if you specify latest. Only on instance cold start is the new secret read from Secret Manager. If you have multiple function instances running, some might use the previous value and some might use the current value. That depends on when each Function instance was started.
Mounting a secret as a volume can be more expensive because the secret might be read more often.

How do you store API tokens securely?

When user enter their API token on the browser, I need securely save their token. What is good approach to encrypt user's token?
I wax considering using AWS Secrets Manager to store User's token through API but it turn out it is really expensive. $0.40 per secret per month.
I might consider encrypting user token in the MySQL and store master secret in the .env file
Is there alternative approach?
Since you're already using AWS services it makes sense to take advantage of more resilient cloud-native solutions.
With SSM you only pay for your underlying AWS resources managed or created by AWS Systems Manager, however, parameter store as well as the majority of other AWS services using KMS for decryption and encryption purposes.
Additional alternatives:
Cache SSM params for instance https://github.com/alexcasalboni/ssm-cache-python
Use credstash (dynamodb + kms)
Use s3 with server and client side encryption https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingEncryption.html
Based on your usage you will need to do the math, KMS is not free, but has a decent monthly free tier
For your scenario, you can save the token AWS DynamoDB, encrypted at rest with AWS KMS.
In addition to the Lambda charges, AWS KMS will mainly cost $1 for CMK, and based on the on-demand encryption and decryption operations about $0.03 per 10,000 requests and the free tier will give 20,000 requests/month free of charge.
For more details about pricing, refer AWS KMS pricing section.

How frequently should I rotate my encryption keys? Can I use Cloud KMS to automatically rotate keys?

With my on-prem KMS, I rotate keys monthly. Can I also do that with Cloud KMS? Is there a better recommended frequency compared to my on-prem use? Is data re-encrypted when I rotate a key?
Your desired frequency of key rotation depends on your use case and threat model. You want to limit the amount of very sensitive data encrypted with a single version of an encryption key.
On Google Cloud Platform, Google's Cloud KMS can be set to automatically rotate keys as often as once per day. This means that a new key version is automatically generated, and made the primary version used to encrypt new data. Most customers will typically choose 30 or 90 day rotation periods, based on business requirements.
Data is not re-encrypted when a key is rotated - rather, the new key version is used to encrypt any new data, but old data is not re-encrypted. You can manually do this by decrypting and re-encrypting the data.
For further discussion on key rotation in Cloud KMS: https://cloud.google.com/kms/docs/key-rotation#frequency_of_key_rotation
To set the rotation period on a key, using gcloud run:
gcloud beta kms cryptokeys set-rotation-schedule CRYPTOKEY_NAME \
--location LOCATION --keyring KEYRING_NAME \
--rotation-period ROTATION_PERIOD \
--next-rotation-time NEXT_ROTATION_TIME

Securing Database Content

Edited based on comments.
My company is developing a system and is in the early design stages. I am the lead on the project. Some of the information to be stored in the system is highly confidential. The system must protect this information such that only authorized users have the ability to see this information. In fact, it is such that we want to protect it from ourselves even. The database to be used will probably be mySQL but does not have to be. I am aware that the data can be encrypted in the database. I am also aware that the software will have to be able to retrieve this data from the database for authorized users. I do not want any developers, including myself, to be able to decrypt and view this information -- in production -- but they do need to be able to view it during development(we will disable encryption during development).
The software will be a cloud based offering but will have an in house hosting option as well.
We can have a software based encryption and I realize that if software can get at the data then it's accessible - but I want this as tight as possible so that a developer cannot (including myself) view this data, but signed in, authorized users, can view it.
I'm stuck in my own thinking box about how to do this so I'm seeking advice as to how to secure this.
The client side will need a decryption key to decrypt the data. The software will have to allow access to this key for authorized users. The users cannot hold this key as the "client" devices could be virtually anything. Now I know I have no control over what the end users who have access do with the data, and that's not by concern. I want them to be able to store this information and have it secure in such a way that I cannot see it! I also do not want to have the ability to make myself authorized to see it - but to have that ability rest in the hands of a user side trusted administrator.
The data can be binary data. I do not want to encrypt the entire database, nor do I want to ever need to re-encrypt data because it can be huge amounts of data.
I have read posts about using GnuPG to handle this with public key for encryption and decryption via any one of a set of multiple private keys. This might be feasable for this but I'm looking for multiple solutions. My "issue" with this is the pass phrase protecting the private key and issueance of these private keys. I really don't want to user having to key in the passphrase associated with the private key every time that they login to the system or try to view the encrypted/protected data, but I don't want to store this passphrase anywhere a developer can see it either!
I understand about PKI but it doesn't offer protection from developers who can access the master decryption key which is shared using a public/private keypair.
I've edited the question with a proposed solution, please punch holes in it.
Development Language is C#. Microsoft supports asymetric keys which is what we want to use.
An X509 Certificate will be utilzied for the encryption keys. The public key will be stored in the database and used for all encryption. The private key will be stored in the database as well but encrypted using a passphrase entered by a trusted administrator. (This is the weak link in my mind, more on this later).
The administrator will create users who have access to the encrypted data. The users will be issued a copy of the private decryption key via the administrator and this key will be associated with their user account and encrypted in the system using their initial pass phrase.
When the user first logs in and is prompted to change their pass phrase, the private key will be re-encrypted using their new pass phrase. Their pass phrase is not stored in the database, only a hash for validation. Their keyed pass phrase will be encrypted using a timestamp or other data and will be stored on their local computer not on the server or in the servers identifable memory except when it is used for decryption of the private key. A software algorithm will be created to retrieve the decryption key for the encrypted master decryption key associated with this user.
Thus users can be created and revoked at the will of the administrator. Users can have their pas phrases reset - but in that case a new decryption key would need to be issued because the old one would not be decryptable any longer.
The one flaw I see, and I'm open to input, is if the administrator forgets their pass phrase and can no longer issue private keys. We could write code that given a users password, recovers the private key and encrypts it using the administrators new password when they enter it.
Another weak link is user pass phrase. If that becomes compromised then a developer could use that to obtain a copy of the private decription key and decrypt data.
Also - if for some reason an administrator needs to be let go we have the same issue as above where we don't have a copy of the private key accessible to share but we could get one using a users pass phrase.
Any advice on overcoming the perceived weaknesses?
We cannot tolerate exposure of the master decryption private key - if it is exposed then the entire database needs to be re-encrypted using a new keypair.
Thank you for your comments.
If you need to protect the data from yourselves, the only option is end-to-end encryption. User has a private key and it never leaves their computer. Devs/sysadmins never have private keys and can never decrypt.
This would require you make your client software source available to users so they can see that you are not leaking their info.
Use USB smart cards for easier/safer key management. They key is generated on the smart card and never leaves it. The smart card does the decryption on your apps behalf.
This make searching harder, but you can fix some of this by storing hashes along w the encrypted values, and searching on them.
Update, answering your questions in your comment:
Web based is not an option. You need a thick client
There is no "master key"
Please clarify "authorized user". Authorized by whom? Please provide an example.
Another option would be to skip encryption entirely and rely solely on access control. Use a db like postgresql, ms sql, or oracle that does row-level security. Don't give access to any one DBA. Give part of password to one dba, another part to another. DBA's need to be in same room to access the server.
Either way, you should be familiar with https://en.wikipedia.org/wiki/Secret_sharing
If you were to condider SQL Server instead of mysql, then the most secure design I can think of that meets your requirements is to require SQL Server Enterprise Edition an Extensible Key Management system that uses a Hardware Security Module. SQL Server Extensible Key Management enables the encryption keys that protect the database files to be stored in an off-box device such as a smartcard, USB device, or EKM/HSM module. EKMs are only supported in Enterprise edition. An HSM will allow for the delegation and isolation of managing the encryption keys and functions under a group other than both developers and DBAs, if that is your intent. Other features I would suggest in the design include the following options to complete end to end transport\session encryption:
Installing a domain or CA certificate on the SQL Server and enabling Force Protocol Encryption or enabling IPSec on the host of the instance
Installing a domain or CA certificate on all IIS websites or web services and forcing encryption in the connection strings and https
The benefits of this design over SQL Server Always Encrypted are that the encryption is protected by a single system that can be monitored and defended with more focus as opposed to numerous clients that increase exposure to theft of the private key from one of the users key stores. Also, key rotation for EKMs should be easy for those who are managing the system. It is also possible with an EKM to require that more than one person be involved in generating keys.

Simple, secure API authentication system

I have a simple REST JSON API for other websites/apps to access some of my website's database (through a PHP gateway). Basically the service works like this: call example.com/fruit/orange, server returns JSON information about the orange. Here is the problem: I only want websites I permit to access this service. With a simple API key system, any website could quickly attain a key by copying the key from an authorized website's (potentially) client side code. I have looked at OAuth, but it seems a little complicated for what I am doing. Solutions?
You should use OAuth.
There are actually two OAuth specifications, the 3-legged version and the 2-legged version. The 3-legged version is the one that gets most of the attention, and it's not the one you want to use.
The good news is that the 2-legged version does exactly what you want, it allows an application to grant access to another via either a shared secret key (very similar to Amazon's Web Service model, you will use the HMAC-SHA1 signing method) or via a public/private key system (use signing method: RSA-SHA1). The bad news, is that it's not nearly as well supported yet as the 3-legged version yet, so you may have to do a bit more work than you otherwise might have to right now.
Basically, 2-legged OAuth just specifies a way to "sign" (compute a hash over) several fields which include the current date, a random number called "nonce," and the parameters of your request. This makes it very hard to impersonate requests to your web service.
OAuth is slowly but surely becoming an accepted standard for this kind of thing -- you'll be best off in the long run if you embrace it because people can then leverage the various libraries available for doing that.
It's more elaborate than you would initially want to get into - but the good news is that a lot of people have spent a lot of time on it so you know you haven't forgotten anything. A great example is that very recently Twitter found a gap in the OAuth security which the community is currently working on closing. If you'd invented your own system, you're having to figure out all this stuff on your own.
Good luck!
Chris
OAuth is not the solution here.
OAuth is when you have endusers and want 3rd party apps not to handle end user passwords. When to use OAuth:
http://blog.apigee.com/detail/when_to_use_oauth/
Go for simple api-key.
And take additional measures if there is a need for a more secure solution.
Here is some more info, http://blog.apigee.com/detail/do_you_need_api_keys_api_identity_vs._authorization/
If someone's client side code is compromised, they should get a new key. There's not much you can do if their code is exposed.
You can however, be more strict by requiring IP addresses of authorized servers to be registered in your system for the given key. This adds an extra step and may be overkill.
I'm not sure what you mean by using a "simple API key" but you should be using some kind of authentication that has private keys(known only to client and server), and then perform some kind of checksum algorithm on the data to ensure that the client is indeed who you think it is, and that the data has not been modified in transit. Amazon AWS is a great example of how to do this.
I think it may be a little strict to guarantee that code has not been compromised on your clients' side. I think it is reasonable to place responsibility on your clients for the security of their own data. Of course this assumes that an attacker can only mess up that client's account.
Perhaps you could keep a log of what ip requests are coming from for a particular account, and if a new ip comes along, flag the account, send an email to the client, and ask them to authorize that ip. I don't know maybe something like that could work.
Basically you have two options, either restrict access by IP or then have an API key, both options have their positive and negative sides.
Restriction by IP
This can be a handy way to restrict the access to you service. You can define exactly which 3rd party services will be allowed to access your service without enforcing them to implement any special authentication features. The problem with this method is however, that if the 3rd party service is written for example entirely in JavaScript, then the IP of the incoming request won't be the 3rd party service's server IP, but the user's IP, as the request is made by the user's browser and not the server. Using IP restriction will hence make it impossible to write client-driven applications and forces all the requests go through the server with proper access rights. Remember that IP addresses can also be spoofed.
API key
The advantage with API keys is that you do not have to maintain a list of known IPs, you do have to maintain a list of API keys, but it's easier to automatize their maintenance. Basically how this works is that you have two keys, for example a user id and a secret password. Each method request to your service should provide an authentication hash consisting of the request parameters, the user id and a hash of these values (where the secrect password is used as the hash salt). This way you can both authenticate and restrict access. The problem with this is, that once again, if the 3rd party service is written as client-driven (for example JavaScript or ActionScript), then anyone can parse out the user id and secret salt values from the code.
Basically, if you want to be sure that only the few services you've specifically defined will be allowed to access your service, then you only option is to use IP restriction and hence force them to route all requests via their servers. If you use an API key, you have no way to enforce this.
All of production of IP's security seems produces a giant bug to users before getting connected. Symbian 60s has the fullest capability to left an untraced, reliable and secure signal in the midst of multiple users(applying Opera Handler UI 6.5, Opera Mini v8 and 10) along with the coded UI's, +completely filled network set-up. Why restrict for other features when discoverable method of making faster link method is finally obtained. Keeping a more identified accounts, proper monitoring of that 'true account'-if they are on the track-compliance of paying bills and knowing if the users has an unexpired maintaining balance will create a more faster link of internet signal to popular/signatured mobile industry. Why making hard security features before getting them to the site, a visit to their accounts monthly may erase all of connectivity issues? All of the user of mobile should have no capability to 'get connected' if they have unpaid bills. Why not provide an 'ALL in One' -Registration/Application account, a programmed fixed with OS, (perhaps an e-mail account) instead with a 'monitoring capability' if they are paying or not (password issues concern-should be given to other department). And if 'not' turn-off their account exactly and their other link features. Each of them has their own interests to where to get hooked daily, if you'd locked/turn them off due to unpaid bills that may initiate them to re-subscribe and discipline them more to become a more responsible users and that may even expire an account if not maintained. Monthly monitoring or accessing of an identified 'true account' with collaboration to the network provider produces higher privacy instead of always asking for users 'name' and 'password', 'location', 'permissions' to view their data services. IP's marked already their first identity or 'finding the location of the users' so, it's seems unnessary to place it on browsers pre-searches, why not use 'Obtaining data' or 'Processing data.'