개발 학습 실습실

이 사이트의 실습은 자바스크립트를 켜야 움직입니다. 아래는 같은 내용을 글로 적은 것입니다.

공부 › 보안 › 암호 기술

해시·암호화·서명

숨기는 것, 확인하는 것, 되돌릴 수 없는 것

보안 이야기에 늘 나오는 해시, 대칭키 암호화, 비대칭키 암호화, 서명은 서로 다른 일을 합니다. "주문 100원"이라는 메시지에 다섯 가지 도구를 각각 써 보고, 내용을 바꾸거나 다른 키를 썼을 때 무슨 일이 생기는지 확인하세요. 화면의 값은 모두 실제로 계산한 값입니다.

실행으로 대조 · Node.js 암호 라이브러리로 실제 계산·검증

이 실습에 나오는 개념

해시 함수와 솔트
해시 함수는 입력을 고정된 길이의 값으로 바꾸는 함수로, 결과에서 원래 입력을 되돌릴 수 없다. 비밀번호는 원문 대신 해시 값을 저장해 유출되더라도 원문이 드러나지 않게 한다. 솔트는 비밀번호마다 다르게 덧붙이는 무작위 값으로, 같은 비밀번호라도 다른 해시가 되게 해 미리 계산해 둔 해시 목록을 이용한 공격을 막는다.
대칭키 암호화와 비대칭키 암호화
대칭키 암호화는 암호화와 복호화에 같은 키를 쓰는 방식으로 빠르지만 키를 상대와 안전하게 공유해야 하는 문제가 있다(AES). 비대칭키 암호화는 공개키와 개인키의 쌍을 쓰는 방식으로, 공개키로 암호화한 것은 개인키로만 풀 수 있어 키 공유 문제가 없지만 느리다(RSA). 실제로는 비대칭키로 대칭키를 안전하게 교환한 뒤 대칭키로 데이터를 암호화한다.
HMAC과 전자서명
메시지가 중간에 바뀌지 않았고 정당한 상대가 보냈음을 확인하는 기술이다. HMAC은 양쪽이 공유한 비밀키와 메시지를 함께 해시해 인증 코드를 만든다. 전자서명은 보내는 쪽이 개인키로 서명하고 받는 쪽이 공개키로 검증하며, 서명한 쪽만 만들 수 있으므로 보낸 사실을 부인할 수 없다.
JWT(JSON Web Token)
사용자 정보 등의 내용(클레임)을 담고 서명을 붙인 토큰이다. 헤더, 페이로드, 서명의 세 부분으로 이뤄진다. 서버는 서명을 검증해 토큰이 위조되지 않았음을 확인하며, 별도의 저장소를 조회하지 않아도 된다. 페이로드는 암호화된 것이 아니라 인코딩된 것이어서 누구나 내용을 볼 수 있으므로 민감한 정보를 넣지 않는다.

이렇게 바꿔 보세요

처음 설정으로 실행하면

  1. 보내려는 메시지는 "주문 100원"입니다.
  2. 해시 함수에 넣으면 길이가 일정한 값이 나옵니다. 키는 쓰지 않습니다. 같은 메시지를 다시 넣으면 언제 누가 해도 똑같은 값이 나옵니다.
  3. 이 값에서 "주문 100원"을 수식으로 거꾸로 되돌리는 계산은 없습니다(다만 후보를 해시해 비교하면 짧은 입력은 알아낼 수 있습니다). 해시는 한 방향으로만 갑니다. 그래서 비밀번호처럼 원래 값을 몰라도 되는 것을 저장할 때 쓰되, 비밀번호에는 솔트를 쓰는 전용 해시를 씁니다.

실행 결과

코드

MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] digest = md.digest(message.getBytes(UTF_8));
// 키가 없다. 누구나 같은 입력으로 같은 값을 얻는다.

이 모형의 전제

화면의 해시, 암호문, 서명 값과 성공·실패 결과는 모두 Node.js의 암호 라이브러리로 실제 계산하고 검증한 것입니다(SHA-256, AES-256-GCM, RSA 2048비트, HMAC-SHA256). RSA 값은 길어서 앞부분만 보였고, 키를 새로 만들 때마다 값이 달라집니다. 실제 서비스에서는 직접 구현하지 않고 검증된 라이브러리와 프로토콜(TLS, JWT 라이브러리)을 씁니다.

앞 실습: 의존성과 공급망 · 다음 실습: TLS 핸드셰이크

이 실습에 나오는 개념

이 실습에서 보는 것

설정

코드


      
    

그림

실행 비교

이렇게 바꿔 보세요