Having trouble understanding where to store private keys - api

I am having an issue determining how to store API keys or other private information correctly. I have a helper library for a large set of inner-facing company applications that calls an external API for emailing and must have access to the API key. I store this key in a shared configuration file used by these applications. If I wanted to further secure the key by encrypting it or moving it to a service like Azure Key Vault, I then am stuck with the dilemma of having simply complicated the problem because I now have the private key for that encryption or the key to access Azure Key Vault that I now need to secure. Because this type of issue is so common I am assuming I am missing something here. Each time I try to further encrypt or otherwise secure a key I am simply adding another layer of the same problem. I still end up with a private key sitting somewhere in plain text. Is it the case that having a plain text key in an otherwise secure environment is just not an issue after all?
I would like to point out that I cannot use Environment Variables or some of the other tools I have seen to secure keys on the machine as these applications can be run on any number of terminal servers or local machines throughout the company. Most are click-once Dot Net applications written in .Net 4.5 and can run anywhere in our environment, some by any user in our domain.

I don't use azure but I assume Azure Key Vault is very similar to AWS Secrets Manager which is exactly the thing I would use (I wrote about one use case for storing Amplitude API keys on my blog).
Why is this better than simply having the key lying around in a file?
Simplified key distribution: you don't need to download the key on all the machines
Improved security: you simply load the key at runtime, no need to have the key lying on the disk forever
Note there's not much point in double-encrypting the key as you mentioned. That's just increasing complexity without improving the security of the solution much.
Also, in case of AWS, you would specify a very granular IAM policy/permissions for accessing the specific secret and attach the policy to the IAM role assigned to the instances needing to work with the key.

Related

Managing the rotation of Azure storage account keys with Azure Function and Key Vault

