jeroen / openssl

OpenSSL bindings for R
Other
65 stars 23 forks source link

Error: OpenSSL error in EVP_DecryptFinal_ex: bad decrypt #78

Closed VictorYammouni closed 4 years ago

VictorYammouni commented 4 years ago

Hello

I hope you are well and that you and your loved ones are in good health

I have already used the openssl package to create an application in Client / Server mode in R which works very well since 1 year now

The server create a 32 Bytes random key and send it to the client to be used for encrypt and decrypt with openssl::aes_cbc_encrypt and openssl::aes_cbc_decrypt functions

I want to create now a client in PYTHON while keeping the server in R

I use exactly the same mechanism to exchange the key between server an client

But i get an issue

Everything I encrypt in R is perfectly decrypted in PYTHON with this méthod:

rawText=binascii.a2b_hex(text) iv=rawText[0:16] rawText=rawText[16:] cipher = AES.new(key, AES.MODE_CBC, iv) answer = cipher.decrypt(rawText).decode("unicode_escape") answer=answer.strip()

However, what is encrypted in PYTHON with the following method

*text += ' ' (16 - (len(text) % 16)) iv = Random.new().read(16) cipher = AES.new(key, AES.MODE_CBC, iv) answer = binascii.b2a_hex(iv + cipher.encrypt(text.encode('unicode_escape'))).decode('ascii')**

generates an error in R

Error: OpenSSL error in EVP_DecryptFinal_ex: bad decrypt

do you have any idea about this problem?

Thank's

jeroen commented 4 years ago

Can you include an example of some text that you generated in python, and include the R code that you use to arrive at this error? I can only help you if I can reproduce the problem.

VictorYammouni commented 4 years ago

thank you very much for this quick response

The text

'c4ceb149e93a4c0246fad4ed0f2a60b2e6e193d19ced2221c4ef3b73579b825b'

The Key

dc d7 d2 4c c3 9c e6 52 46 8d 46 8b b7 36 9a 0e 2e d0 68 a7 76 8f 74 26 f8 b4 cb 4e d3 c0 8b 92

The Code

.hexToRaw<-function(hexString){ h <- sapply(seq(1, nchar(hexString), by=2), function(x) substr(hexString, x, x+1)) return(as.raw(strtoi(h, 16L))) } rawText<-.hexToRaw(text) IV<-rawText[1:16] rawText<-rawText[17:length(rawText)] answer<-rawToChar(openssl::aes_cbc_decrypt(rawText,key,iv=IV))

jeroen commented 4 years ago

I think something must have gone wrong when you export the 'text' from python.

Do you know what should be the outcome answer? One simple thing to test is reverse it:

openssl::aes_cbc_encrypt(answer, key, value)

And then you should see if the encrypted value you get from R, matches the encrypted value you got from python?

I suspect you have a bug somewhere where you convert between text and raw data, that results in corrupting the data.

Most applications use base64 encoding for storing raw data as string, instead of .hexToRaw. Try adapting your code such that iv and key and encrypted text are converted to base64 strings (in R using base64_encode and base64_decode). That might make the conversion between R and python more robust.

VictorYammouni commented 4 years ago

The expected text : Victor

i'll use the reversed test to see what's wrong.

Thank's fro advises

VictorYammouni commented 4 years ago

Hello again

In PYTHON, the cipher.encrypt function expects a text multiple of 16. Usually, I filled with spaces but this time, I wanted with a text of 16 characters: "Victor0123456789"

encrypted text in PYTHON gaves this 3914844a07dd63916f2d17d48a8c7721

But in R, the same thing gaves this: 8357e350c77355e042c5aa527eb324a9b3dfee2792564a74fca9d21517bd5cb1

it's Twice as long

To get the same length, i had to use in R this text : "Victor012345678" So, I think in R, it uses a multiple of 16 minus 1

Do you have any idea ?

Thank's

VictorYammouni commented 4 years ago

Hello

Finally, I found the problem but not yet the solution This is caused by the filling character up to the multiple of 16. I don't know wich character is expected by openssl on R

But I found an alternative solution. the trick is to fill up to 16 with \0 and then I add an additional 16 \20. and it works

I'm going to test this with longer strings than "Victor" to see if it holds up

If you know the fill character expected by the openssl package of R, it can help

Thank's

jeroen commented 4 years ago

The character fill is called padding. Afaik, we use the default padding in the openssl library: https://github.com/jeroen/openssl/blob/master/src/aes.c

VictorYammouni commented 4 years ago

THAT'S IT. It works

The padding for this version of Crypto Python package is manual. I found it by searching a little bit on the net

length = 16 - (len(data) % 16) data += chr(length)*length

Thanks a lot. You helped me well