Advice on securing/encrypting a code - algorithm

I'm developing an application that on one side produces a code with certain information about a purchase, wich includes a credit information. For example, you could buy a given number of minutes to spend in a public PC on a cybercafe, and you receive a ticket with a number/code with that ammount of minutes, which is then decoded and processed by the PC blocking software in the public PC.
The full length of that information (including date of purchase, an ID, and so on) is about 12 bytes. I need to secure that data, obviously, as much as i need to make it unalterable.
I don't have experience on cryptography but have been reading a lot the last few days, so i came up with an scheme in which i encrypt the data using Twofish in CFB mode (to keep the ciphertext small), and add a 4 bytes long IV, randomly generated. I realize it's a short IV, but the reasoning behind is that an attacker should grab an apparently ridiculous ammount of tickets to become a thread with an IV of 65535 variations.
The problem i see (let alone the ones i miss) is that i also need to authenticate the code, since in CFB mode, a small change in the ciphertext produces just a small change in the plaintext, so anybody could change, for instance, its ticket's credit by just changing an A for a B.
So, first question is: is there any obvious problem in using the CRC16 of the plaintext as IV, and add it (unencrypted) to the encrypted code to use it both for authentication and IV? I repeat i'm not in cryptography, but it 'feels' odd to put some information about the plaintext unencrypted along with the cyphertext. But is just the gut feeling.
Or, instead, should i use a stream cipher? Which one could make a big change (/mess up) the plaintext from a small change in ciphertext. Is this related to the error propagation property in the cipher mode of operation?
Some guide, please?
Thanks a lot.
By the way, if that matters, im using mcrypt on PHP.
I must add that the other end of the app, the one that reads the ticket, is not (and cannot be) online. Sorry for that ommision.

It sounds like what you are looking for is either an HMAC or, if you cannot secure the client PCs, a digital signature, not encryption.

I would add some salt and produce an MD5 hash, delivered right with the plaintext

Related

How to check the validity of an AES algorithm?

