erlang/otp

crypto module can sometimes decrypt with the wrong key

Closed this issue · 2 comments

Describe the bug
I'm not actually sure if this is a bug.

:crypto.crypto_one_time/4 will generally raise an error if given the wrong key for decryption. That's the behavior I expect.

But for some combinations of plaintext and incorrect decryption key, it will seem to decrypt successfully, except that the returned text will not be the same as the plaintext.

To Reproduce
Please forgive the Elixir code snippet.

encryption_key = <<240, 94, 230, 64, 244, 27, 127, 130, 109, 35, 244, 119, 228, 205, 130, 224, 248, 5, 159, 28, 180, 131, 13, 41, 205, 230, 57, 212, 46, 208, 55, 62>>
alt_key = <<193, 172, 221, 62, 186, 65, 168, 72, 56, 184, 55, 251, 61, 133, 57, 128, 104, 135, 15, 104, 32, 233, 205, 134, 0, 98, 132, 136, 74, 23, 124, 192>>
wrong_key = <<156, 101, 205, 112, 217, 30, 254, 204, 123, 252, 209, 32, 233, 93, 88, 250, 61, 250, 198, 149, 5, 135, 23, 231, 21, 11, 75, 125, 59, 193, 74, 0>>

plaintext = "൹ǚ᯷➠Ǡതጻᴣđƒ֧☏ኪⱫ᏷Ɠྃࠫ࢔໩Ȳ◈ࣲầ⭗ⓩώ␔ᙷ┧ۅდࡘ⏾"
ciphertext = :crypto.crypto_one_time(:aes_256_ecb, encryption_key, plaintext,
  encrypt: true,
  padding: :pkcs_padding
)

decrypted = :crypto.crypto_one_time(:aes_256_ecb, encryption_key, ciphertext,
  encrypt: false,
  padding: :pkcs_padding
)

# decrypted is the same as plaintext
IO.inspect ["decrypted correctly with encryption key?", plaintext == decrypted]

decrypted = :crypto.crypto_one_time(:aes_256_ecb, alt_key, ciphertext,
  encrypt: false,
  padding: :pkcs_padding
)

# decrypted isn't the same as plaintext, but also doesn't raise an error
IO.inspect ["decrypted correctly with alt key?", plaintext == decrypted]

# raises an ErlangError error like most wrong keys will
# ** (ErlangError) Erlang error: {:error, {~c"api_ng.c", 634}, ~c"Can't finalize"}
:crypto.crypto_one_time(:aes_256_ecb, wrong_key, ciphertext,
  encrypt: false,
  padding: :pkcs_padding
)

Expected behavior
I expected that an error would be raised anytime a key is given which is not the one the text was encrypted with. (I don't know if this expectation is itself correct, but I don't know how else to detect "wrong key".)

Affected versions
Tested with 27.0 and 26.2.5

frej commented

Encryption by itself does not provide any guarantees for integrity nor authentication. This is an unfortunately a common misconception. You need to use, for example, AES-GCM to get that.

[edit:] This seems like a good explanation.

What @frej said :-)

That you get any exceptions at all is an accident of the padding scheme being used. The padding can be obviously screwed up after being decrypted with the wrong key in which case an error is thrown, but it's fairly likely to look okay in which case you get a garbage return value instead.