요약

  • RFC 2047의 인코딩 워드는 헤더의 일부 영역에서 비(非)ASCII 텍스트를 운반한다. 이를 디코딩하면 표시 텍스트가 만들어질 뿐, 인증된 발신자 신원이 확인되는 것은 아니다.
  • 견고한 조사는 원시 헤더, 구문 분석, 문자셋, 주소, 서명 커버리지, 사용자에게 제시된 렌더링을 별도로 보존해야 한다.

사건 기록에서 이미지와 메시지 원문은 결코 같은 열에 놓여서는 안 된다. 이미지는 중요한 질문에 답한다. 그 사람이 그 시점, 그 클라이언트에서 무엇을 보았는가? 원문은 다른 질문을 던진다. 어떤 바이트가 수신되었는가, 필드는 어떻게 토큰화되었는가, 어떤 주소가 인식되었는가, 어떤 부분이 인증되었는가? 이 모든 것을 표시 이름으로만 축약하는 것은 변환 체계가 가장 유용해지는 순간 그 체계를 지워버리는 일이다.

1996년 11월에 Keith Moore의 이름으로 발표된RFC 2047은 매우 정밀한 변환을 규정했다. 메일은 역사적 헤더 문법, 즉 대체로 ASCII에 기반한 문법이 직접 표현할 수 없는 주제와 언어를 운반해야 했다. 또한 행을 접거나 필드를 이동시키거나 드문 구조를 잘못 해석하는 소프트웨어들 사이를 통과해야 했다. 해결책은 평범한 ASCII 문자로 이루어진 하나의 감싸개를 예약하여, 숙련된 독자가 표시 대상 텍스트를 다시 찾아낼 수 있게 한 것이다.

일반 형식은=?charset?encoding?encoded-text?=이다. 첫 번째 항은 문자셋, 두 번째 항은Q또는B방식, 마지막 항은 표현된 바이트를 담는다.B는 이 MIME 맥락에서 Base64를 재사용한다.Q는 quoted-printable과 비슷하며 밑줄 문자에 공백 값을 부여한다. 완전한 인코딩 워드는 75자로 제한되며, 이를 담는 행은 76자로 제한된다. 따라서 더 긴 텍스트는 여러 단위로 나눌 수 있다.

이 감싸개는 상호운용성 측면에서 큰 가치를 지닌다. 그 자체로는 복원된 텍스트가 지명하는 사람에 관해 아무것도 말해주지 않는다.

허용된 위치는 새로운 문법이 아니다

RFC는 인코딩 워드를 아무 곳이나 두는 것을 허용하지 않는다.Subject같은 필드의 텍스트를 대체하거나, 주석 안에 나타나거나, 문장을 이루는 한 단어가 될 수 있다. 특히 주소 앞에 오는 표시 이름(display name)이 그렇다.addr-spec안, 따옴표로 묶인 문자열 안,Received안, 그리고Content-Type이나Content-Disposition의 구조화된 매개변수 안에서는 금지된다.

운영상의 함의는 크다. 디코딩 후에는@, 콜론, 꺾쇠 괄호가 인접한 구문 기호와 정확히 같아 보일 수 있다. 그러나 그것은 구문상의 힘을 얻지 못한다. 독자는 먼저 구조화된 필드를 토큰으로 분석하고, 다음에 허용되는 위치의 인코딩 워드를 인식한 뒤, 표시 텍스트를 만들어야 한다. 새로 보이게 된 문장부호로 주소 분석을 다시 시작해서는 안 된다.

RFC 5322는 이렇게 메일박스 안에서 표시 이름과addr-spec을 구분한다. 전자는 사람의 읽기를 돕고, 후자는 주소의 문법에 속한다. 또한 메시지 형식에서 저자 역할을 표현하는From과 실제 전송을 책임지는 에이전트를 지칭할 수 있는Sender를 구분한다. 이 필드들은 주장을 제시한다. 그 문법의 적합성은 사람이나 그 사람의 행위 권한을 인증하지 않는다.

연락처 배지 뒤로 주소를 숨기는 클라이언트는 이 두 대상을 합쳐버린 것이 아니다. 그중 하나를 덜 보이게 선택했을 뿐이다.

화면이 더 이상 보여주지 않는 공간

인접한 두 인코딩 워드가 행상의 공백으로 분리되어 있으면, 그 공백은 표시 시 무시된다. 이 규칙 덕분에 이름 한가운데 인위적인 빈칸을 만들지 않고 긴 표현을 깔끔하게 접을 수 있다. 이 규칙은 또한 표시 문자열이 전송된 바이트의 전사(轉寫)가 아닌 이유를 설명한다.

