Here is the model we are using to store the CC details how secure does this look?
All our information is encrypted using public key encryption and the keypair is user dependent (its generated on the server and the private key is symmetric encrypted using the users password which is also Hashed on the database) So basically on first run the user sends in his password via a SSL connection and the password is used with the addition of salt to generate an MD5 hash, also the password is used to encrypt the private key and the private key is stored on the server. When the user wants to make a payment, he sends his password. The password decrypts the private key, and the private key decrypts the CC details and the CC details are charged.
If the user's password is secure enough to protect the private key, why not skip the private key and use password (via a suitable key derivation algorithm) to encrypt the credit card number? Unnecessary complications definitely do not improve security.
This scheme doesn't use the public key for anything, indicating that an asymmetric algorithm is out of place here.
This ties the credit card's security to the strength of the user's password, which varies from user to user and is generally weak. It's better to creating your own symmetric encryption key, keeping that safe, and then doing a bunch of complicated stuff that experts invented, involving initialisms like CBC, CTR, and IV.
I am not sure if you store card number and private key files together. It seems like by just using user password to encrypt private key file you are opening the door for dictionary style attack if the encrypted private key files are available.
Not sure why you want to use public key cryptography which can be pretty slow. Also the model of 1 key pair per user may not scale (how many files, can you generate parameters for public key operations). Note that you may have abusive behavior - people checking to see if their list of stolen cards are good.
You could still prevent any use of card number when user is not present by adding your own master secret and deriving key schedule from combination. In general most merchants can't follow this strict requirement as there is a valid need to use card number when user is not present.
If you just want user specific keys (and you must use a different IV every time), then you can go the openssl EVP_BytesToKey route and pass a different salt each time with the master secret from which the encryption key and iv will be derived (and they will be different for each user).
Finally use of payment instrument is protected by just user password as described. Some users choose weak passwords. So you may want to use additional proofing to ensure card belongs to user - some of this is for your own good as you can fight friendly fraud chargebacks and keep your real fraud chargebacks low.
I agree with erickson that if the public key isn't used there is no point in doing asymmetric crypto.
As always the problem here is a key-management problem. The insecurity arises from not knowing how to safely hide the key that decrypts the data.
Im not sure if it is possible, but if you can afford it buy a hardware security module and let you HSM manage the keys, or encrypt all customer (private) keys with the HSM master key.
If you cannot, you should find a suitable place to store your "master" key, a possible example is the windows store (if that is a possibility). However, I most admit that i dont really know how secure the windows store is.
You may want to take a look the Payment Card Industryies "Payment Application DSS"" https://www.pcisecuritystandards.org/security_standards/pa_dss.shtml
It may help make some decisions for you.
Related
The use case is a user has a metadata that needs to be encrypted so when they sign-in a protected and stored object "encrypted" will be "checked" to verify the object information coming in plaintext is equal to what is in the encrypted object.
The question is, is it more appropriate in an Azure Key Vault to give each and every user a key with public and private key ability. Or, just use a single key that will encrypt the object that is stored and just un-sign/decrypt the object when it is accessed.
To me, the object is what is necessary to be encrypted and doesn't really relate to how the key is encrypted hence a universal 1 key to many approach.
The other approach makes sense too but I would have to create a hell of a lot of keys in order to facilitate such an approach. Is 1000's or millions of keys resulting in a key per each user appropriate?
What are the advantages or disadvantages of each other.
I think the same practice would apply to JWT token signing.
I think its better to have one key and on a regular basis rotate the key.
For example, like they do in ASP.NET Core Data Protection API (I know you are using node) where they every 90 days (by default) replace the current key with a new one, and the old one is still kept to allow decryption of old data. In .NET they call this the key-ring, that hold many keys.
I did blog about this here.
Also, do be aware that using some SDK's with Azure Key Vault, they try to download all secrets at start-up, one-by-one. That can be quite a time consuming if you have many secrets.
I have a field called "Pin" in DynamoDB which is sensitive information and can be used by users to perform certain actions. It isn't a password though and we do need to display the value of the "Pin" on the UI if the user asks for it (so hashing doesn't work).
I understand DynamoDB is encrypted at rest. The question is should I be encrypting this value before storing it in the DDB and decrypting it before sending it back? Is there a point of doing that?
Anything else I should be doing here?
#paulsm4 already mentions a few valid points in his comment, let me expand on that.
The question is what you want to protect yourself against.
If you have a requirement to protect against somebody stealing the SSDs the data is stored on being able to read the data or any other kind of regulation that forces you to do encryption at rest, encryption at rest is sufficient.
If you want to protect yourself against your AWS admins being able to read the data in the table while still being able to manage the table itself, you can add explicit deny statements for dynamodb:Get*, dynamodb:Query, dynamodb:Scan and dynamodbBatchGetItem to their roles.
If you want to have an extra level of security on this particular attribute, you can encrypt it using symmetric encryption before writing it and decrypt it before you display it to your users. You can use KMS to do that. This way your admins could read the table but would only see the encrypted PIN. In order to decrypt that, they would need access to the key that was used to encrypt that particular field.
In this case you have to ensure that only your software is allowed to access the key to encrypt/decrypt the PIN and enforces appropriate authorization mechanisms to stop unauthorized users from decrypting the data.
I am working on a project where I need the functionality of user registration and user login. I need some suggestion. What would be the better way of achieving this task?
A.) Old school email & password OR B.) By using public & private keys?
What I understand from option B is that we need to enroll a user from CA from Fabric-SDK. Once enrolment of user is done, we can generate a unique password-phrase like the same is happening in Meta-Mask. We can store that user info along with its username (the default username in fabric is user1, user2) with password-phrase.During user login, it will ask for user's private key or the unique password-phrase generated for its account. The certificates will be stored in hfc-keystore (the default dir used in Hyperledger fabric). Whenever a transaction is executed by that user say user akshay.sood, we will set the context of that user to fabric-client (Please correct if I am wrong in this case).
Here, My questions/queries are:
1.) What do you prefer (email/password or private/public keys and why?).
2.) If you prefer 2nd mechanism then how will you protect user keys and certificates stored in hfc-keystore dir. I mean it can be hacked or data can be stolen by hacker.
3.) How to recover user private/public key and certificate if it is deleted mistakenly from hfc-dir.
4.) Would you prefer using password-phrase? if no, what do you prefer?
Edits are welcome.
Please let me know if you have any suggestion/improvements
Your question is a choice of your preference, convenience & business needs. You can use either or both approaches in combination. Asking the user to keep or manage his private keys calls for a managed wallet. However, IMHO, if you are concerned about leakage or loss of private keys then you would need a Hardware Security Module that is specifically designed for this purpose.
P.S. Fabric & its examples store the keys in hfc folder for simplicity, although not recommended in real cases.
How do I force AWS KMI to rotate a key after a compromise? It seems I can instruct AWS to automatically rotate keys once a year. But on demand, if compromised - doesn't seem possible. Specifically, the PCI-DSS requirements:
3.6.5
a) Do cryptographic key procedures include retirement or replacement (for example, archiving, destruction, and/or revocation) of cryptographic keys when the integrity of the key has been weakened (for example, departure of an employee with knowledge of a clear-text key)?
b) Do cryptographic key procedures include replacement of known or suspected compromised keys?
(When you say KMI, I guess you mean AWS KMS.)
This is a valid question. The way to rotate keys manually is to create a new key and change the alias from the old key to the new one. Unfortunately, most AWS resources use the key id, so you have to assess which one is still using the old one.
If you use Infrastructure as Code tools such as Terraform or Pulumi, you just need to taint the KMS resource, so it will be recreated with a new ID and if you did everything right, e.g. used the alias-based data queries in Terraform, you just need to run the pipelines for those resources, and you are good to go.
How do I force AWS KMI to rotate a key after a compromise?
Key rotation doesn't mitigate compromised key data.
Key rotation is a mechanism to prevent encrypting too many chunks of data (there is a math about relation between amount of encrypted data and probability of key revelation)
Basically the key rotation creates a new version of the key for new encryptions, but KMS will allow decrypting any ciphertext encrypted with the older key version.
See:
https://docs.aws.amazon.com/kms/latest/developerguide/rotate-keys.html#rotate-keys-manually
Unfortunately, most AWS resources use the key id, so you have to assess which one is still using the old one.
When using manual key rotation, the application needs to know which key is the current one (e.g. using an alias), but the ciphertext needs a reference to the key id/arn to decrypt.
But on demand, if compromised - doesn't seem possible.
By default the KMS key doesn't leave the hardware. There is no way the KMS key itself is compromised, so maybe an automatic rotation is feasible having all the advantages (keeping the same ARN/ID/alias)
However - the KMS is meant for envelope encryption, KMS is used to encrypt the random data-key or a service-specific key, which can be leaked theoretically. Then you need to create policies to manage this risk
So far most of our clients (online retailers and banks) have been reticent of placing any parts of theirs applications to a public cloud, although this could be a very cost effective manner to deal with temporary demand upsurge (end of month, holidays etc.)
We could place middle tier on a cloud so that no information is persisted in the cloud, or so that only non-sensitive data is stored there.
What are the best practices in this case?
Are there any regulations that I should be aware?
What are the biggest threats?
The best solution is to use cryptography.
You have the choice of public key cryptography: encrypt your data with a public key, put it "on ze cloud", then when you retrieve it, decrypt with your private key. Even better, if the data only transits through you, you can only have the public key and only your client has the private key.
Or symmetric cryptography, in which case you need the key, which will help encrypt and decrypt.
Symmetric cryptography algorithms are much faster, but if the scenario I mentioned above applies (ie, the client can have the private key), definitely go for it: you won't even be able to read the data without the client's consent.