무결성과 기밀성
- 무결성(integrity) : 메시지가 조작되지 않음
*메시지가 원본 그대로 잘 도착함을 의미- 기밀성(privacy) : 메시지를 가로챌 수 없음
*메시지를 읽을수 없다. 즉, 암호화되어 있다를 의미
데이터 제공자의 신원을 확인하고 보장받는 게 인증에서 중요한 이유
- 클라이언트는 데이터 제공자가 제공해준 데이터를 사용할 수밖에 없음
- 클라이언트는 서버에 데이터 요청을 하고 이후 받은 데이터를 이용해서 화면을 렌더링하는 등의 작업을 수행
- 위의 이유로 클라이언트는 요청 및 응답을 중간에서 가로채는 중간자 공격에 취약
- 중간자 공격 : 클라이언트와 서버 사이에서 공격자가 서로의 요청, 응답의 데이터를 탈취 및 변조하여 다시 전송하는 공격
- 중간자 공격 시 데이터가 중간에 다른 도메인을 거쳐서 전달되기 때문에 서버가 해당 데이터가 제공된 도메인에 대한 추가데이터를 응답객체에 실어 보냄
- 중간자 공격으로 인해 다른 도메인에서 데이터를 받은 클라이언트는 데이터를 제공한 도메인과 전달받은 내용의 도메인을 비교하여 중간자 공격이 존재하는지 아닌지 확인할 수 있음
- 중간자 공격으로 인한 추가 데이터 또한 변조할 수 있기 때문에 해당 데이터를 암호화시키는 작업이 필요
https://google.com
: 내가 접속한 사이트가 진짜 google임을 보장인증 과정
- 요청을 받으면 서버는 인증서와 함께 요청의 응답을 전송
- 응답을 받은 클라이언트는 인증서에 작성된 도메인과 응답 객체에 작성된 도메인을 비교
- 응답에서 확인한 도메인과 인증서에 작성된 도메인이 같다면 데이터를 보내준 서버가 확실하다는 것을 인지
- 중간자가 요청을 탈취해 서버인척, 클라이언트인척 정보를 탈취한 경우, 응답에서 확인한 도메인과 인증서에 작성된 도메인이 같지 않아 데이터를 보내준 서버가 맞는지 확신할 수 없게 됨
통신 과정
- Hand Shake
- 서로를 확인 후 서버는 클라이언트에게 한쌍의 키중 하나를 공개 키로 전달
- 비밀 키 생성
- 클라이언트는 전달받은 키를 이용하여 서버와 키를 만들어낼 임의의 정보를 암호화하여 전송
- 서버도 클라이언트와 마찬가지로 임의의 정보를 암호화하여 전송
- 서로 만들고 교환한 임의의 정보를 마탕으로 비밀 키를 생성
- 상호 키 검증
- 각자 생성한 키를 바탕으로 클라이언트가 테스트용 데이터를 만들어낸 비밀키로 암호화하여 전달
- 서버도 만들어진 키를 바탕으로 복호화를 한 후 다시 암호화 하여 클라이언트로 전달
- 클라이언트가 같은 내용의 데이터를 복호화하는 데 성공했다면 비밀 키 생성 성공
- HTTPS 연결이 성립됨을 의미
mkcert라는 프로그램을 이용해서 로컬 환경(내 컴퓨터)에서 신뢰할 수 있는 인증서를 만들 수 있음
brew install mkcert
mkcert -install
mkcert -key-file key.pem -cert-file cert.pem localhost 127.0.0.1 ::1
localhost
, 127.0.0.1(IPv4)
, ::1(IPv6)
에서 사용할 수 있는 인증서가 완성cert.pem
, key.pem
이라는 파일이 생성cert.pem
파일의 경우 공개키와 인증기관의 서명을 포함하고 있는 인증서이기 때문에 공개되어도 상관이 없지만, key.pem
의 경우 개인 키이므로 git에 커밋하지 않고 암호처럼 다루어야 함const https = require('https');
const fs = require('fs');
https
.createServer(
{
key: fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
cert: fs.readFileSync(__dirname + '/cert.pem', 'utf-8'),
},
function (req, res) {
res.write('Congrats! You made https server now :)');
res.end();
}
)
.listen(3001);
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();
https
.createServer(
{
key: fs.readFileSync(__dirname + '/key.pem', 'utf-8'),
cert: fs.readFileSync(__dirname + '/cert.pem', 'utf-8'),
},
app.use('/', (req, res) => {
res.send('Congrats! You made https server now :)');
})
)
.listen(3001);