해싱(Hashing) : 특정한 규칙에 따라 변환하여 고정된 크기의 해시 값을 생성하는 과정
임의의 난수, 16 진수 : 0~f까지 표기
💡
컴퓨터가 8bit 체제라 16진수를 이해하기 더 편해서 사용
예시) 3을 16진수로 표현할 때 0x03
key : 안녕 → hash : AB3F7D8
16진수 ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F)로 임의의 난수를 표현한 것.
💡
· 16진수에서 기억해야 할 것
1. 0~F까지 표현한다.
2. 프로그램에서 16진수를 표현할 때엔 0X를 사용한다.
ex) 16진수로 3을 표현 > 0X03 이라고 작성.(0X03이 3을 나타냄.)
0X가 있다? > 애는 16진수구나~
💡
컴퓨터는 8비트라서 16진수를 더 이해하기 쉬워함. 신경 쓰지 말고 우린 10진수 쓰자!
2. Hash 특징
안녕 <이라는 글자가 hash를 거치면 AB3F7D 같은 임의의 난수가 생성됨.
(AB3F7D는 설명하기 위해서 임의로 정한 것. 쓰는 알고리즘에 따라 길이가 다름.)
즉 같은 입력에 대해서는 항상 동일한 해시값이 생성
해시 값은 주어진 입력 데이터에 대해 유일하게 대응
작은 변화라도 입력 데이터의 해시 값이 크게 변하도록 설계됨
길이는 hash 알고리즘에 따라 다 다름
이미 해봐서 사람이 기억하고 있으면 찾을 수 있음
💡
Why? 무엇을 hash하던지 항상 동일한 길이가 나옴
💡
<특징 정리>
1) 동일하게 나온다.
ex) ‘안녕’을 hash하면 AB3F7D가 나오고, 또다시 ‘안녕’을 hash하면 AB3F7D가 나온다.
2) 복호화 불가능. (원복할 수 없다. 단반향)
: hash 알고리즘을 통해서 암호화를 하면, 안녕은 AB3F7D로 바꿔줘도,
역으로 AB3F7D를 안녕으로 바꿀 수는 없음.
대신, AB3F7D가 안녕이라는 사실을 ‘기억’하고 있으면 그게 안녕을 뜻한다는 건 알겠지….
3. 왜 사용하는가?
무엇을 hash하든지 항상 동일한 길이가 나옴.
예시) 엄청 두꺼운 책에 엄청 많은 글이 적혀있는 책 한 권을 hash했을 때 : A3F6D08
그 저자의 이름이 홍길동인데 이름을 홍길도로 바꾸면 위조된 것
동일한 책이지만 조금이라도 변경이 되면 hash가 변경됨 : 3F607D4
이 책에 대한 hash를 국가에 등록한 경우 이 책을 위조하면
그 파일 내용을 hash하면 다르게 나옴 어떤 책이 진본인지 알 수 있음
만약 다른 사람이 내 책을 위조하잖아? 그걸 hash하면 원본과 위조본은 hash값이 다르게 나오겠지. 그럼 어떤 책이 진본인지 알 수 있음.
숨은 그림 찾기. 어느 부분이 변경됐는지 알 수는 없지만 hash값을 보면 달라진 건 알 수 있음.
세상을 hash값으로 표현할 수 있지만 0.1초만 움직여도 hash값이 다 달라짐
💡
이 점을 이용해서 ‘전자 서명’, ‘위조 방지’ 에 사용할 수 있음.
* 전자서명 : 온라인 상에서의 시그니처
💡
hash값을 보고 암호를 풀 수 없기 때문에 암호는 hash 사용 불가능. (단반향 특징)
ex) A3F6D0를 보고 어떻게 다시 책으로 바꿔줘? 못해.
4. Hash의 장단점
장점) 변경의 유무를 알 수 있음
단점) 복구화가 안됨
hash 알고리즘을 통해서 암호화하면 hash를 원복시킬 순 없음
어떤 부분이 변경됐는지는 알 수 없음
예시) 세상의 모든 것에 대한 hash 값이 나오고
세상이 계속 바뀌기 때문에 그 순간마다 hash 값이 달라짐
권장 Hash
MD5, SHA-1 → 크랙 당함
크랙을 당하는 이유? 레인보우 테이블을 가지고 있음
레인보우 테이블 : hash 함수에 따른 hash 값들이 다 저장되어 있음
SHA-256, SHA-512에 salt 추가하기
예시) SHA-256 : 256 bit
💡
SHA256 ??
OPEN JAVA 다운로드 받는 사이트를 보면 'sha256' 이란 단어를 볼 수 있다.
256은 bit를 나타낸다. 즉, 2^256
sha = secure hash algorithm
sha256을 클릭하면 이렇게 임의의 난수들 (hash값)이 나온다.
openjava 21버전의 해쉬값이 바로 이것. 이 hash값으로 원본인지 가짜 프로그램인지 구분한다.
5. 단방향 통신
ID = user name
통신할 때 연결되는 물리적인 선 : Byte Stream
PW를 그대로 저장하면 보안법에 걸리니까 hash해서 저장함
직원도 몰라야하니까 단방향 hash를 사용
hash값을 비교해서 값이 같으면 승인
hash니까 해킹을 당해도 단방향이라 원복이 안되니 PW가 노출되지 않음
💡
byte stream
바이트 스트림 (바이트가 흐르는 개울)
id를 username이라고 부른다.
💡
비밀번호는 hash 값으로 저장된다.
<ex. 회원가입 요청>
ssar, 1234, ssar@nate.com
|클라이언트| —————————————————————————→ |네이버| ———————-> |DB| 상에
byte Stream username / pw / email을 저장
ssar / hash값 / ssar@nate.com
* 비밀번호는 hash값으로 저장된다. 즉, 유저가 pw를 1234라고 입력을 해도
hash값으로 변형되어서 AB3F7D 이런식으로 네이버 DB에 전송이 됨.
<ex. 로그인 할 때>
로그인 : ssar, 1234
|클라이언트| —————————————————————————→ |네이버| ———————-> |DB| 상에
byte Stream username / pw 을 비교.
ssar / hash값을 비교
클라이언트가 입력한 비번이 1234 라는 걸 알 수는 없다.
그러나 해쉬값은 (비번을 틀리게 입력하지 않은 이상 바뀌지 않음) 같으니까!
비밀번호를 인식할 때, 1234가 아니라 해쉬값이 같은 뭔가를 넣었구나! 하고 인식함.