인터넷 뱅킹과 같은 중요한 일을 웹에서도 할 수 있게 웹은 안전한 방식의 HTTP를 필요로 한다.
이와 같은 중요한 트랜잭션을 위해, HTTP와 디지털 암호화 기술을 결합해야한다.
아래와 같은 조건들을 제공해주어야 함.
HTTPS는 HTTP를 안전하게 만드는 방식 중에서 가장 인기 있는 것이다. 이를 사용하면, 모든 HTTP 요청과 응답 데이터는 네트워크로 보내지기 전에 암호화 된다.
여기서의 보안 계층은 안전 소켓 계층(SSL) 혹은 이를 계승한 전송 계층 보안(TLS)을 이용하여 구현된다.
HTTPS에 대해 자세히 이야기 하기 전, SSL과 HTTPS에서 이용되는 암호 인코딩 기법에 대한 약간의 배경지식을 알아보자.
기술과 용어
암호법은 메시지 인코딩과 디코딩에 대한 과학이자 기술이다.
암호법은 암호라 불리는 비밀 코드에 기반한다.
암호란 메시지를 인코딩 하는 어떤 특정한 방법과 나중에 그 비밀 메시지를 디코딩하는 방법이다.
책의 그림 14-3 참고
암호는 처음에 간단한 알고리즘으로 시작했지만, 기술이 진보하면서 보다 복잡한 암호로 메시지를 빠르고 정확하게 인코딩하고 디코딩하는 기계를 만들기 시작했다.
코드 알고리즘과 기계가 적에 손에 들어가도, 대부분의 기계들에는 암호의 동작방식을 변경할 수 있는 큰 숫자로 된 다른 값을 설정할 수 있는 다이얼이 달려있다.
➡️ 이러한 암호 매개변수를 키라고 부른다.
키에따라 디코딩이 제각각으로 동작한다.
오늘날의 거의 대부분의 암호 알고리즘은 키를 사용한다.
두 가지 주요한 발전
대칭키 암호법은 인코딩할 때 사용하는 키가 디코딩 할 때와 같은 것을 의미한다.
➡️ 아래 그림에선 (e = d)
인코더 -------------- 디코더
C = E(P,e) P = D(C,d)
P: 평문 P: 평문
e: 키 d: 키
E: 인코더 D: 디코더
C: 암호문 C: 암호문
평범한 대칭키 암호는 오늘날의 슈퍼 컴퓨터로 간단하게 뚫릴 수 있다.
그래서 키를 사용할 때, 비트수가 높은 것을 사용하는 것이 암호를 지키는데 안전하다.
대칭키 암호화의 단점 중 하나는 발송자와 수신자가 서로 대화하려면 둘 다 공유키를 가져야 한다는 것이다.
만약 N개의 노드가 있고, 각 노드가 N-1 상대와 은밀하게 대화를 나누어야 한다면, 대략 총 N^2개의 비밀 키가 필요하다.
한 쌍의 호스트가 하나의 인코딩/디코딩 키를 사용하는 대신 공개키 암호 방식은 두 개의 비대칭 키를 사용한다.
인코딩 키: 모두에게 공개되어 있는 공개키
디코딩 키: 호스트만이 갖고 있는 개인키
이렇게 하면 대칭 키의 쌍이 N^2으로 증가하는 것을 피할 수 있다.
공개키 비대칭 암호의 과제는 아래의 내용을 알고 있더라도 비밀인 개인 키를 계산할 수 없다는 것을 확신시켜주는 것이다.
➡️ 이 모든 요구를 만족하는 공개키 암호 체계중 유명한 하나는 MIT에서 개발한 RSA 알고리즘
공개키 암화 방식의 알고리즘은 계산이 느린 경향이 있다.
따라서 노드간 연결이 맺어지고 나서 이후의 나머지 데이터를 암호화할 때는 빠른 대칭 키를 사용하는 방식이 흔히 쓰인다.
암호 체계는 누가 메시지를 썼는지 알려주고 그 메시지가 위조되지 않았음을 증명하기 위해 메시지에 서명을 하도록 하는 데에 이용될 수 있다.
디지털 서명은 메시지에 붙어있는 특별한 암호 체크섬으로, 메시지를 작성한 저자가 누구인지 알려주고 메시지 위조를 방지한다.
저자의 개인 키는 일종의 '지문'처럼 사용된다.
디지털 인증서는 인터넷의 신분증이며 신뢰할 수 있는 기관으로부터 보증 받은 사용자나 회사에 대한 정보를 담고 있다.
디지털 인증서에는 공식적으로 '인증 기관'에 의해 디지털 서명된 정보의 집합이 담겨있다.
인증서 안에 존재하는 것들
디지털 인증서에 대한 전 세계적인 단일 표준은 없지만, 오늘날 사용되는 대부분의 인증서가 그들의 정보를 X.509라고 불리는 표준화된 서식에 저장하고 있다.
사용자가 HTTPS를 통한 안전한 웹 트랜잭션을 시작할 때, 최신 브라우저는 자동으로 접속한 서버에서 디지털 인증서를 가져온다. 이후 이것을 검사한다.
HTTPS는 HTTP 프로토콜에 대칭, 비대칭 인증서 기반 암호 기법의 강력한 집합을 결합하여 분권화된 글로벌 환경에서도 HTTPS를 매우 안전한 동시에 매우 유연하고 관리하기 쉽게 만들어 준다.
HTTPS는 HTTP 메시지를 TCP로 보내기 전에 먼저 그것들을 암호화하는 보안 계층으로 보낸다.
오늘날 HTTPS 보안 계층은, SSL과 그것의 현대적 대체품인 TLS로 구현되었다.
https
로 시작하는 스킴 접두사를 가진다.
또한 클라이언트는 서버에 443번 포트로 연결하고 서버와 바이너리 포매승로 된 몇몇 SSL 보안 매개변수를 교환하면서 '핸드셰이크'를 하고, 암호화된 HTTP 명령이 뒤를 잇는다
HTTPS에서의 절차는 TCP 연결이후, 클라이언트와 서버간 암호법 매개변수와 교환 키를 협상하면서 SSL 계층을 초기화한다.
핸드셰이크 완료 후 SSL 초기화가 완료되며, 클라이언트는 요청 메시지를 보안 계층에 보내는데, 이 메시지는 암호화되어 보내진다.
핸드셰이크에서는 다음과 같은 일이 일어난다.
서버 인증서는 조직의 이름, 주소, 서버 DNS 도메인 이름, 그외 정보를 보여주는 X.509 v3에서 파생된 인증서 이다.
웹 서버 인증서 검사를 위한 알고리즘의 단계는 아래와 같다.
날짜 검사
인증서가 유효한지 확인하기위해 시작 및 종료일을 검사
서명자 신뢰도 검사
어떤 인증 기관에의해 서명되었는지 확인한다.
서명 검사
공개키를 서명에 적용하여 체크섬 검사한다.
사이트 신원 검사
인증서의 도메인 이름과 서버의 도메인 이름과 비교하여 맞는지 검사한다.
가상 호스팅(하나의 서버에 여러 호스트 명)로 운영되는 사이트는 인증서와 관련하여 다루기 까다로운 무넺가 있어서 보통 이를 피하기 위해 리다이렉트하는 방법을 사용한다.
프락시를 사용하는 경우, 클라이언트가 서버로 데이터를 보낼때 암호화하면 더 이상 HTTP 헤더를 읽을 수 없다.
이러한 경우 사용하는 것이 HTTPS SSL 터널링 프로토콜 이다. 이를 사용하면 클라이언트는 이 내용을 프락시가 읽을 수 있도록 암호화가 시작되기 전에 평문으로 말해준다.
HTTP는 다음을 보장한다.
Content-Type
미디어 포맷 또는 Content-Langugage
헤더를 이용)하여 브라우저나 다른 클라이언트가 콘텐츠를 바르게 처리할 수 있게함Content-Length
와 Content-Encoding
헤더)Content-MD5
체크섬 이용)이 모든 것을 가능하게 하기 위해 HTTP는 콘텐츠를 나르기 위한 잘 라벨링된 엔터티를 사용한다.
HTTP 메시지를 인터넷 운송 시스템의 컨테이너라고 하면, HTTP 엔터티는 메시지의 실질적인 화물이다.
HTTP/1.1의 10가지 주요 엔터티 헤더 필드
엔터티 본문은 가공되지 않은 데이터만을 담고 있다.
이 데이터의 의미에 대해 설명하는 엔터티 헤더로
Content-Type
같은 엔터티가 있다.
이 헤더는 메시지의 엔터티 본문의 크기를 바이트 단위로 나타낸다.
➡️ 이 헤더는 서버 충돌로 인해 메시지가 잘렸는지 감지하고자 할 때와 지속 커넥션을 공유하는 메시지를 올바르게 분할하고자 할때 필요하다.
만약 인코딩이나 압축이 되었다면 압축된 후의 크기를 나타냄
옛날 HTTP는 커넥션이 닫힌 것을 보고 메시지가 끝났음을 인지했는데, Content-Length
가 없다면 클라이언트는 커넥션이 정상적으로 닫힌것인지, 전송 중 서버에 충돌이 발생한 것인지 구별 X
클라이언트는 메시지 잘림을 검출하기 위해
Content-Length
를 필요로 한다.
특히 캐싱 프락시 서버에 취약하여 이 위험을 줄이기 위해 이 헤더를 갖고 있지 않은 HTTP 본문은 캐싱 X(잘렸다는 것을 인지하지 못해 캐시가 이를 저장하고 계속해서 제공하기에)
Content-Length
가 잘못된 값을 담고 있는 경우 아예 빠진 것보다도 큰 피해를 유발할 수 있다.
Content-Length는 지속 커넥션을 위해 필수다.
➡️ Content-Length 헤더 없이 어디까지가 엔터티 본문이고 어디부터가 다음 메시지인지 알 수 없기 때문
이 헤더 없는 지속 커넥션을 만날 수 있는 상황은 청크 인코딩인 경우
청크 인코딩: 데이터를 각각이 특정한 크기를 갖는 일련의 청크들로 쪼개어 보내는것
HTTP는 보안을 강화하거나 압축을 통해 공간을 절약할 수 있도록 엔터티 본문을 인코딩할 수 있다.
이는 책 참고
HTTP가 일반적으로 TCP/IP와 같이 신뢰할 만한 전송 프로토콜 위에서 구현되지만, 여러가지 이유로 메시지의 일부분이 전송 중에 변형되는 일이 일어난다.
이러한 변경을 감지하기 위해 송신자는 데이터에 대한 체크섬을 생성할 수 있고 수신자는 그 체크섬으로 기본적인 검사를 할 수 있다.
Content-MD5 헤더는 서버가 엔터티 본문에 MD5 알고리즘을 적용한 결과를 보내기 위해 사용된다. ➡️ 메시지 무결성 검사를 위해 보통 쓰이며, 문서의 위치를 빠르게 알아내고 콘텐츠의 중복 저장을 방지하기 위한 해시 테이블의 키로 이용될 수 있다.
Content-Type 헤더 필드는 엔터티 본문의 MIME 타입을 기술한다.
이 헤더는 원본 엔터티 본문의 미디어 타입을 명시한다. 즉 인코딩을 거친 경우에도 인코딩 전의 본문 유형을 명시한다는 의미
Content-Type 헤더는 내용 유형을 더 자세히 지정하기 위한 선택적인 매개변수도 지원한다.
Content-Type: text/html; charset=iso-8859-4
MIME "멀티파트" 이메일 메시지는 서로 붙어있는 여러 개의 메시지를 포함하며 하나의 복합 메시지로 보내진다.
HTTP 폼을 채워서 제출하면, 가변 길이 텍스트 필드와 업로드 될 객체는 각각이 멀티파트 본문을 구성하는 하나의 파트가 되어 보내진다.
ex) html input에 text와 file을 같이 보내는 경우 멀티파트로 같이 보내짐
범위 요청에 대한 HTTP 응답 또한 멀티파트가 될 수 있다.
HTTP 애플리케이션은 때때로 콘텐츠를 보내기 전에 인코딩을 하려고 한다.
이를 통해 전송 시간을 줄이거나 암호화하는데 이점을 챙길 수 있다.
웹 서버가 원본 Content-Type과 Content-Length 헤더를 수반한 원본 응답 메시지를 생성
콘텐츠 인코딩 서버가 인코딩된 메시지를 생성하고 Content-Encoding 헤더를 인코딩된 메시지에 추가하여 받는쪽에서 디코딩 가능하도록 함
➡️ Content-Length는 달라짐
수신 측 프로그램은 인코딩된 메시지를 받아서 디코딩하고 원본을 얻는다.
HTTP는 몇 가지 표준 콘텐츠 인코딩 유형을 정의하고 확장 인코딩으로 인코딩을 추가하는 것도 허용한다.
인코딩 알고리즘에 고유한 토큰을 할당하는 IANA를 통해 표준화된다.
몇 가지 흔히 쓰이는 콘텐츠 인코딩 토큰
identity를 제외한 3개는 메시지의 크기를 정보의 손실 없이 줄이기 위한 무손실 압축 알고리즘이다.
서버에서 클라이언트가 지원하지 않는 인코딩을 사용하는 것을 막기 위해, 클라이언트는 자신이 지원하는 인코딩 목록을 Accept-Encoding 요청 헤더를 통해 전달한다.
전송 인코딩은 전체 메시지에 대해 적용되며, 구조적인 이유 때문에 적용된다.
전송 인코딩은 다른 프로토콜에서도 네트워크를 통한 '안전한 전송'을 위해 존재했다.
알 수 없는 크기
콘텐츠 인코더는 콘테츠를 먼저 생성하지 않고서는 메시지 본문의 최종 크기를 판단할 수 없는데, 이 사이즈를 알기도 전에 데이터의 전송을 시작하려고 함
보안
전송 인코딩을 사용해 알아보기 어렵게 할 수 있지만 SSL과 같은 방식을 더 많이 씀
전송 인코딩을 제어하고 서술하기 위해 정의된 헤더 2가지
안전한 전송을 위해 어떤 인코딩이 메시지에 적용되었는지 수신자에게 알려줌
어떤 확장된 전송 인코딩을 사용할 수 있는지 서버에 알려주기 위해 요청 헤더에 사용
청크 인코딩은 메시지를 일정 크기의 청크 여럿으로 쪼갠다.
이는 전송 인코딩의 한 형태이며 따라서 본문이 아닌 메시지의 속성이다!
청크와 지속 커넥션
지속 커넥션에서는 Content-Length
헤더에 본문의 길이를 담아서 보내주어야 하는데, 동적으로 생성되는 경우에 알기 어렵다.
→ 이러한 딜레마를 청크 인코딩은 서버가 본문을 여러 청크로 쪼개 보낼 수 있게 해줌으로써 해결한다.
마지막에 서버는 크기가 0인 청크로 본문이 끝났음을 알린다.
청크 인코딩된 메시지의 트레일러
청크 메시지에 트레일러를 추가할 수 있는 경우
전송 인코딩이 메시지 본문에 적용될 때, 몇 가지 규칙이 반드시 적용되어야 한다.
'chuncked'
를 포함해야 한다.HTTP 프로토콜은 어떤 특정한 종류의 요청이나 응답을 다루는 방법들을 정의하는데, 이를 인스턴스 조작이라 부른다.
대표적 두 가지
이 부분은 7장-캐시에서 거의 다루었기 때문에 넘어감
클라이언트가 문서의 일부분이나 특정 범위만 요청할 수 있도록 해주는것
델타 인코딩은 객체 전체가 아닌 변경된 부분에 대해서만 통시한여 전송량을 최적화하는, HTTP 프로토콜의 확장이다.
서버에게
A-IM
이라는 받아들일 수 있는 인스턴스 조작의 종류를 가리키는 요청 헤더를 보내 델타 인코딩을 사용한다.
델타 인코딩은 필요한 부분만 보내 전송 시간을 줄일 수 있지만, 구현하기가 까다로울 수 있다. 또한 서버는 반드시 클라이언트가 가지고 있던 이전 버전의 사본들 모두를 유지해야 최신 사본간 차이점을 알아낼 수 있어서 디스크 공간을 더 소모한다.