각 단위는 독립적이다. 이스케이프 시퀀스나 멀티바이트 문자는 한 단위에서 시작해 다음 단위에서 끝날 수 없다. 그러나 여러 원시 표기가 같은 가시적 결과에 도달할 수 있다. 같은 글자를 표현할 수 있는 두 문자셋,Q와B방식, 서로 다른 접기 위치, 16진수 표기에서 허용되는 변형은 모두 표시 과정에서 사라질 수 있다.

그 반대도 똑같이 중요하다. 문자셋을 모르는 소프트웨어는 원시 구문을 유지하거나, 근사적인 표시를 시도하거나, 실패를 알릴 수 있다. 잘못된 형식의 워드가 메시지 전체를 막도록 강제하지는 않는다. 따라서 두 클라이언트가 같은 입력을 다르게 표시할 수 있으며, 서버의 유일한 캡처만으로는 독자의 경험을 재구성할 수 없다.

올바른 결론은 “디코딩은 위험하다”가 아니다. “디코딩은 출처(provenance)를 소모하는 관찰 가능한 행위다”라는 것이다.

직접 UTF-8: 다른 경로, 같은 구분

RFC 6532는 국제화된 메일 환경이 허용하는 경우, 나중에 많은 필드 본문에서 UTF-8을 직접 사용할 수 있게 한다. 이 RFC는 NFC 정규화를 권고하고, 동등하거나 혼동 가능한 유니코드 표현에 따른 보안 문제를 상기시킨다. 이때 RFC 2047 감싸개는 그 텍스트에 불필요해질 수 있지만, 바이트, 코드포인트, 글리프, 신원이 하나의 객체가 되는 것은 아니다.

실제 시스템은 혼재되어 있다. 한 메시지는 직접 UTF-8로 도착하고, 다른 하나는 인코딩 워드를 담고, 셋째는 게이트웨이를 통과했다. 관측 가능성이 최종 문자열만 보존한다면, 어느 경로가 선택되었는지, 치환이 있었는지, 어떤 정규화가 화면에 도달하기 전에 일어났는지 더 이상 설명할 수 없다.

서명은 자기 주제를 갖는다

RFC 6376은 또 다른 증거를 만든다. DKIM은 본문과 선언된 필드 목록에 정규화(canonicalization)를 적용하고, 주로 서명 도메인에 부착된 서명을 검증한다. 유효한 결과는 선택된 규칙과 도메인 키에 따라 해당 데이터가 보존되었음을 증명할 수 있다. 그러나 그것은 디코딩된 표시 이름을 검증된 사람으로 바꾸지 않으며, 보이는 모든 필드가 서명에 포함되었다는 보장도 하지 않는다.

따라서 “DKIM 유효”와 친숙한 이름을 나란히 놓는 패널은 하나의 접합을 만든다. 이를 감사하려면From필드의 정확한 인스턴스, 커버된 바이트, 서명된 필드 목록, 정규화 방식, 서명 도메인, 분석된 주소, 인식된 인코딩 워드, 최종 렌더링을 알아야 한다. 이 연결 지점이 없으면, 서로 다른 질문에 답하는 두 개의 정확한 결과가 하나의 일반적 인증처럼 보인다.

렌더링 영수증

방어 가능한 재구성은 관측 지점과 원시 필드의 보호된 해시에서 시작한다. 필드 순서, 접기와 줄바꿈, 파서와 디코더의 버전, 토큰 경계, 각 인코딩 워드의 위치, 선언된 문자셋,Q또는B선택, 오류와 치환 문자를 보존한다. 얻어진 코드포인트, 정규화, 문자 체계나 방향 경보를 기록하고, 표시 이름을addr-spec과 분리한다.

옆에는 DKIM 사실이 놓인다. 커버된 필드, 정규화, 결과, 서명 도메인. 마지막으로 실제로 렌더링된 텍스트, 인터페이스 언어, 대체 폰트, 표시된 경고가 온다. 바이트, 소프트웨어 버전, 화면 맥락에 대한 결함은 결함으로 남아 있어야 한다.

이 영수증은 잠재적으로 개인 데이터를 담는다. 따라서 무제한 수집을 정당화하지 않는다. 최소화, 접근 통제, 비례하는 보존 기간은 여전히 필요하다.

Keith Moore의 IETF 프로필은 그의 공개된 기여를 정리한다.University of Tennessee의 2008년 역사 문서는 그가 1991년부터 2007년까지 거기에서 일했으며, 1990년부터 IETF 표준화 그룹에 참여했다고 밝힌다. 이는 시점이 정해진 참고 자료일 뿐 현재의 직무는 아니다. 여기서 관련된 기여는 규칙 그 자체다. 이름을 읽을 수 있게 하되, 그 가독성이 발신자를 확립한다고 주장하지 않는 것이다.

출처