Will any encryption scheme safely allow me to encrypt the same integer repeatedly, with different random material prepended each time? It seems like the kind of operation that might get me in hot water.
I want to prevent spidering of items at my web application, but still have persistent item IDs/URLs so content links don't expire over time. My security requirements aren't really high for this, but I'd rather not do something totally moronic that obviously compromises the secret.
// performed on each ID before transmitting item search results to the client
public int64 encryptWithRandomPadding(int32 id) {
int32 randomPadding = getNextRandomInt32();
return encrypt(((int64)randomPadding << 32) + id), SECRET);
}
// performed on an encrypted/padded ID for which the client requests details
public int32 decryptAndRemoveRandomPadding(int64 idToDecrypt) {
int64 idWithPadding = decrypt(idToDecrypt, SECRET);
return (int32)idWithPadding;
}
static readonly string SECRET = "thesecret";
Generated IDs/URLs are permanent, the encrypted IDs are sparsely populated (less than 1 in uint32.Max are unique, and I could add another constant padding to reduce the likelyhood of a guess existing), and the client may run the same search and get the same results with different representative IDs each time. I think it meets my requirements, unless there's a blatant cryptographic issue.
Example:
encrypt(rndA + item1) -> tokenA
encrypt(rndB + item1) -> tokenB
encrypt(rndC + item2) -> tokenC
encrypt(rndD + item175) -> tokenD
Here, there is no way to identify that tokenA and tokenB both point to identical items; this prevents a spider from removing duplicate search results without retrieving them (while retrieving increments the usage meter). Additionally, item2 may not exist.
Knowing that re-running a search will return the same int32 padded multiple ways with the same secret, can I do this safely with any popular crypto algorithms? Thanks, crypto experts!
note: this is a follow-up to a question that didn't work out as I'd hoped: Encrypt integer with a secret and shared salt
If your encryption is secure, then random padding makes cracking neither easier nor harder. For a message this short, a single block long, either everything is compromised or nothing is. Even with a stream cipher, you'd still need the key to get any further; the point of good encryption is that you don't need extra randomness. Zero padding or other known messages at least a block long at the beginning are obviously to be avoided if possible, but that's not the issue here. It's pure noise, and once someone discovered that, they'd just skip ahead and start cracking from there.
Now, in a stream cipher, you can add all the randomness in the beginning and the later bytes will still be the same with the same key, don't forget that. This only actually does anything at all for a block cipher, otherwise you'd have to xor the random bits into the real value to get any use out of it.
However, you might be better off using a MAC as padding: with proper encryption, the encrypted mac won't give any information away, but it looks semi-randomish and you can use it to verify that there were no errors or malicious attacks during decryption. Any hash function you like can create the MAC, even a simple CRC-32, without giving anything away after encryption.
(A cryptographer might find a way to shave a bit or two off due to the relatedness, will tons of plaintexts if they knew beforehand how they were related, but that's still far beyond practicality.)
As you asked before, you can safely throw in an unecrypted salt in front of every message; a salt can only compromise an encrypted value if the implementation is broken or the key compromised, as long as the salt is properly mixed into the key, particularly if you can mix it into the expanded key schedule before decryption. Modern hash algorithms with lots of bits are really good at that, but even mixing into a regular input key will always have the same security as the key alone.
Related
Why not to use OTP to encrypt more than one message but every encryption after the XOR do something like subtitution/ceasar cipher on the CT?
Reusing a one-time-pad is bad because it gives you information about the key.
p: a plaintext message to be encrypted: p_1 p_2 ... p_n
e_i: encryption of p_i with key k_i
otp: e_i = p_i^k_i for ii in 1..n
If you encrypt multiple messages and you xor them together you get something like
e1_1^e2_1 = p1_1^k_1^k_1^p2_1
and since k_1^k_1 cancels that becomes
e1_1^e2_1 = p1_1^p2_1
So you instantly learn information about the messages, but if you happened to know something about the input, you also learn something about the key.
By something like Caesar cipher you might mean
e2_1 = p2_1^(k_1+13)
That's assuming a 26-letter alphabet for your key and message space.
Unfortunately after 2 messages, your key wraps again, and you're back to the same problem you had before.
(there are other big problems too)
more generally, whatever simple thing you do , you give away information about the messages and typically key. The attacker can typically set up a big matrix of equations and use linear algebra to solve for the key once you give them enough information.
However if you take the simple thing you're doing and make it more and more complex and eventually get to a point where
kn: the key for the nth message
kn = f(k,n) for some function k
such that an attacker cannot learn significant information about f(k,n) givenf(k,m)forn != m, you've invented a stream cipher.
People do use stream ciphers all the time; they are not as secure as OTP, but they are a core of internet security.
The trick of course is figuring out a good functionf`; describing how to do that is beyond the margin of this question. (And besides I don't actually have that skill).
I was wondering if there is a protocol for this.
The idea is to have some encrypted data on a server.
Now I would like to find a protocol that fulfills the following requirements.
Since actively managing keys is beyond what most users are willing to put up with, a password protected key is stored on the server.
The server should not be able to decrypt the data. I.e. can not learn the password
Third parties should not be able to access the password protected key because they don't know the password.
There should only be one password. The problem is trivial to solve with 2 passwords. One to download the protected key and one to unprotect the key
The solution might involve some kind of zero-knowledge proof of knowledge of the password.
There is no problem generating multiple keys and authentication hashes from the same password. You shouldn't be sending the real password to the server in any case. You want to send it through PBKDF2 first. My usual recommendation for authentication looks like this:
salt = static-per-app-token + username
key = PBKDF2(salt, password, > 10000 iterations)
send key to server
on server: finalkey = SHA512(key) // This step keeps someone who steals your auth database from logging in
compare finalkey to database
Given that procedure, you can just modify the PBKDF2 step to generate a key twice as long as you need. The top X bytes are for authenticating, the bottom X bytes are for decryption. PKBDF2 can create as many bytes as you want, and having half the bytes doesn't help you figure out the other half.
For your specific problem, this is probably the most convenient and best performing. You could also do as you suggest, and use two different salts for PBKDF2. That is also fine. It just takes twice as long to compute. If that's not a problem, then it's a very simple solution and may be even more convenient depending on your code.
But just to take the discussion another step, let's say you didn't have a password. You had a (random) key, and you wanted to create independent keys from that. Or you have the output of PBKDF2 already, and want to expand it into more keys. In that case, you can expand an key using HKDF. The process is simple (|| means "concatenate"):
prk = psuedorandom key (your input key)
info = some-random-token || username
T(0) = empty string (zero length)
T(1) = HMAC-Hash(PRK, T(0) | info | 0x01)
T(2) = HMAC-Hash(PRK, T(1) | info | 0x02)
T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) ...
You keep building T(n) until you have enough bytes for all your keys. You glue all the T(n) results together, and slice it up to get your keys out. This is much faster than PBKDF2, and can be applied to the output of PBKDF2 if you want.
Take a look at the RNCryptor v4 spec for an example of a process for expanding a single password into a bunch of different keys and random values.
Passwords are still horrible, and none of this can fix badly chosen passwords, but that at least stacks the cards in your favor if the password is reasonably hard to guess.
I am tasked with implementing a dongle-based copy protection scheme for an application. I realize that no matter what I do, someone will crack it, but I want to at least make it a little more difficult than an if-statement checking whether a dongle is present.
My approach is to encrypt critical data that the application needs for proper execution. During runtime, the decryption key is retrieved from the dongle (our chosen model has some suitable API functions for that), the data is decrypted and the application is happy.
Of course, a determined attacker can intercept that decryption key and also get ahold of the decrypted data. That's ok. But what should be hard is to substitute their own data. So I'm looking for an encryption scheme where knowing the decryption key doesn't enable someone to encrypt their own data.
That's obviously asymmetric encryption. But for every such algorithm I found so far, the encryption (or public) key can be generated from the decryption (or private) key, which is exactly what I'm trying to avoid.
Note: simply signing the data won't help much, since (unless I'm totally misunderstanding such signatures) verifying the signature will just be another if-statement, which is easily circumvented.
So... any ideas?
The moment the private key is known to the attacker you won't have any secret information to differentiate yourself from the others.
To make it harder for the attacker: You might want to expire each pair (public key, private key) after an application specific time T and generate a new pair based on the previous pair both on the dongle and your own machine, independently. This way the attacker needs to have a constant access to the dongle to be able to encrypt his data with the new private key or to run his private_key_detection algorithm as often as T.
You probably want to run the decrypt on the dongle. There are a few pieces of hardware that help this (I just googled this one, for example.). There are likely many others....Dallas Semiconductor used to have a Java button that would allow you to run code on a small dongle like device, but I don't think they have it anymore.
Some of these allow you to execute code in the dongle. So maybe a critical function that is hard to recreate yet doesn't require high performance might work? Perhaps a license key validation algorithm.
Maybe you could include code in the dongle that has to be put into memory in order for the program to run. This would be a little harder to break, but might be hard to implement depending on what tools you are using to make your program.
You probably also want to study up on some anti-debugging subjects. I remember seeing a few publications a while back, but here is at least one. This is another layer that will make it harder to crack.
Dependency on an Internet connection may also be an option. You have to be careful here to not piss off your customers if they can't get your code to run without an Internet connection.
You can also check out FlexLM (or whatever it is called these days). It works, but it is a beast. They also try to negotiate a percentage of your company's gross profit for the license fee if I recall correctly (it's been years....I think we told them to stuff it when they asked for that.)
Good luck!
To answer my own question (somewhat), it is possible to do this with RSA, but most APIs (including the one of OpenSSL's crypto library) need to be "tricked" into doing it. The reason you can generate the public key, given the private key, is that
It is common practive for implementations of RSA to save p and q (those big prime numbers) in the private key data structure.
Since the public key (which consists of the modulus N and some exponent e) is public anyway, there's (usually) no point in choosing an obscure e. Thus, there are a handful of standard values that are used commonly, like 3 or 65537. So even if p and q are unknown, you might be able to "guess" the public exponent.
However, RSA is symmetrical in the sense that anything you encrypt with the public key can be decrypted with the private key and vice versa. So what I've done (I'm a monster) is to let the crypto library generate an RSA key. You can choose your own public exponent there, which will later be used to decrypt (contrary to the normal way). Then, I switch around the public and private exponent in the key data structure.
Some tips for anyone trying to do something similar with the crypto library:
In the RSA data structure, clear out everything but n and e / d, depending on whether you want to encrypt or decrypt with that particular key.
Turn off blinding with RSA_blind_off. It requires the encryption exponent even when decrypting, which is not what we want. Note that this might open you up to some attacks.
If someone needs more help, leave a comment and I'll edit this post with more information.
We've had to extend our website to communicate user credentials to a suppliers website (in the query string) using AES with a 256-bit key, however they are using a static IV when decrypting the information.
I've advised that the IV should not be static and that it is not in our standards to do that, but if they change it their end we would incur the [big] costs so we have agreed to accept this as a security risk and use the same IV (much to my extreme frustration).
What I wanted to know is, how much of a security threat is this? I need to be able to communicate this effectively to management so that they know exactly what they are agreeing to.
*UPDATE:*We are also using the same KEY throughout as well.
Thanks
Using a static IV is always a bad idea, but the exact consequences depend on the Mode of Operation in use. In all of them, the same plaintext will produce the same ciphertext, but there may be additional vulnerabilities: For example, in CFB mode, given a static key, the attacker can extract the cipherstream from a known plaintext, and use it to decrypt all subsequent strings!
Using a static IV is always a bad idea. Using a static key is always a bad idea. I bet that your supplier had compiled the static key into their binaries.
Sadly, I've seen this before. Your supplier has a requirement that they implement encryption and they are attempting to implement the encryption in a manner that's as transparent as possible---or as "checkbox" as possible. That is, they aren't really using encryption to provide security, they are using it to satisfy a checkbox requirement.
My suggestion is that you see if the supplier would be willing to forsake this home-brewed encryption approach and instead run their system over SSL. Then you get the advantage of using a quality standard security protocol with known properties. It's clear from your question that neither your supplier nor you should be attempting to design a security protocol. You should, instead, use one that is free and available on every platform.
As far as I know (and I hope others will correct me if I'm wrong / the user will verify this), you lose a significant amount of security by keeping a static key and IV. The most significant effect you should notice is that when you encrypt a specific plaintext (say usernameA+passwordB), you get the same ciphertext every time.
This is great for pattern analysis by attackers, and seems like a password-equivalent that would give attackers the keys to the kingdom:
Pattern analysis: The attacker can see that the encrypted user+password combination "gobbbledygook" is used every night just before the CEO leaves work. The attacker can then leverage that information into the future to remotely detect when the CEO leaves.
Password equivalent: You are passing this username+password in the URL. Why can't someone else pass exactly the same value and get the same results you do? If they can, the encrypted data is a plaintext equivalent for the purposes of gaining access, defeating the purpose of encrypting the data.
What I wanted to know is, how much of a security threat is this? I need to be able to communicate this effectively to management so that they know exactly what they are agreeing to.
A good example of re-using the same nonce is Sony vs. Geohot (on a different algorithm though). You can see the results for sony :) To the point. Using the same IV might have mild or catastrophic issues depending on the encryption mode of AES you use. If you use CTR mode then everything you encrypted is as good as plaintext. In CBC mode your first block of plaintext will be the same for the same encrypted data.
I would like to give customers a random-looking order number but use 0, 1, 2, ... in the backend. That way the customer gets a non-password-protected order status URL with the encrypted order number and they cannot look at other customers' order numbers by adding or subtracting 1. This might replace a scheme where random order keys are generated, checked for uniqueness among all the previous orders, and re-generated until unique. When the web server gets a request to view an order, it decrypts the order number and retrieves the order.
To keep the URL short, what "good" encryption algorithm has the shortest block size? Is this scheme a good idea? (What if I was encrypting Apple, Inc. employee ids to keep Steve Jobs from asking for Employee #0?)
Observe that all the package tracking websites allow you to track packages without authentication. It would be fine to limit the amount of information shown on the password-free order status page.
Most block ciphers are going to use larger than 32-bit sized blocks, for security reasons.
However, I found one that is made specifically for what you are doing: Skip32
You may consider using a GUID, but perhaps you have reasons you want to avoid that. (Say, your app is done already.)
Edit:
Actually, if a GUID is permissible, then that gives you a range of 128 bits. You could easily use any other block cipher. The benefit to having a larger space (at the cost of long ID strings) is that you'll have much more protection from people guessing IDs. (Not that it an order ID by itself should be a security token anyways...)
If your idea is that just knowing the order number (or URL) is enough to get information on the order then:
The order number space needs to be extremely large, otherwise attackers and/or customers will conceivably search the order space, to see what can be seen.
You should consider that an attacker may launch gradual probing from numerous machines, and may be patient.
Probing the order number space can be mitigated by rate limiting, but that's very hard to apply in a web environment -- it's hard to distinguish your customer access from attacker access.
Consider also that the order number is not much of a secret, people could be sending around in emails; once it's out, it's impossible to retract.
So, for the convenience of one-click check-my-order-without-logging-in, you have created a permanent security risk.
Even if you make the order number space huge, you still have the problem that those URLs are floating around out there, maybe in possession of folks who shouldn't have gotten them.
It would be much much better to require a login session in order to see anything, then only show them the orders they're authorized to see. Then you don't have to worry about hiding order numbers or attackers guessing order numbers, because just the order number isn't enough information to access anything.
Recently I started using Hashids set of small libraries. The idea is to encrypt a number or list of numbers into hashed string like:
12345 => "NkK9"
[683, 94108, 123, 5] => "aBMswoO2UB3Sj"
The libraries are implemented in popular programming languages by various authors. They are also cross-compatible, which means you can encode the number in Python and then decode it JavaScript. It supports salts, alphabet definition and even exclusion of bad words.
Python:
hashids = Hashids(salt="this is my salt")
id = hashids.encode(683, 94108, 123, 5)
JS:
var hashids = new Hashids("this is my salt"),
numbers = hashids.decode("aBMswoO2UB3Sj");
This is not govt proof encryption but totally sufficient for some non-predictable permalink sharing sites.
Issues of whether you should actually be doing this aside, here's a very simple block cipher with a fixed key (since you only seem to need one permutation anyway).
static uint permute(uint id)
{
uint R = id & 0xFFFF, L = (id>>16) ^ (((((R>>5)^(R<<2)) + ((R>>3)^(R<<4))) ^ ((R^0x79b9) + R)) & 0xFFFF);
R ^= ((((L>>5)^(L<<2)) + ((L>>3)^(L<<4))) ^ ((L^0xf372) + L)) & 0xFFFF;
return ((L ^ ((((R>>5)^(R<<2)) + ((R>>3)^(R<<4))) ^ ((R^0x6d2b) + R))) << 16) | R;
}
Skip32 is much better as far as 32-bit block ciphers go, but it's a bit heavyweight when three (long) lines would do. :-)
I prototyped this idea using Blowfish, a block cipher with 64-bit blocks.
I don't think this scheme is that great of an idea. Why aren't you verifying that a user is logged in and has access to view a specified order?
If you REALLY want to just have all orders out there without any authentication, a GUID would be best.
Or, you could try to come up with order numbers prefixed with something about the customer. Like (PhoneNumber)(1...100)
To meet the requirement you could simply use a hash such as SHA-1 or MD5 on your indexes. These will provide the adequate security you require.
To bring down the size you can change to a different encoding; such as 64 bit.
I'd also very strongly recommend insist on using a salt, otherwise the hash values could easily be broken.