Having asked a question about Removing Secrets from Azure Function Config this Microsoft approach was recommended for managing the rotation of keys for Azure Storage Accounts and the keeping of those keys secret in Azure KeyVault
Note we are accessing Tables in an Azure Storage Account and Tables unlike Blobs and Queues do not support Managed Identity access controls.
The recommendation comes with some Azure Deplyment templates that would not run for me so I decided to create the resources myself to check my understanding of the approach. After trying to follow the recommendation I have some questions
Existing situation:
An existing function called "OurAzureFunction" that currently has the Storage Account connection string configured with the key directly in the Function config.
An existing storage account called "ourstorageaccount" that contains the application data that "OurAzureFunction" operates on
My understanding of the recommendation is that it introduces
"keyRotationAzureFunction", an Azure function with two Httptriggers, one that responds to event grid event for secrets that are soon to expire and one that can be called to regenerate the keys on demand.
"keyRotationKeyVault", a Key Vault that is operated on by the keyRotationAzureFunction.
An Event Grid subscription that listens to SecretNearExpiry event from "keyRotationKeyVault"
I have issues with understanding this approach. I can't see a better way but to collate the issues in this Stack Overflow question rather than with three individual questions.
Does keyRotationAzureFunction have the "Storage Account Key Operator Service Role" on "ourstorageaccount" so that it can regenerate its' keys?
What configuration does "OurAzureFunction" have that allows it to create a connection to ourstorageaccount? Is it the tagged secret in "keyRotationKeyVault"?
Is the value of the secret in "keyRotationKeyVault" not used just the tags related to the secret?
Yes, the function has to run as a principal that can rotate the keys, which that role provides. Key rotation can be kept as a separate role so that you can provide granular access to secrets to avoid leaks.
The function (rather, the principal) just needs "get" access to a secret used for generating SAS tokens (it's a special kind of secret where the value returned will change to generate new SAS tokens) that grants access to storage. The Key Vault must be configured to manage tokens for the Storage account. See a sample I just published recently at https://learn.microsoft.com/samples/azure/azure-sdk-for-net/share-link/ which I hope simplifies the problem.
The value of the secret is actually the generated SAS token for the storage account. The tags are used to figure out which secret to use for the storage account in case you have other secrets in your Key Vault, or even manage multiple function apps this way (you can identify the correct secret for the storage account key near expiry).
I'm not sure why ARM templates did not work for you. You need to be an owner of Storage and Key Vault to create necessary permissions.
To answer your questions:
Yes
Yes it is using tags to with Storage information to connect and regenerate key
Value is not not for connection to Storage, but it could be an alternative way to connect.
You can see more information about tags here:
https://github.com/jlichwa/KeyVault-Rotation-StorageAccountKey-PowerShell

what happens to JWT if someone gets my private and public key?

It seems to me that if my private and public key are compromised (which i use to sign and verify JWTs), that anyone can independently generate JWT tokens for themselves to use on my API?
Whereas on the other hand if I generated my own tokens myself, and stored a look-up table of 'one-way-hashed user id' => 'token', then if someone broke into my system, they would not be able to generate tokens to use on my API, and they would also not be able to use the tokens (because they would not know which token belonged to which user)
If someone breaks into your system and it is still secure, then you made a secure system; nothing to worry about.
with JWT, it appears to me that if someone breaks in, I do have something to worry about.
It seems to me that if my private and public key are compromised (which i use to sign and verify JWTs), that anyone can independently generate JWT tokens for themselves to use on my API?
Yes, that's correct.
Public keys are intended to be public and can be distributed.
On the other hand, private keys are supposed to be private and must be kept secure in your server. Anyone who has access to the private keys should be capable to issue tokens.
Disclosing your private key is a huge security breach.
It seems to me that if my private and public key are compromised (which i use to sign and verify JWTs), that anyone can independently generate JWT tokens for themselves to use on my API?
As also pointed out that you need to keep your Private Key Secure , the best way to keep it secure is to use an HSM for signing your data , in this case you can extend the JWT generator to sign the data through a crypto dll inside the HSM , this insures that the private key is never exposed outside the HSM
Whereas on the other hand if I generated my own tokens myself, and
stored a look-up table of 'one-way-hashed user id' => 'token',
Any one can generate your non-keyed hash. Secure hashes involved a private key which becomes a digital signature. Now we've come full circle, because that's exactly what a JWT token is.
Alternatively, you store them in a datastore, but now you must query this on every round trip. Most ticket(cookie)/token authentication systems use public key verification, which verifies the validity of the ticket/token without a database roundtrip.
If you store them in a datastore, now you must track expiration in the datastore as well. Tickets/tokens can have an expiration built into them. The nice thing about tickets/tokens is the client holds them. You can expire a session more quickly than the authentication. I.e. often you get a ticket that may allow you to be logged in for 2 hours, but the web server can expire your session in 10 minutes to reduce memory usage. When you access the web server in 15 minutes, it will see your ticket/token and see that it is still valid, and create a new session. This means at any point in time the server is tracking far fewer idle users.
JWT issuers are great for distributed systems, where authentication is shared. Rather than reimplement the authentication in every system, exposing multiple systems to the private key, as well as potential bugs in the authentication, we centralize it to one system. We can also leverage third party integrators that generate JWTs. All we need to do is get their public key for verifying the JWTs.
If someone breaks into your system and it is still secure, then you
made a secure system; nothing to worry about.
I have your list of nonces you were saving in your database now, and can login as anyone. I also likely have your connection strings, even if you're encrypting your application config, if I have root access then I can access the same key store that's used by the application to decrypt them. Now I get your username/passwords from your database and can login as anyone, regardless of what authentication scheme you use.
You'll be hard pressed to find a system that can still be secure after someone's gained root or physical access to the machine.
There's a small handful of systems that have purpose built hardware for storing keys and handle requests for encryption operations through an interface, thus ensuring the keys are protected at a hardware level and never accessed directly from software:
https://en.wikipedia.org/wiki/Hardware_security_module

Cryptographic Agility and Key Management

I have a design question. I have a web application that uses .NET encryption APIs to encrypt/decrypt data. (App uses old crypto algorithms like MD5 and SHA-1). Also, app hard-codes the encryption keys in the production code.
I would like to;
1 ) Update existing old algorithms (MD5 and SHA-1) to new ones.
2 ) Move encryption keys from source code to a secure share.
3 ) Can change the encryption keys easily and regularly
My Design;
Algorithm Update
For the algorithm update, we use specific .NET implementations of crypto algorithms. We use classes like MD5CryptoProvider or RijndaelManaged. These are all hard-coded. I am going to remove the specific algorithm dependency and make it more agile like;
HashAlgorithm algo = HashAlgorithm.Create(MyPreferredHash.ToString());
algo.ComputeHash(...);
MyPreferredHash value will be loaded from a config file so that we can change this when we want to.
Question: Upgrading the code is easy to do this. However do you see any potential issues with changing crypto algorithms? We do not store any encrypted or hash data anywhere and web application is stateless. All the hash values are generated and appended to url strings and decrypted from another pages. Therefore, no data is stored. Except the cookies. When we encrypt cookie and send it back to user, we decrypt it when server receives it. In this case, i thought of destroying the cookie and send a new one to the client. Is this reasonable? Any other issues you think of ?
Key Management
Second part of the design, is to remove hard-coded keys from source code to secure share. After this, I need to be able to rollout new encryption keys. Each encryption key will be associated with a expire date. When we rollout a new encryption key, new key will be used for encryption and decryption. If it fails to decrypt, then we can try old keys. Old keys will be used for decryption or verification until their expire date. When they pass their expire date, they should retire.
For the storage; I am thinking of storing the encryption keys in a config file in the local machine as "encrypted" by a master key which will reside in a secure share. Therefore, anybody who doesn't have access to this secure share will not be able to see the master key. Master key will be loaded from secure share to machine registry when a machine reboots. The encryption keys in the local machine will be loaded from config file (local) and decrypted by master key in registry.
This storage choice will give us storing only one master key in a secure share and also historical changes to the encryption keys as we will store them in version control system.
The challenging part is the key change/update.
What is the recommended key change algorithm here for a distributed web application? If we are doing partial deployment after a release, not all the machines will have the same config file content (e.g. new encryption key added). All site deployment can take 1-2 weeks. This is also another concern that if we should wait for all deployments complete so that these keys will be active after that.
Any other feedback?
You are quite right to design your app to be agile in the face of unknown future attacks on particular encryption algorithms.
The simplest way to future-proof your app in a robust way would seem to be to switch to using a standard data format for your encrypted information, and use a standard library to do the hard lifting. The choice of a specific standard to use would depend on what kind of data formats you're working with, but there are good candidates to choose from. Then when there is a future attack, you can just change some parameters, or update to the latest version of the implementation.
Doing crypto is very tricky. Best to leave it up to the experts.

