two-way keyed encryption/hash algorithm

2020-02-09 09:15发布

问题:

I am no way experienced in this type of thing so I am not even sure of the keywords (hence the title). Basically I need a two way function

encrypt(w,x,y) = z

decrypt(z) = w, x, y

Where w = integer 
      x = string (username)
      y = unix timestamp 

and z = is an 8 digit number (possibly including letters, spec isn't there yet.)

I would like z to be not easily guessable and easily verifiable. Speed isn't a huge concern, security isn't either. Tracking one-to-one relationship is the main requirement. Any resources or direction would be appreciated.

EDIT

Thanks for the answers, learning a lot. So to clarify, 8 characters is the only hard requirement, along with the ability to link W <-> Z. The username (Y) and timestamp (Z) would be considered icing on the cake.

I would like to do this mathematically rather than doing some database looks up, if possible.

If i had to finish this tonight, I could just find a fitting hash algorithm and use a look up table. I am simply trying to expand my understanding of this type of thing and see if I could do it mathematically.

回答1:

You just need to encrypt a serialization of (w, x, y) with a private key. Use the same private key to decrypt it.

In any case, the size of z cannot be simply bounded like you did, since it depends on the size of the serialization (since it needs to be two way, there's a bound on the compression you can do, depending on the entropy).

And you are not looking for a hash function, since it would obviously lose some information and you wouldn't be able to reverse it.

EDIT: Since the size of z is a hard limit, you need to restrict the input to 8 bytes, and choose a encryption technique that use 64 bits (or less) block size. Blowfish and Triple DES use 64 bits blocks, but remember that those algorithms didn't receive the same scrutiny as AES.

If you want something really simple and quite unsecure, just xor your input with a secret key.



回答2:

Encryption vs. Hashing

This is an encryption problem, since the original information needs to be recovered. The quality of a cryptographic hash is judged by how difficult it is to reverse the hash and recover the original information, so hashing is not applicable here.

To perform encryption, some key material is needed. There are many encryption algorithms, but they fall into two main groups: symmetric and asymmetric.

Application

The application here isn't clear. But if you are "encrypting" some information and sending it somewhere, then later getting it back and doing something with it, symmetric encryption is the way to go. For example, say you want to encode a user name, an IP address, and some identifier from your application in a parameter that you include in a link in some HTML. When the user clicks the link, that parameter is passed back to your application and you decode it to recover the original information. That's a great fit for symmetric encryption, because the sender and the recipient are the same party, and key exchange is a no-op.

Background

In symmetric encryption, the sender and recipient need to know the same key, but keep it secret from everyone else. As a simple example, two people could meet in person, and decide on a password. Later on, they could use that password to keep their email to each other private. However, anyone who overhears the password exchange will be able to spy on them; the exchange has to happen over a secure channel... but if you had a secure channel to begin with, you wouldn't need to exchange a new password.

In asymmetric encryption, each party creates a pair of keys. One is public, and can be freely distributed to anyone who wants to send a private message. The other is private. Only the message recipient knows that private key.

A big advantage to symmetric encryption is that it is fast. All well-designed protocols use a symmetric algorithm to encrypt large amounts of data. The downside is that it can be difficult to exchange keys securely—what if you can't "meet up" (virtually or physically) in a secure place to agree on a password?

Since public keys can be freely shared, two people can exchange a private message over an insecure channel without having previously agreed on a key. However, asymmetric encryption is much slower, so its usually used to encrypt a symmetric key or perform "key agreement" for a symmetric cipher. SSL and most cryptographic protocols go through a handshake where asymmetric encryption is used to set up a symmetric key, which is used to protect the rest of the conversation.



回答3:

You probably can't.

Let's say that w is 32 bits, x supports at least 8 case-insensitive ASCII chars, so at least 37 bits, and y is 32 bits (gets you to 2038, and 31 bits doesn't even get you to now).

So, that's a total of at least 101 bits of data. You're trying to store it in an 8 digit number. It's mathematically impossible to create an invertible function from a larger set to a smaller set, so you'd need to store more than 12.5 bits per "digit".

Of course if you go to more than 8 characters, or if your characters are 16 bit unicode, then you're at least in with a chance.



回答4:

Let's formalize your problem, to better study it.

Let k be a key from the set K of possible keys, and (w, x, y) a piece of information, from a set I, that we need to crypt. Let's define the set of "crypted-messages" as A8, where A is the alphabet from which we extract the characters to our crypted message (A = {0, 1, ..., 9, a, b, ..., z, ... }, depending on your specs, as you said).

We define the two functions:

crypt: I * K --> A^8.
decrypt A^8 * K --> I

The problem here is that the size of the set A^8, of crypted-messages, might be smaller than the set of pieces of information (w, x, y). If this is so, it is simply impossible to achieve what you are looking for, unless we try something different...

Let's say that only YOU (or your server, or your application on your server) have to be able to calculate (w, x, y) from z. That is, you might send z to someone, and you don't care that they will not be able to decrypt it.

In this case, what you can do is use a database on your server. You will crypt the information using a well-known algorithm, than you generate a random number z. You define the table:

Id: char[8]
CryptedInformation: byte[]

You will then store z on the Id column, and the crypted information on the corresponding column.

When you need to decrypt the information, someone will give you z, the index of the crypted information, and then you can proceed to decryption.

However, if this works for you, you might not even need to crypt the information, you could have a table:

Id: char[8]
Integer: int
Username: char[]
Timestamp: DateTime

And use the same method, without crypting anything.

This can be applied to an "e-mail verification system" on a subscription process, for example. The link you would send to the user by mail would contain z.

Hope this helps.



回答5:

I can't tell if you are trying to set this up a way to store passwords, but if you are, you should not use a two way hash function.

If you really want to do what you described, you should just concatenate the string and the timestamp (fill in extra spaces with underscores or something). Take that resulting string, convert it to ASCII or UTF-8 or something, and find its value modulo the largest prime less than 10^8.



回答6:

Encryption or no encryption, I do not think it is possible to pack that much information into an 8 digit number in such a way that you will ever be able to get it out again.

An integer is 4 bytes. Let's assume your username is limited to 8 characters, and that characters are bytes. Then the timestamp is at least another 4 bytes. That's 16 bytes right there. In hex, that will take 32 digits. Base36 or something will be less, but it's not going to be anywhere near 8.



回答7:

Hashes by definition are one way only, once hashed, it is very difficult to get the original value back again.

For 2 way encryption i would look at TripleDES which .net has baked right in with TripleDESCryptoServiceProvider.

A fairly straight forward implementation article.

EDIT

It has been mentioned below that you can not cram a lot of information into a small encrypted value. However, for many (not all) situations this is exactly what Bit Masks exist to solve.