Android端AES加密+RSA加密密钥,Node.js端AES解密失败求助
Hey there, let's break down why your Node.js AES decryption is failing while RSA works perfectly—cross-platform crypto issues almost always boil down to tiny mismatches in parameters or data handling. Here’s how to fix it:
1. Mismatched AES Encryption Parameters
This is the #1 culprit. Android and Node.js must use exact identical settings for AES:
- Cipher Mode: Double-check if you’re using CBC, ECB, or GCM on Android. For example, if Android uses
AES/CBC/PKCS7Padding, Node.js must useaes-128-cbc(with PKCS7 padding enabled, which is default in Node’s crypto module). - Initialization Vector (IV): If using CBC mode, the IV generated on Android must be sent to the server alongside encrypted data (IV doesn’t need encryption—it’s not sensitive). Most people forget this step, and without the correct IV, decryption will fail completely.
- Key Length: Ensure your AES key is strictly 128 bits (16 bytes). If Node.js ends up with a key of a different length, decryption will throw errors or produce garbage.
Example Fix Code
Android Side (CBC Mode):
// Generate AES key and IV SecretKey aesKey = KeyGenerator.getInstance("AES").generateKey(); byte[] iv = new byte[16]; // 16 bytes = 128 bits, matches AES block size new SecureRandom().nextBytes(iv); // Encrypt target string Cipher aesCipher = Cipher.getInstance("AES/CBC/PKCS7Padding"); aesCipher.init(Cipher.ENCRYPT_MODE, aesKey, new IvParameterSpec(iv)); byte[] encryptedData = aesCipher.doFinal("your_target_string".getBytes(StandardCharsets.UTF_8)); // Prepare data to send: IV (Base64) + ":" + encrypted data (Base64) + encrypted AES key (Base64) String ivBase64 = Base64.encodeToString(iv, Base64.DEFAULT); String encryptedDataBase64 = Base64.encodeToString(encryptedData, Base64.DEFAULT); // Encrypt AES key with RSA (your existing code here) String encryptedAesKeyBase64 = ...;
Node.js Side:
const crypto = require('crypto'); // Split received data into IV and encrypted content const [ivBase64, encryptedDataBase64] = receivedEncryptedData.split(':'); const iv = Buffer.from(ivBase64, 'base64'); const encryptedData = Buffer.from(encryptedDataBase64, 'base64'); // Decrypt AES key via RSA (your working code here) const decryptedAesKey = Buffer.from(rsaDecrypt(encryptedAesKeyBase64)); // Ensure this is raw 16-byte buffer // AES Decryption const decipher = crypto.createDecipheriv('aes-128-cbc', decryptedAesKey, iv); let decrypted = decipher.update(encryptedData); decrypted = Buffer.concat([decrypted, decipher.final()]); console.log(decrypted.toString('utf8')); // Should output your original string
2. Key Encoding/Decoding Mismatch
When you encrypt the AES key with RSA on Android, make sure you’re handling the key bytes correctly:
- On Android, use
aesKey.getEncoded()to get the raw 16-byte key, then encrypt that binary data directly (not a Base64-encoded string of the key). - On Node.js, after RSA decryption, you should have a raw 16-byte Buffer—don’t try to convert it to a UTF-8 string first, as that will corrupt the key.
3. Character Encoding Inconsistencies
Always explicitly use UTF-8 when converting strings to bytes on Android (getBytes(StandardCharsets.UTF_8)) and when decoding the decrypted buffer on Node.js (toString('utf8')). Using default system encodings (like GBK on some Android devices) will cause mismatches.
4. Padding Misalignment
Android’s PKCS7Padding is compatible with Node.js’s default padding (PKCS7), but if you’re using NoPadding on Android, you must disable auto-padding in Node.js:
const decipher = crypto.createDecipheriv('aes-128-cbc', decryptedAesKey, iv); decipher.setAutoPadding(false); // Only do this if Android uses NoPadding
- Print the Base64-encoded AES key, IV, and encrypted data from Android, then manually plug these values into Node.js to test decryption—this will isolate whether the issue is in data transmission or crypto settings.
- Verify the length of the decrypted AES key on Node.js: it must be exactly 16 bytes.
- Test with ECB mode first (not secure for production, but useful for debugging)—if decryption works, the problem is definitely related to IV handling.
内容的提问来源于stack exchange,提问作者Neron Joseph

