설명
RSA 암호화에는 안전한 패딩이 필요합니다. NoPadding은 결정적이며 암호문 변조에 취약합니다. PKCS#1 v1.5 패딩(PKCS1Padding)은 복호화 오류나 처리 시간으로 패딩의 유효성을 구분할 수 있을 때 패딩 오라클(Bleichenbacher) 공격에 노출될 수 있습니다. 공격자는 이러한 응답 차이를 이용해 암호문을 단계적으로 복호화할 수 있습니다.
잠재적 영향
- 평문 노출 (Plaintext Disclosure): 패딩 오라클을 악용하여 암호화된 비밀값(토큰, 세션 키, 개인정보)을 복호화할 수 있습니다.
- 자격 증명/토큰 탈취 (Credential/Token Exposure): 로그인 토큰, API 키 등 민감한 값이 유출되어 계정 탈취로 이어질 수 있습니다.
- 무결성 훼손 및 메시지 변조 (Integrity Compromise): NoPadding 또는 취약한 패딩은 암호문 가변성(malleability)로 인해 의미 있는 변조를 허용할 수 있습니다.
- 보안 수준 강등 (Security Downgrade): 안전한 OAEP 대신 구식 패딩을 허용하면 시스템 전반의 암호 강도가 약화되고 다른 공격과 결합될 수 있습니다.
해결 방법
- 항상 OAEP 패딩을 사용하세요: Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding").
- 가능한 경우 OAEP 파라미터를 명시하세요: OAEPParameterSpec(SHA-256, MGF1 with SHA-256, PSource.PSpecified.DEFAULT).
- 기존 RSA 암호화 코드에서 "RSA", "RSA/ECB/PKCS1Padding", "RSA/ECB/NoPadding" 대신 OAEP를 사용하세요. 암호화·복호화 양쪽의 파라미터와 프로바이더 지원 여부를 확인하세요.
- 에러/예외 처리를 균일하게 하여 복호화 실패 원인을 구분 못 하게 하세요(오라클 형성 방지).
- 실제 서비스에서는 하이브리드 암호화를 적용하세요: 데이터는 AES-GCM으로 암호화하고, 무작위 세션 키를 RSA-OAEP로 래핑.
- 키 길이 최소 2048비트 이상을 사용하고, 최신 JCA/JCE 프로바이더를 적용하세요.
예시
변경 전
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));
}
}
변경 후
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));
}
}
설명:
- 변경 전: PKCS#1 v1.5 암호화는 복호화 측에서 패딩 오류를 구분할 수 있으면 패딩 오라클 공격에 이용될 수 있습니다. NoPadding 역시 결정적이며 암호문 변조에 취약하므로 대안으로 사용하지 마세요.
- 변경 후: OAEP의 해시와 MGF1 해시를 SHA-256으로 명시하여 파라미터를 일치시킵니다. 예시는 암호화만 보여 주므로, 복호화 실패에 대한 균일한 오류 처리는 별도로 구현해야 합니다.