오늘의 Today I Learned (TIL)으로는 Hashing을 공부해보려고 한다. 자 가보자구~
키(Key) 값을 해시 함수(Hash Function)라는 수식에 대입시켜 계산한 후 나온 결과를 주소로 사용하여 바로 값(Value)에 접근하게 할 수 하는 방법이다.
단방향 암호화방식이다.
키(Key) 값을 값(Value)이 저장되는 주소 값으로 바꾸기 위한 수식
해시함수의 조건
- 입력의 크기에 제한이 없는 가변적인 길이를 수용해야 한다.
- 출력은 고정된 길이를 가져야 한다.
- 해시 함수(Hash Function)의 입력은 어떠한 값이 들어와도 계산이 쉬워야 한다.
- 해시 함수(Hash Function)는 일방향성(One-way Function, 역변환 불가)이어야 한다.
- 해시 함수(Hash Function)는 충돌(Collision)이 없거나 적어야 한다.
웹 페이지 서버를 구성하면서 회원가입을 하면 데이터베이스에 비밀번호가 그대로 저장되는 것은 서비스를 제공하는데 있어서 다른 서비스까지 추가 해킹을 당하는 일이 발생할 수 있다.
따라서 비밀번호를 암호화하여서 데이터베이스에 저장해야하는데 암호화는 암호화에 사용된 키(비밀번호)를 통해 데이터를 복호화 할 수 있기 때문에 해싱이 등장하게 되었다.
하지만, 슈퍼컴퓨터가 등장하게 되면서 hash 함수만 알면 비밀번호가 될수 있는 모든 가지수의 정보들을 적은 테이블이 존재한다. 이러한 테이블을 레인보우테이블이라고 한다. 해당 테이블을 이용하여 무작위 공격을해서 해싱된 암호화를 알아 낼 수 있기 때문에 해쉬를 할때 salt를 사용한다.
hash를 할때, 사용하는 무작위 숫자(소수점 가능)으로 원본 값을 알아내도 salt를 추가해주면서 가지수가 엄청나게 늘어나게된다. 따라서, 레인보우 테이블을 만들기도, 만들었어도 비밀번호를 찾아 내는 것 거의 불가능하다.
현재까지 많은 곳에서 사용중이므로 알아내는 것이 쉽지 않다.
레인보우 테이블 공격 방지를 위해 솔트(Salt)를 통합한 적응형 함수 중 하나로 SHA(Secure Hash Algorithm, 안전한 해시 알고리즘) 종류의 암호화는 GPU 연산에 유리한 32비트 논리 및 연산만 사용하기 때문에 GPU 연산을 이용한 공격에 취약하다고 한다.
그래서 Bcrypt 설계자는 Blowfish(브루스 슈나이어가 설계한 키(key) 방식의 대칭형 블록 암호)를 이용해 구현하였다고 한다.
@Mutation(() => User)
async createUser(
@Args('email') email: string,
@Args('password') password: string,
@Args('name') name: string,
@Args({ name: 'age', type: () => Int }) age: number,
) {
//비밀번호 암호화 하기
const hashedPassword = await bcrypt.hash(password, 10.2); //암호화할 값 + salt값
return this.usersService.create({ email, hashedPassword, name, age });
}
bcrypt.hash(password,salt,callback)의 순으로 입력한다.
Node.js 내장모듈인 Crypto를 이용해 특정 파일의 해시값을 생성한다.
const filename = process.argv[2]; // 읽을 파일 이름을 매개 변수로 써준다
const crypto = require('crypto');
const fs = require('fs');
const hash = crypto.createHash('sha256'); // sha-256 알고리즘 사용
const input = fs.createReadStream(filename);
input.on('readable', () => {
const data = input.read();
if (data)
hash.update(data);
else {
console.log(`${hash.digest('hex')} ${filename}`);
}
});
SHA-256을 비롯해 MD5, SHA-2 등을 지원.