integritee-network / worker

Integritee off-chain worker and sidechain validateer
Apache License 2.0
89 stars 46 forks source link

Unable to get `call_worker` decryption working with shielding key #987

Closed Kailai-Wang closed 2 years ago

Kailai-Wang commented 2 years ago

Hi we are starting to write e2e test for the sidechain in litentry, but somehow we couldn't get the decryption working inside TEE.

Steps that we have done:

We tried to use unchanged integritee-node and worker to avoid any mess-up from our side but it didn't help, unfortunately.

This is the F/E code that we used: https://github.com/litentry/tee-worker/tree/56-decryption-not-working/scripts/litentry/decryption-not-working

Have we done anything wrong? I'd appreciate any help, thanks!

haerdib commented 2 years ago

Let me just confirm: The error you're experiencing is the error ClientError::BadFormatDecipher? E.g. while retrieving the shielding key or while deciphering the encrypted call?

haerdib commented 2 years ago

Actually, I just noticed, that's a Bad error format. Failing to retrieving the key should generate a different error, sorry for this.

Kailai-Wang commented 2 years ago

No problem, yea we got errors when decryption, so BadFormatDecipher

masapr commented 2 years ago

Hi @Kailai-Wang do you still need help with this?

Kailai-Wang commented 2 years ago

Yes I do 😂 @haerdib noticed that we didn't do the reverse() as the encointer does.

We fixed that but somehow it still didn't work..

If you find it's hard to go into our code, it would also be super helpful if you have a working example

clangenb commented 2 years ago

Oh yeah, I remember that I also struggled for days to get this working with encointer. Unfortunately, the code from encointer is no longer in production (will be again in the next months). The only thing I can do here is trying to remember how I debugged back then, which is actually the pretty obvious stuff:

  1. Print the keys to see the settings (e, n) in both environments
  2. Deep dive the sgx-crypto lib to see, exactly, where the error gets thrown.
  3. Print the encrypted stuff on both sides to see the byteorder, do some trial and error with reversing the bytes of the encrypted data.

Lastly, this is an integration test from the wallet that used to be working: https://github.com/encointer/encointer-wallet-flutter/blob/76677651556c8b56d7de50dbec523dfa0dee5689/lib/js_service_encointer/test/cantillon.test-e2e.js#L91

Note: Even if the encointer code is no longer in production, the de/-encryption did not change, so the typescript code should still be somewhat valid at least when it comes to the key settings. Btw. It might be obvious, but did you set the keyopts? https://github.com/encointer/encointer-js/blob/af0331bf04e6a6e4b42cef1e930db1a8f7d822b6/packages/worker-api/src/parsers.ts#L38

clangenb commented 2 years ago

I remember again, this was the crucial part that I was struggling the most with: https://github.com/encointer/encointer-wallet-flutter/blob/76677651556c8b56d7de50dbec523dfa0dee5689/lib/js_service_encointer/test/cantillon.test-e2e.js#L105

haerdib commented 2 years ago

de-/encryption did not change, but the worker response did. We now return a hex encoded type with different Struct Wrappers. I believe there's an issue in the Type conversions. The rust-cli and the typescript-cli put together a different public key in the end.

The key opts are the same, that is not the problem.

haerdib commented 2 years ago

Findings

The retrieved key parts of the shielding key match the one from the worker, so a type decoding issue can be ruled out:

Worker-cli:

[2022-09-15T07:04:41Z ERROR itc_rpc_client::direct_client] got key: Rsa3072KeyPair: { n:71C6772C201761BA16137F60451F410EA14EC4B23C6F4B7270DD1F08FB63A6DC8AC49EAE97F5B83ABA531BD5CB1872E9BC51511D15083BCA146E76C547665E062DF9B248AAF9171FAFE53F78889AC0A1BF504BDD6FC6579EF8A8D2852D5734A5EED983D4835B92E220727A1B3B8299FEBC83AA05CC0FFC689CC00695DEAB98D97C20E6B86E399AB50312BD24E0E509DFFD7F542184CF77EF65392C5D1CADC0062C478D16604FB5A7166CB241159E514BF7536D393EBD5BEAA9A1FCFED08351B65CD46B12E963A92B69C18144DE7F9B96D05CB5F1172006F5CD46F6A753699642D3F0F4BD79BC97C09DB63E293E77024774B99B32A23B76A6BE568C4002CA46679B0BE877627F188410C2E2FF9064F9B3DF537FDABF056FEEB3CE33061069F56914BD2356242B3AD0DC521A838A2BEF626B4078E11DC8FBBC0AAF8FBE2B372EF385AE760C1C7CED27588B47539A468C7B2C9543FD0B183DECE5FCB29AEBB08BAA0C713DB7E3212C3EAD8A59BB12F0A35CCAB072652B6016548229D3E3A603C381, e:01000001 }

