Need help implementing key management scheme - encryption

Scheme has following requirements
Client application should perform encryption/decryption using
component 1, component 2 and ZPK (zone PIN key. Client should get
this key from host in encrypted form).
Host application should perform encryption/decryption using key MK
(master key formed from component 1 and component 2) and ZPK.
Here is how I'm generating components
Online-AUTH>GC
Enter LMK id [0-2]: 0
Enter key length [1,2,3]: 2
Enter key type: 002
Enter key scheme: u
Clear component: **** **** **** **** **** **** **** ****
Encrypted component: UXXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
Key check value: xxxxxx
Online-AUTH>GC
Enter LMK id [0-2]: 0
Enter key length [1,2,3]: 2
Enter key type: 002
Enter key scheme: u
Clear component: **** **** **** **** **** **** **** ****
Encrypted component: UYYYY YYYY YYYY YYYY YYYY YYYY YYYY YYYY
Key check value: yyyyyy
Online-AUTH>FK
Enter LMK id [0-2]: 0
Enter key length [1,2,3]: 2
Enter key type: 002
Enter key scheme: u
Enter component type [X,H,T,E,S]: e
Enter number of components [1-9]: 2
Enter component 1: UXXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
Component 1 check value: xxxxxx
Continue? [Y/N]: y
Enter component 2: UYYYY YYYY YYYY YYYY YYYY YYYY YYYY YYYY
Component 2 check value: yyyyyy
Continue? [Y/N]: y
Encrypted key: UZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ ZZZZ
Key check value: zzzzzz
What I don’t understand is
What are the benefits of creating MK using enciphered components How
to decrypt enciphered ZPK with component 1 and component 2.
What is the relation between component 1, component 2 and output
of FK command
Is encrypting PIN block under ZPK is enough/ubiquitous
Any help appreciated. PS I want to stick to ubiquitous implementations.

You are not first :)
I will try to explain (but my English not so good to be clear enough :( ).
HSM never works with plain keys, all the keys it processing, are encrypted under other, called Key Encryption Key (KEK), keys. The LMK is KEK which is securely stored in the secure environment, HSM. The main idea of HSM is, that you can not get real LMK key value, respectively, you can not get the real working key plain value. All the keys you are using with HSM are cryptograms. LMK is your personal KEK which is not accessible to other parties (what means it is secure KEK). These keys you should keep in database to use with your own HSM.
Sometimes, you need to transmit keys to other parties, eg, Visa or MasterCard to exchange some encrypted data like PIN-blocks. In that case you should use another KEK called ZMK. It is transport key which is used ONLY for other key exchange. You are unable to use ZMK encrypted keys with your HSM. First, you MUST import the key under your LMK to make it managanbe.
CONCLUSION:
1) You should keep in DB keys under LMK
2) Keys under ZMK are only used to be transmitted to other parties.
If I was not clear enough pls do not hesitate to ask, will try to find another explanation.

Related

Key verification in AES

If the user enters a wrong key for AES decryption, some garbage data is generated. I want to verify the given decryption key and throw an error if the key is incorrect. How can I verify the key entered by the user?
Use an HMAC. The basic premise is that you run the plaintext through an HMAC, add the result to the plaintext and then encrypt. Then do the opposite when decrypting. If the plaintext and HMAC result match, then you know you've got the correct key.
OR, if you want to know prior to decryption, use the key material provided by the user to derive two further keys (using, say PBKDF2). Use one for encryption and another for an HMAC. In this case, encrypt first and then apply the HMAC using the second key. This way you can compute the HMAC and check if it matches before you decrypt.
Simplest approach is to add a magic number to the plaintext file data in a predictable location before encrypting; when decrypting, if the magic number is wrong, you used the wrong key. Downside to this approach is that it cannot validate the integrity/authenticity of the entire message.
To do that, use AES in an authenticated mode (e.g. AES-GCM) which gives stronger guarantees that the rest of the message was not tampered with.
One common way used to verify if a key is correctly entered, without revealing the actual key, is by use of a KCV (Key Check Value). When you create the key you would at the same time calculate the KCV, when the key is then entered manually, you can verify the entry by re-calcuylating the KCV. This is eg. used when entering keys manually into HSM's from physical key letters.
To calculate a KCV for an AES key you encrypt an empty (0x00) block with the key and the first 3 bytes of the resulting encrypted block is then the KCV.
Take a look here

