나쁜 암호 기술을 작성하는 사람은 없다. 단지 네 가지 계층에서 올바른 암호 기술을 작성할 뿐이다.
요약
안전한 암호 기술 구현을 위해 고려해야 할 네 가지 계층(기본 요소, 모드, 파라미터, 사용법)을 설명합니다. 단순히 알고리즘을 교체하는 것을 넘어, 각 계층의 결함을 파악하는 것이 보안 리뷰의 핵심임을 강조합니다.
핵심 포인트
- 암호 구현은 Primitive, Mode, Parameter, Usage의 4단계 계층으로 구분됨
- 알고리즘 업그레이드(계층 1)만으로는 심층적인 보안 결함을 해결할 수 없음
- 정적 IV나 타이밍 공격 같은 계층 3, 4의 결함이 가장 발견하기 어렵고 위험함
- 보안 리뷰 시 단순 규칙 목록보다 계층적 접근 방식이 더 효과적임
내가 가장 자주 작성하고, 동시에 가장 자주 후회했던 코드 리뷰 코멘트는 바로 이것이다.
"더 강력한 알고리즘을 사용하세요."
이 코멘트가 후회스러운 이유는 그것이 실제 결함인 경우가 거의 없기 때문이다. 그것은 내가 서 있는 위치에서 보이는 결함일 뿐이다. 팀이 SHA-1을 SHA-256으로 교체하면 모두가 리뷰가 유용했다고 동의하지만, 정작 중요한 문제는 여전히 제자리에 남아 있게 된다.
다음 계층을 숨기는 네 가지 계층
암호 호출(crypto call)은 네 번의 별도 단계에서 올바르게 이루어져야 하며, 한 계층에서 올바르면 다음 계층은 보이지 않게 된다. AES는 이미 당신이 내린 결정처럼 보일 것이다. 총 네 단계다.
계층 1 — 기본 요소 (the primitive). {#layer-1} 올바른 종류인가? KDF (Key Derivation Function)가 필요한 곳에 해시(hash)를 사용했는가? MAC (Message Authentication Code)이 필요한 곳에 암호(cipher)를 사용했는가? CSPRNG (Cryptographically Secure Pseudo-Random Number Generator)가 필요한 곳에 Math.random()을 사용했는가? 함수 이름에 드러나기 때문에 모두가 이 계층을 리뷰한다.
계층 2 — 모드 (the mode). {#layer-2} 기본 요소는 맞지만 모드가 틀렸다. ECB 모드의 AES는 동일한 블록을 동일한 암호문으로 암호화한다. 유명한 펭귄 그림이 "암호화" 후에도 여전히 읽을 수 있는 이유가 바로 이것이다. aes-256-ecb를 언뜻 보았을 때 틀렸다고 느껴지는 부분은 없다. aes와 256이 포함되어 있으며, 둘 다 안심을 주기 때문이다.
계층 3 — 파라미터 (the parameters). {#layer-3} 기본 요소도 맞고 모드도 맞지만, 입력값이 틀렸다. 정적 IV (Initialization Vector). 2015년에 설정된 후 다시 검토되지 않은 반복 횟수(iteration count). 누군가 RSA_PKCS1_PADDING을 명시적으로 전달한 RSA. Node.js는 기본적으로 OAEP를 사용하므로, 이 경우는 틀리기 위해 의도적인 인자가 필요하며, 이것이 바로 리뷰를 통과하는 이유다. 각각은 단일 값이며 대개 상수(constant)인데, 상수는 주의를 끌지 않는다.
계층 4 — 사용법 (the usage). {#layer-4} 위의 모든 것이 올바르지만, 주변 코드가 허점을 드러낸다. HMAC을 ===로 비교하여 타이밍 공격(timing attack)을 통해 정답을 유출하는 경우. 키를 올바르게 유도한 뒤, 이를 로그에 남기는 경우. 이 계층은 암호 코드가 전혀 아니기 때문에, 암호 리뷰에서 놓치게 된다.
왜 계층 구조가 규칙 목록보다 효과적인가
규칙 목록(rule list)은 무엇을 검색(grep)해야 하는지를 알려줍니다. 하지만 계층(layer)은 당신의 팀이 현재 어느 위치에 있는지, 그리고 따라서 무엇을 놓치게 될 것인지를 알려줍니다.
저의 가설 — 이는 측정된 수치가 아닌 가설입니다 — 은 실패 사례들이 해당 팀이 이미 암호 기술(crypto)에 얼마나 많은 주의를 기울였는지에 따라 군집을 이룬다는 것입니다. 한 번도 생각해 본 적이 없다면: 계층 1. 방금 감사를 마쳤다면: 계층 2 (감사 결과가 "프리미티브(primitives)를 업그레이드하라"고 했고, 정확히 그렇게 수행했기 때문입니다). 수년간 주의를 기울여 왔다면: 계층 3과 4.
이 가설이 맞다면, 불편한 결론은 계층 3과 4의 결함이 가장 오래 살아남는다는 것입니다. 왜냐하면 해당 코드가 "우리가 강력한 알고리즘을 사용하고 있는가"를 묻는 모든 리뷰를 통과하기 때문입니다. 처음 두 계층을 해결하는 성숙함이, 역설적으로 더 깊은 곳을 들여다보는 것을 멈추게 만드는 성숙함이기도 합니다. 이것이 제가 이 분류 체계(taxonomy)를 통해 가장 얻고 싶은 측정 지표입니다.
탐지: 쉬운 계층이 함정이다
계층 1과 2는 단일 호출 표현식(call expression) 안에 존재합니다. createHash("sha1")이나 aes-256-ecb는 문자열 리터럴(string literals)이며, 이를 매칭하는 것은 구문론적(syntactic)인 문제이기에 어떤 린터(linter)라도 잘 수행할 수 있습니다.
계층 3과 4는 그렇지 않습니다. IV(초기화 벡터)가 정적인지 여부는 그것이 어디에서 왔는지에 달려 있습니다. 이는 데이터 흐름(data-flow)의 문제이며, 패턴을 매칭하는 것과 값을 추적하는 것의 차이입니다. 비교 연산이 타이밍 공격에 취약한지(timing-unsafe) 여부는 해당 값이 비밀 값(secret)인지에 달려 있는데, 어떤 분석기(analyzer)도 표현식만으로는 이를 알 수 없습니다.
따라서 도구의 커버리지(coverage)는 결함이 얼마나 오래 생존하는지와 반비례 관계에 있습니다. 도구가 깔끔하게 커버하는 계층은 당신의 팀이 이미 수정하고 있는 계층입니다. 어떤 도구가 "암호를 커버한다"라고 주장한다면, 별도의 증거가 없는 한 이를 "계층 1과 2를 커버한다"로 해석하십시오. 이를 확인하기 위해서는 규칙의 개수가 아니라 정답이 알려진 코퍼스(corpus)가 필요합니다.
이것이 표준에서 차지하는 위치
이 계층들은 서로 구별되는 CWE(Common Weakness Enumeration)로 매핑되며, 이것이 바로 유용한 부분입니다. 분류 체계 (taxonomy)는 대부분의 리뷰에서 뭉뚱그려지는 차이점을 이미 부호화하고 있습니다:
네 가지 모두를 단순히 "취약한 암호 기술 (weak crypto)"로 분류하는 것은, 계층 3과 4의 사례들이 귀하의 버그 데이터에서 사라지게 만들고, 결과적으로 우선순위에서도 밀려나게 만드는 방식입니다.
읽어볼 가치가 있는 선행 연구: Egele 등이 작성한 An Empirical Study of Cryptographic Misuse in Android Applications (CCS 2013)는 암호 API를 사용하는 앱의 압도적 다수가 적어도 하나의 계층에서 오류를 범하고 있음을 발견했습니다. 10년 전의 연구이고 플랫폼도 다르지만, 이 계층 구조는 전혀 퇴색되지 않았습니다.
NIST SP 800-175B는 각 원시 요소 (primitive)의 용도에 대한 참조 표준이며, AES에 대한 Bernstein의 캐시 타이밍 (cache-timing) 연구는 왜 계층 4가 망상이 아닌지를 가장 명확하게 설명해 줍니다.
생성된 코드가 계층 2와 3에 머무는 이유
"Node에서 AES 암호화"를 요청받은 모델은 실행 가능한 무언가를 생성합니다. '실행됨'은 모델이 최적화하는 제약 조건이며, 이 계층들은 모두 그 제약 조건의 관점에서는 보이지 않습니다. ECB 모드도 실행됩니다. 정적 IV (초기화 벡터)도 실행됩니다. 1000번의 반복 횟수도 실행됩니다. 코드는 독자가 확인하는 계층에서는 올바르게 보입니다. 왜냐하면 모델이 '올바름'이 그렇게 보이는 말뭉치 (corpus)를 기반으로 학습되었기 때문입니다.
사람의 리뷰가 이를 놓치는 이유도 같습니다. 모델은 당신이 읽었던 것과 동일한 튜토리얼을 읽었습니다.
귀하의 코드베이스는 어느 계층에서 실패하고 있습니까? 그 답은 누가 작성했느냐보다 코드가 언제 작성되었느냐를 더 많이 말해주는 경향이 있습니다. 계층 2는 보통 "수년 전 한 번 감사(audit)를 받았다"는 것을 의미합니다.
저는 dev.to/ofri-peretz에서 측정 (measurement) 및 정적 분석 (static analysis)에 대해 글을 씁니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기