0
$\begingroup$

First of all, I would like to tell you guys that I'm a complete noob at cryptography in general, so please pardon any dumb stuff I may say.

Well, I have used a lot of cryptography libraries in a couple projects I have done in the past. They usually work like this:

Input: secure = cryptography('sensitive data', 'password, salt, key, whatever');

Output: U2FsdGVkX1/+sKF6K1TD2/wdHJRwhuwuYez4yESJxuI= ( or something like this)

Question is, when I run the exact same piece of code, the output is always different:

input: secure = cryptography('sensitive data', 'password, salt, key, whatever');

Output: U2FsdGVkX1+TkUfkTukfsEuSBMree9vg2I/ixgOZE1A= (different output from the first time)

Being completely ignorant about cryptography, I don't know why do they change like this every time I run the exact same piece of code again and again.

So, I would like to know, why do they behave like this? And, is there any cryptographic algorithm that always returns the same output when the sensitive string and the key are equal no matter how many times I run the code? Thank you very much.

$\endgroup$
4
$\begingroup$

I don't know why do they change like this every time i run the exact same piece of code again and again.

What you are actually doing here (under the hood) is most likely using a cryptographic system that was implemented to be as easy and as fail-safe as possible to use, so you just hand the algorithm the things it absolutely needs and it does the rest.

So I can imagine the flow to be roughly as follows (assuming password-based encryption):

  1. If there was no salt provided, generate your own using the system's random number generator.
  2. If there was no work factor provided, choose the strong default one.
  3. Use the salt, the password and the work factor, to run them through the deterministic password based key derivation function (PBKDF) and get a key in return.
  4. Generate a 12-byte to 16-byte IV at random.
  5. Use the key and the IV to instantiate an authenticated encryption mode (like AES-GCM)
  6. Encrypt the sensitive data using said instance, this results in a ciphertext and an authentication tag being generated.
  7. Base64-encode the concatenation of IV, the ciphertext and the authentication tag and return the result to the user.

As you see, the difference in look most likely comes from step 4. The reason it is there is becaue a) users tend to be bad at providing nonces / IVs and that's why the library probably has decided to do it itself and b) we need a unique nonce or else an attacker can detect duplicate messages.

And, is there any cryptography algorithm that always returns the same output when the sensitive string and the key are equal no matter how many times i run the code?

Yes, most core-algorithms of cryptography run fully deterministically, however then you need to ensure non-determinsm of the execution for security which is why some libraries takes this work off you.

| improve this answer | |
$\endgroup$
4
$\begingroup$

Two reasons why cryptographic algorithm often behaves as you observe (non-deterministically):

  1. When the objective is to encipher some secret, it is necessary for security in many scenario. Otherwise, an observation post sending its report which usually is "Nothing in sight anywhere" would always send the same cryptogram in this situation, allowing to discriminate this usual case from "Elbonian vessels by south".
    Things get worse with public-key encryption: if the encryption was deterministic, it would be possible to check a guess of the message; thus knowing that the message is the name of someone in class, someone with the class roll could break the encryption.

  2. In some other applications, some randomness is necessary for security, or strengthens it, because it makes internal values unknown or unpredictable to an adversary. An example is signature: many signature schemes (including DSA, ECDSA, and to a lesser degree RSASSA-PSS), rely on a random value drawn by the signer (that must imperatively remain secret in [EC]DSA), and influence the result.


Deterministic encryption can be done, but as stated above that tends to be a defect (in particular it prevents from meeting the standard academic goal of CPA security), thus this is uncommon.

I looks like what you are looking for is deterministic password-based encryption with salt. This could be done as follows:

  • turn password and salt into an AES key using a Password-Based Key Derivation function like PBFDF2, Bcrypt, or Scrypt (these are deterministic)
  • encipher the result using AES in CBC mode with the IV implicit and set to zero, and some standard byte padding.
  • move the last 16 bytes of the ciphertext in the front, and again encipher the result using AES in CBC mode with the IV implicit and set to zero (no byte padding is needed this time).

For decryption:

  • turn password and salt into an AES key as in encryption
  • decipher the ciphertext using AES in CBC mode with the IV implicit and set to zero, and move the first 16 bytes of the deciphered plaintext to the end
  • decipher the ciphertext using AES in CBC mode with the IV implicit and set to zero, and undo the byte padding.

The double encryption gives some level of insurance that plaintext with the same beginning won't be recognizable as such from the ciphertext.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.