Generating a unique ID for DynamoDB with fewer bits than a UUID

For a DyanamoDB-backed web app, I need to generate unique, stable URLs that reliably refer to unique rows in the DynamoDB table.
In the past, for a PostgreSQL-backed application, I've had good results from using an auto-incrementing integer as primary key, and using a hashid of the integer:
In [1]: import hashids
In [2]: hasher = hashids.Hashids(min_length=5, alphabet='abcdefghijklmnopqrstuvwxyz0123456789')
In [3]: hasher.encode(12345)
Out[2]: 'e763y'
I would then use this in the URL:
http://example.com/random-mutable-title-e763y/
However, with DynamoDB, there are no auto-incrementing primary keys, and UUIDs are recommended instead.
However, UUIDs contain 128 bits, and the hashid of a UUID is much longer:
In [3]: import uuid
In [4]: hasher.encode(uuid.uuid4().int)
Out[4]: '5j257lmv00xwo5pvo132783jv0qkq'
It's prohibitively long for a URL, or at least plain ugly:
http://example.com/random-mutable-title-5j257lmv00xwo5pvo132783jv0qkq/
I've seen it recommended to simply mask the UUID:
In [5]: hasher.encode((uuid.uuid4().int & (1 << 64) - 1))
Out[5]: 'v0qnq92ml7oj382'
But even that seems a bit long:
http://example.com/random-mutable-title-v0qnq92ml7oj382/
I could saw off more bits:
In [6]: hasher.encode((uuid.uuid4().int & (1 << 32) - 1))
Out[6]: 'lj044pkn'
But that seems a bit dangerous:
In [7]: len(set(uuid.uuid4().int & (1 << 32) - 1 for _ in range(100000)))
Out[7]: 99999
What's the best/safest thing to do here? I don't anticipate a heavy write load to this table, so do I need to break down and implement an auto-incrementing integer scheme with conditional writes?
Update:
I just realized that if I right-shift 32 bits of a UUID1, it seems to be fairly unique:
In [8]: len(set(uuid.uuid1().int >> 32 for _ in range(1000000)))
Out[8]: 1000000
But will this come back to bite me? :D
Update 2:
To answer some questions from comments:
My application will be the only one writing to this table.
The application is written in Python.
The data schema for the table uses a hash key for the user ID and a sort key that varies depending on what's being stored in the row. Let's say I'm storing User records, a user's Projects, and Documents contained within the projects. I'll probably end up having a Global Secondary Index to support queries based on the URL hashid, unless the hashid and the record's primary key end up being equivalent.
Common queries for the table will be:
User by email (for logins) supported by another GSI
All Users (by hash key)
All of a User's Projects (using hash key and sort key beginswith())
A particular Project (supported by the GSI under discussion)
All Documents in a particular Project (hash key and sort key beginswith())
Individual document (supported by the GSI under discussion)

How to generate unique 56 bit key for a given input string

This is part of my homework question (but this is not the actual question),
In my question professor asked me to generate a unique 56 bit key to encrypt and decrypted a message. Both the sender and receiver shares a pass-phrase (password) only. There is no key exchange here.
How to get unique 56 bit key with the help of a pass-phrase??
Can i use hash? but how to get 56 bit hash value ??
Question : (relevant part)
Messanger app:
1) Alice and Bob share the same password (or passphrase), they must use the
password to set up the tool to correctly encrypt and decrypt messages shared
between each other.
2) Each message during Internet transmission must be encrypted using a 56-bit
key
3) DONOT directly use the password as the key, you have to generate the same
key between Alice and Bob to encrypt messages.
.......
.....
The keyword is Key derivation functions

Hashing and Salting confusion

