margelo / react-native-quick-crypto

⚡️ A fast implementation of Node's `crypto` module written in C/C++ JSI
Other
718 stars 93 forks source link

🐛 Decryption error - privateDecrypt #494

Open Morgandri1 opened 2 weeks ago

Morgandri1 commented 2 weeks ago

What's happening?

I'm trying to decrypt a string encrypted with RSA-PKCS1, and i'm running into this same nondescript error.

[Error: Failed Cipher Operation - privateDecrypt]

I've narrowed it down to two possibilities: Incorrect keypair data formatted incorrectly

My current process being halted is:

is there any reason to assume the server is generating an improper keypair? I have verified the key itself is correct.

Reproducible Code

// handler.rs
for member in members {
    let mut user = users::get_user(&member)?;
    let pemkey = match base58_public_key_to_pem(&user.id) {
        Ok(pemkey) => {
            println!("{}", pemkey);
            pemkey
        },
        Err(e) => {
            println!("Key conversion error: {:?}", e);
            return Err(warp::reject::custom(InternalError::Unknown));
        }
    };
    let key = match encrypt_symetric_key(&pemkey, &key) {
        Ok(key) => key,
        Err(e) => {
            println!("Encryption error: {:?}", e);
            return Err(warp::reject::custom(InternalError::Unknown));
        }
    };
    let _ = chats::add_member(
        &ctx, 
        user.clone(), 
        key
    )?;
    user.chats.push(
        bs58::encode(encrypt_data(
            &base58_public_key_to_pem(&user.id).expect("Failed to convert key"), 
            ctx.id.as_bytes()
        ).expect("Failed to encrypt chat id")).into_string()
    );
    let _ = users::update_user(user)?;  
}

// rsa.ts
export function decryptMessageWithPrivateKey(encryptedMessage: Buffer, privateKeyPem: string): string {
    const decryptedMessage = QuickCrypto.privateDecrypt(
        {
            key: privateKeyPem,
            padding: QuickCrypto.constants.RSA_PKCS1_PADDING,
        },
        encryptedMessage
    );
    return decryptedMessage.toString('utf8');
}

// webserver.ts
this.retrieveData({ctx: decryptMessageWithPrivateKey(Buffer.from(base58.decode(chat)), cache.user.private_key)}).then((r: ChatResponse) => {
  this.cache.chats = [...this.cache.chats, {
    id: chat,
    ...r,
    messages: [],
    key: deriveChatSymKeyFromEncryptedKeys(r.symetric_keys, cache.user.private_key)
  }]
})

Relevant log output

ERROR  [Error: Failed Cipher Operation - privateDecrypt]

Device

iPhone 16 Pro iOS 18

QuickCrypto Version

0.7.5

Can you reproduce this issue in the QuickCrypto Example app?

1.0.0-beta3 does not implement privateDecrypt

Additional information

boorad commented 2 weeks ago

Someone needs to take a dive into the C++ implementation, which is a few years old, and fix things up. Also, more tests need to be ported from the node.js codebase.

Morgandri1 commented 2 weeks ago

Thanks @boorad, do you have any recommendations of what to do in the mean time? All other react-native libraries for RSA are immature and/or poorly documented. Many of which haven't been touched in years.

boorad commented 2 weeks ago

@Morgandri1 can you take the dive into C++ (using XCode) to see what's going on? Use this PR & branch, and the example app. Set some breakpoints in XCode in the C++ files. I've commented out all but the first test in PublicCipherTests.ts. Weird thing is that it passes sometimes :eyes:

Morgandri1 commented 2 weeks ago

To be perfectly honest, I have no idea where to start on that. not sure how to open the lib code in xcode before it compiles

Morgandri1 commented 2 weeks ago

@boorad I tried diving into the c++ and couldn't find the privateDecrypt or publicEncrypt functions. do you know where i should start?