Securely storing encryption key in WinRT / Windows Store apps

I would like to encrypt some of my Windows 8 app data (stored in local storage folder). This is not very sensitive data, however I would like to prevent users from forging/modifying it (and was looking into encryption as a way to achieve that).
Is there any secure key store available that I could use to save my key for later reuse? What I would like to do is:
1) on the first run generate the key and store it somewhere,
2) encrypt the data using the key,
3) anytime i need to decrypt the data i would retrieve the key from the store.
Did you have a look at the PasswordVault class yet? http://msdn.microsoft.com/en-us/library/windows/apps/windows.security.credentials.passwordvault.aspx
Basically all confidential information should go in there.
If you want to 'prevent users from forging/modifying it', the question is, how much energy you are willing to put into this.
Generally speaking, data in the PasswordVault should be secure without using additional encryption. Regarding security above that level it can be said that an attacker with physical access to the computer can do anything with it, as you'd have to store the keys on the same machine. Anything more swiftly reaches a point of diminishing returns against invested effort - i.e. just adding some obscurity instead of real security.
Be careful with the PasswordVault solution, I discovered that it is actually a problem because it is a roaming settings. If you open your application on two devices at the same time, you will get two encryptions keys, but after a day or so, the roaming setting will override the first generated encryption key.

saving key in application settings

i am starting to use cryptostream class. i may be wrong, if you encrypt something, close the app, and then try to decrypt it, it will not be able to because a different key will be generated. because i do need this functionality, i am wondering if it's possible to save the key in application settings and whether this is the right way to go?
If you always run your app under the same user account (it can be a local user or a domain user), the best option would be to use DPAPI. The advantage of using DPAPI is that you do not have to worry about the key (the system generates it for you). If you run the app under different user identities, then it gets more complex because the options that are available range from bad to worse (the major problem is: how do you protect your secret: key, password, passphrase, etc). Depending on what you want to do, you may not need to use encryption at all (e.g. if you want to encrypt a connection string, consider using integrated windows authentication, which does not require a password). For more info on the topic, check out this MSDN article: Safeguard Database Connection Strings and Other Sensitive Settings in Your Code; it may give you some ideas.
Lots of applications save the keys in configuration files. It's a common bad practice.
It's not secure but all secure options are hard to implement. There are options using different factors,
You can derive the key from a password using PBE (password-based encryption). But you have to enter a password to start your application. This is so called "What you know" factor.
Put the key in a smartcard. This is very secure but you need to have access to the card on the machine. This is called "What you have".
Ignore other schemes involving encrypting keys with yet another key. It doesn't really change the security strength.