Typescript cli:

keyJson n 
0x71c6772c201761ba16137f60451f410ea14ec4b23c6f4b7270dd1f08fb63a6dc8ac49eae97f5b83aba531bd5cb1872e9bc51511d15083bca146e76c547665e062df9b248aaf9171fafe53f78889ac0a1bf504bdd6fc6579ef8a8d2852d5734a5eed983d4835b92e220727a1b3b8299febc83aa05cc0ffc689cc00695deab98d97c20e6b86e399ab50312bd24e0e509dffd7f542184cf77ef65392c5d1cadc0062c478d16604fb5a7166cb241159e514bf7536d393ebd5beaa9a1fcfed08351b65cd46b12e963a92b69c18144de7f9b96d05cb5f1172006f5cd46f6a753699642d3f0f4bd79bc97c09db63e293e77024774b99b32a23b76a6be568c4002ca46679b0be877627f188410c2e2ff9064f9b3df537fdabf056feeb3ce33061069f56914bd2356242b3ad0dc521a838a2bef626b4078e11dc8fbbc0aaf8fbe2b372ef385ae760c1c7ced27588b47539a468c7b2c9543fd0b183dece5fcb29aebb08baa0c713db7e3212c3ead8a59bb12f0a35ccab072652b6016548229d3e3a603c381
keyJson e 
0x01000001

The cyphertext from here on, is not changed any more, the worker is able to read the correct Vec value: https://github.com/haerdib/tee-worker/blob/e21e6910767d18335a4a1987f1edb62f66d9bc23/scripts/litentry/decryption-not-working/test.ts#L181 E.g. everything following this part, is for sure not part of the problem.

Open Problems

Therefore, two things may be the cause of the problem:

Useful links

Kailai-Wang commented 2 years ago

Thanks for looking into it!

We have made some experiments as well, it should have nothing to do with the TrustedCall construction. We couldn't even get enc-decryption of simple messages working:

We tried other JS-libraries and got the same result (decryption fail). However, TEE can decrypt text which is encrypted by itself using TEE's Rsa3072Pair.

Kailai-Wang commented 2 years ago

We suspect that the shielding key pair that is generated by TEE is either wrong or not compatible with the standard RSA key pair.

We have a bit of testing here: https://github.com/litentry/tee-worker/blob/56-decryption-not-working/scripts/litentry/decryption-not-working/plain_enc_dec_test.ts

We simply construct the keypairs using the components and try to encrypt/decrypt simple texts using both nodersa and crypto js-library:

Any ideas? @haerdib My colleague tried construction with golang and got the same result (error). reverse or not doesn't matter Or the key was generated correctly but wrongly printed?

I also checked encrypt_buffer and decrypt_buffer and didn't find obvious problems.

Kailai-Wang commented 2 years ago

We tried:

We have some doubts in the openssl version mismatch too:

Maybe it causes subtle differences?

haerdib commented 2 years ago

As far as I have read this shouldn't make any difference. But I haven't investigated.

I was able to make it work with a "normal" rsa rust crate: https://crates.io/crates/rsa

https://github.com/integritee-network/worker/blob/bh/litentry-shielding-key/cli/src/trusted_operation.rs#L199-L228

The key was to use from_le. Unlike "defaul"t openssl, intel does it just the other way round. Comparing the shielding key generated by teaclave with another one would also not help, because, here comes the funny part:

When calling encrypt, the first thing done, is that the key is changed to an intel rsa key:

    pub fn encrypt_buffer(self, plaintext: &[u8], ciphertext: &mut Vec<u8>) -> SgxResult<usize> {
        let pubkey = self.to_pubkey()?;
        ...
     fn to_pubkey(self) -> SgxResult<SgxRsaPubKey> {
        let result = SgxRsaPubKey::new();
        match result.create(
            SGX_RSA3072_KEY_SIZE as i32,
            SGX_RSA3072_PUB_EXP_SIZE as i32,
            &self.n,
            &self.e,
        ) {
            Ok(()) => Ok(result),
            Err(x) => Err(x),
        }
    }

https://github.com/apache/incubator-teaclave-sgx-sdk/blob/c70a82f708fd20e9fd0377990dde097d14024f7a/sgx_crypto_helper/src/rsa3072.rs#L246-L279

This SgxRsaPubKey is an intel wrapper and does the following:

//generate rsa key pair, with n_byte_size*8 mod size and p_e exponent
//
tmp_bn_e = BN_lebin2bn(p_e, e_byte_size, tmp_bn_e);
BN_CHECK_BREAK(tmp_bn_e);

https://github.com/intel/linux-sgx/blob/master/sdk/tlibcrypto/sgxssl/sgx_rsa_encryption.cpp#L52-L125

So comparing shielding keys does not help. During encryption, it gets exchanged. Heh.

What I was not able to find out yet, is why the typescript version did not work, as we all have tried the reverse thing quite extensively.

Should I investigate there further?

haerdib commented 2 years ago

Output of the branch:

~/integriTEE/worker/bin (bh/litentry-shielding-key ✗) ./integritee-cli -p 9994 -P 2094 trusted --direct --mrenclave 12PpbXPeKnUtAPWfL2GeCVppJDqZa9b9Xgvscb7PqryA set-balance //Alice 100
send trusted call set-balance(5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY, 100)
[2022-09-29T12:23:52Z ERROR integritee_cli::trusted_operation] serialized_pub_key"{\"n\":[153,41,193,143,96,200,211,24,29,110,220,248,26,73,1,246,41,181,18,126,158,144,155,71,70,172,0,213,186,23,206,118,75,49,23,22,37,59,11,123,41,66,111,43,87,248,78,111,153,173,196,8,10,47,89,11,14,81,72,10,89,113,113,249,126,4,240,14,192,11,248,20,24,53,207,70,142,50,76,107,106,186,76,168,219,55,0,145,112,66,218,110,8,181,64,171,190,39,51,218,7,222,134,104,91,79,7,229,91,196,210,211,29,174,120,89,0,25,191,48,45,26,92,84,20,150,48,37,37,184,236,159,81,248,126,150,16,185,31,212,181,242,49,71,146,4,158,83,49,245,195,98,235,27,153,28,121,177,56,71,239,73,124,194,37,166,198,18,194,89,164,158,74,180,83,115,106,29,164,108,31,82,228,97,29,129,186,102,76,182,213,71,67,79,85,167,117,232,20,158,232,14,216,51,247,252,254,25,12,184,63,153,183,16,170,106,199,123,86,210,135,18,110,108,12,33,170,206,96,13,84,155,113,143,3,109,194,252,153,232,144,203,141,210,213,204,143,150,89,139,59,122,34,186,193,245,223,238,233,140,217,79,126,211,191,167,196,150,108,146,174,254,67,111,214,209,169,170,101,248,106,247,178,70,8,77,84,111,229,133,103,71,199,111,219,81,27,245,1,193,237,236,164,66,241,124,169,96,98,251,151,116,251,58,44,136,154,161,79,60,22,216,52,9,21,37,235,174,68,173,10,59,81,168,31,156,33,144,63,158,24,246,45,178,1,236,94,102,172,244,121,82,250,34,193,163,171,50,91,6,166,167,97,228,248,142,148,79,242,16,2,199,26,123,42,35,237,172,3,99,174,38,80,178],\"e\":[1,0,0,1]}"
[2022-09-29T12:23:52Z ERROR integritee_cli::trusted_operation] n [153, 41, 193, 143, 96, 200, 211, 24, 29, 110, 220, 248, 26, 73, 1, 246, 41, 181, 18, 126, 158, 144, 155, 71, 70, 172, 0, 213, 186, 23, 206, 118, 75, 49, 23, 22, 37, 59, 11, 123, 41, 66, 111, 43, 87, 248, 78, 111, 153, 173, 196, 8, 10, 47, 89, 11, 14, 81, 72, 10, 89, 113, 113, 249, 126, 4, 240, 14, 192, 11, 248, 20, 24, 53, 207, 70, 142, 50, 76, 107, 106, 186, 76, 168, 219, 55, 0, 145, 112, 66, 218, 110, 8, 181, 64, 171, 190, 39, 51, 218, 7, 222, 134, 104, 91, 79, 7, 229, 91, 196, 210, 211, 29, 174, 120, 89, 0, 25, 191, 48, 45, 26, 92, 84, 20, 150, 48, 37, 37, 184, 236, 159, 81, 248, 126, 150, 16, 185, 31, 212, 181, 242, 49, 71, 146, 4, 158, 83, 49, 245, 195, 98, 235, 27, 153, 28, 121, 177, 56, 71, 239, 73, 124, 194, 37, 166, 198, 18, 194, 89, 164, 158, 74, 180, 83, 115, 106, 29, 164, 108, 31, 82, 228, 97, 29, 129, 186, 102, 76, 182, 213, 71, 67, 79, 85, 167, 117, 232, 20, 158, 232, 14, 216, 51, 247, 252, 254, 25, 12, 184, 63, 153, 183, 16, 170, 106, 199, 123, 86, 210, 135, 18, 110, 108, 12, 33, 170, 206, 96, 13, 84, 155, 113, 143, 3, 109, 194, 252, 153, 232, 144, 203, 141, 210, 213, 204, 143, 150, 89, 139, 59, 122, 34, 186, 193, 245, 223, 238, 233, 140, 217, 79, 126, 211, 191, 167, 196, 150, 108, 146, 174, 254, 67, 111, 214, 209, 169, 170, 101, 248, 106, 247, 178, 70, 8, 77, 84, 111, 229, 133, 103, 71, 199, 111, 219, 81, 27, 245, 1, 193, 237, 236, 164, 66, 241, 124, 169, 96, 98, 251, 151, 116, 251, 58, 44, 136, 154, 161, 79, 60, 22, 216, 52, 9, 21, 37, 235, 174, 68, 173, 10, 59, 81, 168, 31, 156, 33, 144, 63, 158, 24, 246, 45, 178, 1, 236, 94, 102, 172, 244, 121, 82, 250, 34, 193, 163, 171, 50, 91, 6, 166, 167, 97, 228, 248, 142, 148, 79, 242, 16, 2, 199, 26, 123, 42, 35, 237, 172, 3, 99, 174, 38, 80, 178]
[2022-09-29T12:23:52Z ERROR integritee_cli::trusted_operation] e [1, 0, 0, 1]
[2022-09-29T12:23:52Z ERROR integritee_cli::trusted_operation] rsa_pub_key_le RsaPublicKey { n: BigUint { data: [1788993794050435481, 17726529988500155933, 5159876808477422889, 8560806032882838598, 8866245321879400779, 8020621039667986985, 817736527487741337, 17974272215050899726, 1510970594495038590, 7731610246943028504, 10448412552060516970, 12340062026819322480, 7531951552130656190, 15263477986075561819, 3512553723664051741, 2679806792344279597, 10844377982213863461, 5130148313313556752, 7116801428380583058, 5132046909117635563, 1352951419178338799, 8310183970010847682, 7053853211289197930, 5176243785989521693, 11390984949543030595, 1873212633689624296, 7685974094797322252, 7813202778093157319, 11192585683357802764, 16760705400218816369, 10849115246091422608, 17708639867039877977, 15239705984858975967, 18351766526664943551, 17898899940400590659, 8022121534194906986, 5898431038658938341, 4802223608573326619, 8401460029830036721, 4345869850517453563, 12604208754405464086, 11249895461031161156, 12839188698297765921, 5943050204581129217, 458015499876377338, 5734365425184122790, 2533973095287492850, 12848812267315375341] }, e: BigUint { data: [16777217] } }
Trusted call 0xc8eb41308fdb584da99bb15f9924089e812d04c29a8d954bac838b97a1153c40 is Submitted
Trusted call 0xc8eb41308fdb584da99bb15f9924089e812d04c29a8d954bac838b97a1153c40 is InSidechainBlock(0x02ee8f042d6213d60896f5f474b40546f1dd87c99b575414568fcfae370f588c)
Kailai-Wang commented 2 years ago

Thanks @haerdib that's very valuable information 👍

Following your comment we went through a few tests and came to the conclusion that:

I hope it helps a bit too. This ticket can be closed 🙏

haerdib commented 2 years ago

Oh, geez. That's very valuable information. Thank you very much for reporting this!

@clangenb @echevrier please take note of the node-rsa thing.

clangenb commented 7 months ago

It seems that node-rsa is not broken per see, but it is no longer compatible with the crypto implementations in recent node-js versions. This commit fixed encryption on my end, and we can still use the very old code for the encointer-wallet app: https://github.com/encointer/encointer-js/issues/90#issuecomment-2041806528