cheatfate / nimcrypto

Nim cryptographic library
MIT License
190 stars 23 forks source link

Encrypted string with aes-128-ecb can't be decrypted with different compiler #54

Closed sillagiusti closed 2 years ago

sillagiusti commented 2 years ago

I've an encrypted string generated by PHP:

$ciphertext = openssl_encrypt($plainText, "aes-128-ecb", $encryptionKey, OPENSSL_RAW_DATA);

Then, $ciphertext is going to be send through TCP Socket Client to a nim socket server.

On nim socket server, I've these instructions:

var decText = newString(2048)
var dectx: ECB[aes128]
dectx.init(encryptionKey)
dectx.decrypt(encryptedMessage, decText)
dectx.clear()
echo decText

Where encryptedMessage is $ciphertext sent by client and encryptionKey is the same key $encryptionKey.

If I compile with my GCC from AMD64 Architecture, everything works and decText shows the original plain text. But If I compile with mipsel-openwrt-linux-musl-gcc-7.5.0, decText shows a wrong result.

I supposed the issue is something about sizeof(uint), because in the first compiler I've sizeof(uint) = 8 and in second one sizeof(uint) = 4.

cheatfate commented 2 years ago

It should not matter, could you please provide some example input/output here? I need $plainText and $cipherText values on PHP side. You can use gist.github.com and put links there. If final binary is get cross-compiled there could be an issue with byte-order. So if real hardware running with bigEndian but binary thinks it should run with littleEndian it could generate absolutely incorrect result.

cheatfate commented 2 years ago

Could you please check this compilation for your mipsel-openwrt-linux-musl-gcc-7.5.0 compiler.

# This should switch code generation to generate code for `bigEndian`.
nim c --cpu:mips <project.nim>

and

# This should switch code generation to generate code for `littleEndian`.
nim c --cpu:mipsel <project.nim>

So according to my understanding mipsel is just little-endian version of mips. So you should first check your real hardware endiannes, and cross-compile your nim project appropriately.

sillagiusti commented 2 years ago

Here you are:

$plainText = "4 set 127.0.0.1 A01219 state '{}'";

For $cipherText I give you bin2hex() value after openssl_decrypt:

04cc2cc656be4d7d6f55dbcb9a5941e2e052b79b309c1c736805553def28fc84a311c9e09cc2571d52d05ce10ab1baac

And this is the same value printed from nim project (on both compiled binary).

But, after decrypt on nim I've two different results depending on architecture:

AMD64 Intel i9 (correct one):

3420736574203132372E302E302E312041303132313920737461746520277B7D270F0F0F0F0F0F0F0F0F0F0F0F0F0F0F

MIPS (bad one): DF9B61CBE06A702FEE5913AB9A8F08D55A27EBFAE7CFD529A8CC94683406D3D571C5012F2B49FF176EEF7FE976B11F76

on my nim.cfg, I've these settings:

# For OpenWRT, you will also need to adjust PATH to point to your toolchain.
mips.linux.gcc.exe = "/.../toolchain-mipsel_24kc_gcc-7.5.0_musl/bin/mipsel-openwrt-linux-musl-gcc"
mips.linux.gcc.linkerexe = "/.../staging_dir/toolchain-mipsel_24kc_gcc-7.5.0_musl/bin/mipsel-openwrt-linux-musl-gcc"

and I launch this to compile for MIPSEL:

nim c -d:release -d:useMalloc --checks=off --stackTrace=off --verbosity=0 --cpu=mips main.nim

the same command for AMD64, but without --cpu=mips option.

I've seen now your comment. Ouch! I need to check order-byte!

sillagiusti commented 2 years ago

Could you please check this compilation for your mipsel-openwrt-linux-musl-gcc-7.5.0 compiler.

# This should switch code generation to generate code for `bigEndian`.
nim c --cpu:mips <project.nim>

and

# This should switch code generation to generate code for `littleEndian`.
nim c --cpu:mipsel <project.nim>

So according to my understanding mipsel is just little-endian version of mips. So you should first check your real hardware endiannes, and cross-compile your nim project appropriately.

So, I added into nim.cfg:

mipsel.linux.gcc.exe = "/.../toolchain-mipsel_24kc_gcc-7.5.0_musl/bin/mipsel-openwrt-linux-musl-gcc" mipsel.linux.gcc.linkerexe = "/.../staging_dir/toolchain-mipsel_24kc_gcc-7.5.0_musl/bin/mipsel-openwrt-linux-musl-gcc"

and launching

nim c --cpu:mipsel <project.nim>

it works! Thank you very much. But I can't understand why.

cheatfate commented 2 years ago

Initially you have selected wrong architecture, mips and used it to compile your nim project into C files. mips architecture means that system.cpuEndian == bigEndian, so nimcrypto interprets all the integers as big-endian integers. But when you execute your binary on real hardware which was actually not mips but mipsel (which uses little-endian integers) everything got messed up. So if you using mipsel C compiler you should use --cpu:mipsel in your Nim command line.