Cryptographic Hash to verify identification key - amazon-web-services

Let's say I want to pass information to the user that includes the user's unique id. Then, I want to use that id for CRUD operations. Is it a viable, or even recommended, option to store a cryptographic hash of that data, which would remain static using something like SHA-2 and then verify that what the user passed to me was what I sent them? Or, should I never send them the information in the first place and just look up the information from a table?
My issue now is that I am using AWS Cognito and using the sub as the unique identifier. So, I do not want to 'trust' the end user with sending me that sub after cognito provides them with it.

Related

How can I generate a HMAC key and secret key and share with client using AWS?

I am looking to generate a HMAC key and secret value as I want to use it as part of API request signatures. I want to be able to share the secret value and key with a 3rd party so I need access the value in plain text for one time. There would be a HMAC per 3rd party so the number could be large.
Option 1, I could generate this application side but I don't want to store in the dB and I was hoping to use a aws for storage but unsure what the process would be?
Option 2, Preferably I wanted to use AWS to generate the key and secret for HMAC as it can ensure uniqueness etc. I wanted it to provide the key and the secret one time. Looking at the documentation it seems to suggest that the secret value never leaves the HSM. Is my understanding correct or what is the best way to implement this using AWS?

Deterministic encryption using AWS KMS

I need to build an identity service that uses a customer supplied key to encrypt sensitive ID values for storage in RDS but also has to allow us to look up a record later using the plaintext ID. We'd like to use a simple deterministic encryption algorithm for this but it looks like KMS API doesn't allow you to specify the IV so you can never get identical plaintext to encrypt to the same value twice.
We also have the requirement to look up the data using another non-secure value and retrieve the encrypted secure value and decrypt it - so one-way hashing is unfortunately not going to work.
Taken together, this means we won't be able to perform our lookup of the secure ID without brute force iterating through all records and decrypting them and comparing to the plaintext value, instead of simply encrypting the plaintext search value using a known IV and using that encrypted value as an index to look up the matching record in the database.
I'm guessing this is a pretty common requirement for things like SSN's and such so how do people solve for it?
Thanks in advance.
look up a record later using the plaintext ID
Then you are loosing quite a bit of security. Maybe you could store a hash (e. g. sha-256) of the ID along the encrypted data, which would make easier to lookup the record, but not revert the value
This approach assumes that the ID is from a reasonably large message space (there are potentially a lot of IDs) so it is not feasible to create a map for every possible value
KMS API doesn't allow you to specify the IV so you can never get identical plaintext to encrypt to the same value twice.
yes, KMS seems to provide its own IV for ciphertext enforcing good security practice
if I understand your use case correctly, your flow is like this:
The customer provides a key K and you use this key to encrypt a secret S, which is stored in RDS with an associated ID.
Given a non-secret key K, you want to be able to look up S and decrypt it.
If the customer is reusing the key, this is actually not all that hard to accomplish.
Create a KMS key for the customer.
Use this KMS key to encrypt the customer's IV and the key the customer has specified, and store them in Amazon Secrets Manager - preferably namespaced in some way by customer. A Json structure like this:
{
"iv": "somerandomivvalue",
"key": "somerandomkey"
}
would allow you to easily parse the values out. ASM also allows you to seamlessly perform key rotation - which is really nifty.
If you're paranoid, you could take a cryptographic hash of the customer name (or whatever) and namespace by that.
RDS now stores the numeric ID of the customer, the insecure values, and a namespace value (or some method of deriving the location) in ASM.
It goes without saying that you need to limit access to the secrets manager vault.
To employ the solution:
Customer issues request to read secure value.
Service accesses ASM and decrypts the secret for customer.
Service extracts IV and key
Service initialises cipher scheme with IV and key and decrypts customer data.
Benefits: You encrypt and decrypt the secret values in ASM with a KMS key under your full control, and you can store and recover whatever state you need to decrypt the customer values in a secure manner.
Others will probably have cryptographically better solutions, but this should do for a first attempt.
In the end we decided to continue to use KMS for the customer supplied key encrypt/decrypt of the sensitive ID column but also enabled the PostgreSQL pgcrypt extension to provide secure hashes for lookups. So in addition to our encrypted column we added an id_hash column and we operate on the table something like this:
`INSERT INTO employee VALUES ..., id_hash = ENCODE(HMAC('SENSITIVE_ID+SECRET_SALT', 'SECRET_PASSPHRASE', 'sha256'), 'hex');
SELECT FROM employee WHERE division_id = ??? AND id_hash = ENCODE(HMAC('SENSITIVE_ID+SECRET_SALT', 'SECRET_PASSPHRASE', 'sha256'), 'hex');`
We could have done the hashing client-side but since the algorithm is key to later lookups we liked the simplicity of having the DB do the hashing for us.
Hope this is of use to anyone else looking for a solution.

Where and how to store login data

