Description
RSA encryption needs secure padding. NoPadding is deterministic and vulnerable to ciphertext manipulation. PKCS#1 v1.5 padding (PKCS1Padding) can expose a padding oracle, such as a Bleichenbacher attack, when decryption errors or processing times distinguish valid from invalid padding. An attacker can use those response differences to decrypt ciphertext incrementally.
Potential impact
- Plaintext disclosure: a padding oracle can expose encrypted secrets such as tokens, session keys, and personal data.
- Credential or token theft: disclosed login tokens or API keys can lead to account compromise.
- Integrity loss: raw RSA or vulnerable padding can permit meaningful ciphertext manipulation.
- Reduced cryptographic protection: allowing legacy padding instead of OAEP can weaken the system and combine with other attacks.
Remediation
- Use OAEP padding:
Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding"). - Specify the OAEP parameters explicitly where possible:
OAEPParameterSpecwith SHA-256, MGF1 with SHA-256, andPSource.PSpecified.DEFAULT. - Replace
"RSA","RSA/ECB/PKCS1Padding", and"RSA/ECB/NoPadding"in RSA encryption code with OAEP. Verify matching parameters and provider support on both the encryption and decryption sides. - Handle decryption failures uniformly so that error details do not create an oracle.
- Use hybrid encryption in applications: encrypt data with AES-GCM and wrap a random session key with RSA-OAEP.
- Use RSA keys of at least 2048 bits and maintain the JCA/JCE provider.
Examples
Before
java
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
public class InsecureRSAExample {
// 취약: PKCS#1 v1.5 패딩 사용
public static byte[] encryptPassword(String password, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); // BAD
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(password.getBytes(StandardCharsets.UTF_8));
}
}
After
java
import javax.crypto.Cipher;
import javax.crypto.spec.OAEPParameterSpec;
import java.security.spec.MGF1ParameterSpec;
import javax.crypto.spec.PSource;
import java.nio.charset.StandardCharsets;
import java.security.PublicKey;
public class SecureRSAExample {
// 안전: OAEP(SHA-256, MGF1) 사용
public static byte[] encryptPassword(String password, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
OAEPParameterSpec oaep = new OAEPParameterSpec(
"SHA-256",
"MGF1",
MGF1ParameterSpec.SHA256,
PSource.PSpecified.DEFAULT
);
cipher.init(Cipher.ENCRYPT_MODE, publicKey, oaep);
return cipher.doFinal(password.getBytes(StandardCharsets.UTF_8));
}
}
Explanation:
- Before: PKCS#1 v1.5 encryption can be exploited through a padding oracle if the decrypting system distinguishes padding errors.
NoPaddingis also deterministic and malleable, so it is not a suitable alternative. - After: The example explicitly uses SHA-256 for both the OAEP hash and the MGF1 hash. It demonstrates encryption only; uniform handling of decryption failures must be implemented separately.