I have read a lot about hashing and salting passwords. I know how hashing works, that is all very easy, but the thing I am confused about is salting.
If I hash and salt a password and stick it into the database, how can I check that password with the password given when a user tries to log-in. Surely because the salt is completely random, it will be near-impossible to get that salt again to be able to match the database
EXAMPLE:
//On create account.
hash(password + randomSalt) to the Database
//On log-in
hash(password + differentRandomSalt) compare to Database
You generate a random hash of a fixed length with every password you hash. Then you store that salt in combination with the computed hash into one database column.
When the user wants to login, you extract the salt-part from the database and can match the results.
Example:
var salt = GenerateSecureRandom(16) // generates e.g. 0x42552241
var saltedHash = Hash(salt + password)
Login scenario:
var saltedHash = GetSaltedHashFromDatabase()
var salt = GetFirstBytes(saltedHash) // 0x42552241
var hash = GetRemainingBytes(saltedHash) // 0x47111337
var match = IsMatch(hash, salt, userInput)
A database entry could look like this (where = is the salt and * is the hash):
0x4255224147111337
========********
For (much) more details have a look at: https://crackstation.net/hashing-security.htm
The salt is random for each different user/password combination. It's not random for the same user/password combination. If that would be the case, then you would not be able to verify the password, as you already found out. If a large enough salt is generated with a sufficiently secure random number generator then it would even be impossible to verify the password. The idea of the salt is to protect against rainbow table attacks as well as creating a different password hash for different users if the password is the same.
The salt is usually stored together with the username and password hash in the database. It could be made part of a special construct that contains the salt and the password hash or it could be stored in a separate column. Sometimes the password-hash is actually a special string containing both the salt and the hash in some kind of format (using hexadecimal or base64 encoding) that needs to be parsed, but it could also a binary value simply consisting of a statically sized salt and statically sized hash.
An example bcrypt string would be:
$2a$12$QyrjMQfjgGIb4ymtdKQXIewDBqhA3eNppF8qOrMhidnEbzNvmHqhy
which is constructed as in this SO answer.
Setup:
find user
receive & verify old + password (see below)
receive new password
generate random salt
calculate hash from password and salt
store salt & hash in database with user
Verification:
find user
receive password
retrieve salt & hash for user
calculate hash to verify from password and salt
compare and return result
Usually, for security reasons, you should try and do a time-constant compare, even if that's not really an issue for password hashing. Furthermore often no distinction is made between unknown user and wrong password, simply to avoid giving information to attackers.
It makes sense to construct your password hashing scheme in such a way that it allows for updates to the amount of iterations, hash size, hash function etc.

How to encrypt something so that can be decrypted using any two of three keys?

So say I want to encrypt a file and the only way I want it to be read is if two different people enter their keys. So, for instance there are four keys:
key1, key2, key3, key4.
If I encrypt it with key1 then the following combinations will decypt it:
key2,key3
key3,key4
key2,key4
Is this possible using a standard method?
Generate a unique content key to encrypt the message (this is common to many message encryption standards), then apply an erasure code scheme such as Reed-Solomon coding against that content key concatenated with enough additional random data to ensure that any m of n "shards" of the key can be put together to create the final key. Shards are only given out from the random data portion so that none of the shards given out contain actual bits from the content key. This way, any number of collected shards short of m does not give any useful information about the key itself.
EDIT: Reed-Solomon to generate key shards appears to be identical to Shamir's secret-sharing, first published in 1979; thanks to #caf for pointing out the article.
Generate a symmetric key key1 randomly and use it to encrypt the data, then generate key2, key3 and key4 from key1 using Shamir's Secret Sharing protocol.
To securely distribute key2, key3 and key4 you can then use a public key algorithm to encrypt them using the public keys of the recipients.
Say you're assigning keys x1, x2, .. xN
Encrypt the file with a master symmetric key M. Then store several encrypted copies of M:
Encrypted with x1 and x2
Encrypted with x2 and x3
Encrypted with x1 and x3
...
Any two keys will unlock one of the encrypted copies of the master, which will decrypt the file.
Not as you state it, I don't think. But you could get the same effect like this: Use public key crypto; now there are 4 public and 4 private keys. As person #1, encrypt your message with each pairwise combination of the other 3. E.g. encrypt the message with key 2, then encrypt that with key 3. Now encrypt the message with key 2, then encrypt that with key 4. Finally, 3 then 4. Now if any two of the others get together they can recover the original message.
make the fourth key the bitwise checksum of the other three... You could even sequentially increment which key had the checksum value.. so that
key 4 bit 1 was a checksum of bit 1 in keys 1-3, and
key 1 bit 2 was a checksum of bit 2 in keys 2-4, and
key 2 bit 3 was a checksum of bit 3 in keys 1,3,4, and
key 3 bit 4 was a checksum of bit 4 in keys 1,2,4, and
key 4 bit 5 was a checksum of bit 5 in keys 1,2,3,
etc. ...
kinda like striped raid 5 does...
This way, no matter which three of the four keys you had, you could recreate the missing one. use some combination of all four keys to encrypt the message.

Resources