I use a code who do AES encoding, and I use it for more than 10 years. The problem i don't know if this code is well written or not! The algorithm was written more than 15 years ago, is very tiny (only one hundred of lines) and can compile on ios/android/windows 32bit-64bit/MacOs.
For example in the code i saw that :
The password is hashed with MD5 (so in 16 bytes) before to be send to the encryption algorithm. I can of course change this part easily but what other algorithm to use ? SHA2 ?
The iV is initialized with current time, and then the first block of the compression output is the iV (so it's public). Don't know if it's good or bad !
What else i need to check ?
Now how can i check the validity of the output to know if everything work as expected ?
use a code who do AES encoding, and I use it for more than 10 years. The problem i don't know if this code is well written or not!
It is called encryption. And from the question ( ~ 100 lines) I assume you'd like to validate a code which is using AES encryption, not the AES encryption itself. I wrote a small blog about encryption. It is focused on Java, but principles are universal
The password is hashed with MD5 (so in 16 bytes) before to be send to the encryption algorithm. I can of course change this part easily but what other algorithm to use ? SHA2 ?
Do you mean - hash of the password is used as an encryption key? (I see that often)
If that's the case, it may be not sufficient today. If the passwords are human-provided (not long random data with high entropy), it's better to use some PBKDF to generate an encryption key from a password.
The iV is initialized with current time, and then the first block of the compression output is the iV (so it's public). Don't know if it's good or bad !
IV needs to be unique and may be public. Some encryption modes (e.g. CBC) requires IV to be unpredictable (random)
What else i need to check ?
You may check if the AES implementation itself is provided by some mature library/framework to prevent some side-channel attacks.
As well data should be authenticated (signed, appended hash, ..) to prevent maleability (it is called authenticated encryption)
Now how can i check the validity of the output to know if everything work as expected ?
well - it's only you who can tell of the output is correct or not.

Verify validity of a key without weakening of the chipher strength

I have a very large block of code (few seconds to crypt).
I use KeyA to encrypt it.
later in the process, i receive a key (not necessarily KeyA)...
but i don't need to open the block yet,
what i really need, is to validate that this is really the Key that will open the code correctly.
I Assumed i can keep a known block, and encrypt it,
and in order to validate the key, only open it, but it feels like weakenning the power of the cryptography (brute-force is easier, one can learn few things about the key properties).
Does my assumption really weakening the chipher? why yes/why no?
Is there a different way to ensure the match of a key without opening the whole block.
I am assuming you are using Symmetric-Key Cryptography (the kind where the key used to decrypt the file is the same as the one used to encrypt it).
If the cipher is vulnerable to a Known-Plaintext Attack, then the known block of plaintext may reveal information about the key. The stream cipher used for ZIP files suffered from this problem. Because ZIPs are compressed, it was difficult to guess enough plain-text, but the checksum used to verify passwords (among other factors) helped provide sufficient plain-text for a practical attack.
In principle you could publicize the hash of KeyA (assuming that the hash algorithm is strong enough that it cannot be reversed, and that the hash algorithm isn't also used internally by the cipher). This would allow you to quickly reject invalid keys without changing the way the message is encrypted.
Taking this idea further, you could use a Message authentication code such as HMAC. A message authentication code will validate that the message (in this case your very large block of code, or perhaps just its file path) has not been tampered with, as well as validating that the key is correct.
If you are concerned that this will make brute force easier or expose properties of the key, you could split the key into two parts. The first part of the key could be purely for validation, and the second part purely for decryption. e.g. MyKey = AuthenticationPart,DecryptionPart
(Disclaimer: This is based on my very incomplete understanding of crypto. You might get better responses from the experts on security.stackexchange.com and/or crypto.stackexchange.com)

Using password salt as IV in password-based encryption

I need to write a simplified encryption API that can easily deal with symmetric encryption, either by using a random generated key or a password-derived key.
The password generation is performed with the PKCS5_PBKDF2_HMAC() function from the OpenSSL library and using EVP_sha256() as hashing algorithm and a random generated 16-byte salt.
The symmetric encryption is performed with the OpenSSL EVP API.
My question is: how (in)secure is it to use the password derivation salt also as the IV for encryption?
The reason behind this question is that this will allow me to simplify the API and the output stream in the following way:
for the encryption routine, a user would have to provide either the password or the secret key; based on whichever is provided, the code can decide if a key needs to be derived from the password or use the provided key as it is;
similarly, for the decryption routine, a user would have to provide either the password or the secret key; based on whichever is provided, the key could be re-derived from the password and the IV, which is also acting as a password salt (and is put first in the output stream, right before the ciphertext);
the output stream will consist only of the IV concatenated with the ciphertext, eliminating a separate salt;
the output stream will be the same for a random generated key or a password-derived key.
Note: the API automatically takes care of the salt/IV generation, which is randomly generated for each encryption session, so even if a password is reused, the key is guaranteed to be different.
Thank you in advance for your answers.
As it happens, I've run into pretty much exactly the same scenario while working on one of my own projects (where a message is encrypted in CBC-mode with a random IV, and the user can either specify a key or a textual password).
Similar questions are discused here and here. To summarize: the purpose of an IV is to ensure that ciphertext remains unique even if the key is reused. As long as you're generating a new IV per message like you said you are, the source of the key doesn't matter as much. Which means you're probably safe reusing the salt as the IV, as far as anyone knows right now. It doesn't even seem like it would even make sense for it to be an issue, because the salt gets put through a cryptographic hash before deriving the key in a different way; as long as you use a good hashing function in PBKDF2 (i.e. SHA-256 as mentioned above), a key so derived is indistinguishable from one which was randomly generated, which in this case it might have been.
However, people uncover unexpected things in the world of cryptanalysis all the time, and straight-up reusing the same data in two places is considered A Bad Thing in principle even if we don't know of any practical problems right this minute. Should you actually be worried about this? At my level of knowledge on cryptanalysis, I'm somewhere between "maybe" and "I don't know," which is a little too much uncertainty for my tastes, so I'm going with the "technically safer" course of action, which is generating separate IV and salt values. Transmitting both the salt and the IV is a perfectly cromulent security practice, and you have nothing to lose if the user directly inputs the key and the salt goes unused.

Public Initialization Vector?

I'm using an OpenSSL cipher in Ruby to send text between a client and server and apparently it's a good idea to employ an IV, but for decryption on the server-side, I'm going to need that IV which was generated client-side. My question is will I run into problems sending the IV over the network? I don't know the first thing about cryptography, so I have no idea whether the IV can be used to decrypt the message or not.
The IV is public information, it's totally fine to send it over the network. However, you should use a cryptographically secure random for every single encryption, especially if you are using CBC mode. Using a somehow predictable IV in a situation like that leaves your encryption vulnerable to certain kinds of attacks.
If you are completely new to cryptography and using Cipher, have a look at the docs, we added some information there that should help you getting started. It illustrates some best practices, among them is handling the IV correctly.
The IV ensures that even if you were to encrypt two identical plaintexts using the same key, they produce distinct ciphertexts (because a new, randomly generated IV should be used for every encryption).
The IV cannot be used to decrypt the message without the key, and does not need to be transmitted securely, so it can be safely sent over the network along with the encrypted message.

Algorithm for message code validation

If you read this thread before - forget everything I wrote, I must have been drunk when I wrote it. I'm starting over:
I'm currently working on a project where we will be using some sort of algorithm for validating user input. There are three parties to consider;
Client - Browsing our web pages
Company - We, handling the Client requests
3rd Party Company - Handling Client messages
On our web pages we will show the Client some information about a product. If he/she wants more information about the product he has to contact the 3rd Party Company and state the products code (not unique per se, but not common either). In return the Client will receive some other code from the 3rd Party Company which he should input on our web page, where we will validate the code for approval.
The best would be if we, the Company, had no interaction with the 3rd Party Company. Pure encryption is out of the picture because it generates a string that is too long. We are doing this by SMS, so the codes has to be short.
What I've come up with so far:
For every product I generate a somewhat unique code (it doesn't matter if it's unique or not really) in base 16 (0-f). The Client who wants more info about the product sends a SMS to the 3rd Party Company stating the products code. In return the Client receives the same code, but the digits are multiplied (possibly by 2) and converted to base 36. On top of that a last character is added to the code, a control number, to make the code valid for the Luhn algorithm in base 36. The user enters the received code and we, the Company, validate it on the server side against the product code (validate against Luhn, divide by 2 and switch back to base 16).
Does this sound reasonably safe and appropriate? Is it a valid way to send messages by three parties, when two of them shouldn't need to communicate?
Sorry for the edit, but my mind must have been elsewhere when I wrote the first post.
I think you are confusing things, if you use the Luhn algorithm, for example, it'll just return True or False on the checksum. The sample code you gave seems to indicate that you want to have some checksum result (ex. 12345) that can be hashed from two different values. This problem would be more difficult.
How will the third party create this value? Will you give them some Javascript code for them to execute, or some other language? Couldn't you have a shared secret key and they could symmetrically encrypt the value with that secret key, you could have them prefix the part they encrypt with some known value so you could verify it quickly.
Their code:
to_send = encrypted(shared_key, 'check' + code)
Your code:
unencrypted = decrypt(shared_key, to_send)
if not unencrypted.startswith('check'):
return False # failed check
OK, so you want no interaction between the other application and your application. And you would like to limit the codes to 6 characters. Here are my thoughts:
Use 10 characters, that will make brute-force attacks harder;
Use all Latin letters and digits - that will give you 36 possible character values;
Why not use some big number library and simply multiply your code (taken as a Base36 number) by some ludicrously large value (say, 2048 random bits). Then convert it to Base36 and take the last 10 digits. Or maybe first 5 and last 5. Or maybe some other combination dependant on the original code. I've no idea how cryptographically strong this will be (probably not much), but the effort to crack the code will doubtfuly be smaller than simply paying for the service.
Alternatively you could salt (prepend some secret string) your code and then calculate MD5 of it. Return the MD5 (or some N characters of it) to the user as your code. This should be pretty cryptographically OK, although I'm no expert. By converting the MD5 result to Base36 you could increase the strength of this algorithm.
Why a "checksum"? Can't the 3rd party run any little utility that you give them? All you need is a 5-digit encryptor that the 3rd party can run on their computer, feed the product code into, and send the 5-digit result to the client as the key code.
The encryptor always produces the same result from the same input.
Then, the client sends you the product code and the key code. You run the product code through an exact copy of that encryptor, and compare that result to the key code.
The security of this system can be enhanced without changing the fundamental architecture.
-Al.
Edit after some clarifications:
I still think that the product code and the matching 3rd party response cannot be constant - otherwise it can be shared will other users, which will thus be able to give the response code without going to the 3rd party.
If the product code is constant, a possible approach is that the 3rd party response depends on both the code and the user's phone number, and so is your validation. This way, each response is both product and user specific.
The specific permutation of the Luhn algorithm isn't too important in my opinion - if someone can crack one variation, he'll probably be able to crack another one.
Original Answer:
In short, I think you can use the Luhn algorithm, if you give the user a one-time ticket, valid for a limited amount of time.
First, if I understand the problem correctly, your product code cannot be constant - otherwise the response created by the 3rd party will always be the same for this product. This means the user will be able to use this code again later, or even give it to another user.
Therefore, I think you should generate and give the user a random new code per his request of information/access to the product. This code should be valid for this product for a limited period of time (an hour, a day, depending on your needs).
The response sent by the 3rd party to the user should be valid only when entered together with the code you provided to the user.
After validation, this code cannot be used until the specified time period is over.
As an option, I think you and the 3rd party can append something like the current date to the code and response pair during computation, so they are not always the same pair.
After long debates with the 3 Party Company we've concluded that the best solution will be if they pass the Clients SMS to me, I generate a new code and send it back to them which in their turn send a new SMS to the Client with the code I generated. Not optimal from my point of view, but at least I can now do it in any way I want.
Thanks for your input thou.

Resources