I need to create a desktop application via C++ that could store previous successful connections to show it for user next time. What is the best practice to store such login data? Is it acceptable to store it in the encrypted form inside some file or DB? If yes, what type of encryption is the best for such purpose?
the main problem of storing login data is, that you have to retrieve it and you want retrieve it without user input some password. so the password is decodeable by design and the only protection of the password is security through obscurity. so it does not really matter how you encode the password since Joe Badguy can retrieve it in any case. just do not save it in plain text or some "encryption" like XOR. also maybe do not name the parameter "password=" to make detection a bit more difficult.

Securing REST API with hashed signature

I've asked a question related to this one here:
Securely Passing UserID from ASP.Net to Javascript
However now I have a more detailed/specific question. I have the service and I have the application that is going to consume the service my plan to secure it, is to generate a hash based on some values, a nonce, and a secret key. My only issue is that it seems that in order to verify the hash I will have to send all of the values plus the nonce, except the secret key. Is this a flaw in my design or is this how such things are done? I have googled around and haven't been able to find out if this is the right and secure way to do this.
For example lets say I need to pass values 1,2, and 3 to my rest service, so I users phone number, the nonce, and, the secret key to generate a hash, now in order to generate the hash again I would need to pass all of the above except the key (which I can retrieve based on the users phone number).
I am totally leaving my service up for attack, securing it properly, or somewhere in between?
EDIT: made a spelling and grammar correction
EDIT 2: Finally came to to a satisfactory solution by using MVC 4 with forms authentication, identical cookie names between two projects, and making use of a globally applied [Authorize] attribute
There is nothing inherently wrong with this plan. If the client sends:
data . nonce . hash(data . nonce . shared-secret)
Then the server verifies the message by checking that hash(data . nonce . shared-secret) matches the hash provided by the client, you would be safe against both tampering and replay (assuming, of course, that you're using a reasonable cryptographic hashing algorithm).
Under this design, the client can even generate its own nonces, provided there is no risk that two clients will generate the same nonce.
However, eavesdroppers will still be able to see all the data you send… So, unless there is a very good reason not to, I would simply use https (which, unless there are other requirements I'm unaware of, be entirely sufficient).

Improve my Shared Secret Algorithm/Methodology & suggest a Encryption Protocol

I am looking for protocol/algorithm that will allow me to use a shared secret between my App & a HTML page.
The shared secret is designed to ensure only people who have the app can access the webpage.
My Problem: I do not know what algorithm(my methodology to validate a valid access to the HTML page) & what encryption protocol I should use for this.
People have suggested to me that I use HMAC SHAXXX or DES or AES, I am unsure which I should use - do you have any suggestions?
My algorithm is like so:
I create a shared secret that the App & the HTML page know of(lets call it "MySecret"). To ensure that that shared secret is always unique I will add the current date & minute to the end of the secret then hash it using XXX algorithm/protocol(HMAC/AES/DES). So the unencrypted secret will be "MySecret08/17/2011-11-11" & lets say the hash of that is "xyz"
I then add this hash to the url CGI: http://mysite.com/comp.py?sharedSecret=xyz
The comp.py script then uses the same shared secret & date combination, hashes it, then checks that the resulting hash is the same as the CGI variable sharedSecret("xyz"). If it is then I know a valid user is accessing the webpage.
Can you think of a better methodology to ensure on valid people can access my webpage(the webpage allows the user to enter a competition)?
I think I am on the correct track using a shared secret but my methodology for validating the secret seems flawed especially if the hash algorithm doesn't produce the same result for the same in put all the time.
especially if the hash algorithm doesn't produce the same result for the same in put all the time.
Then the hash is broken. Why wouldn't it?
You want HMAC in the simple case. You are "signing" your request using the shared secret, and the signature is verified by the server. Note that the HMAC should include more data to prevent replay attacks - in fact it should include all query parameters (in a specified order), along with a serial number to prevent the replay of the same message by an eavesdropper. If all you are verifying is the shared secret, anyone overhearing the message can continue to use this shared secret until it expires. By including a serial number, or a short validity range, you can configure the server to flag that.
Note that this is still imperfect. TLS supports client and server side certificate support - why not use that?
The looks like it would work. Clock drift could be a problem, you may need to validate a range of, say, +/- 3 minutes if it fails for the exact time.
flawed especially if the hash algorithm doesn't produce the same result for the same input all the time
Well, that would be a broken hash algorithm then. A hash reliable produces the same output for the same input every time (and almost always a different output for a different input).
Try using some sort of network encryption. Your web server should be able to handle that type of authentication automatically. All that remains is for you to write it into your app (which you have to do anyway). Depending on your app platform, you may be able to do that automatically as well.
Google these: Kerberos, SPNEGO and HTTP 401 Authorization Required. You may be able to get away with simple hard-coded user name and password HTTP headers and run your connections over HTTPS. That way you have less custom code on your server and your server takes care of authenticating your requests for you. Not to mention you are taking advantage of some additional features of HTTP.