27. crypto 단방향 암호화
// 단방향 암호화(crypto)
// 암호화는 가능하지만 복호화는 불가능
// - 암호화: 평문을 암호로 만듦
// - 복호화: 암호를 평문으로 해독
// 단방향 암호화의 대표 주자는 해시 기법
// - 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식
// - abcdefgh 문자열 -> qvew
// 암호화는 멀티 스레드로 돌아간다.
// 암호화는 CPU를 많이 잡아먹는 작업이기 때문에 멀티 스레드로 돌아간다.
// ----------------------------------------------------------------
// 보통 잘못 알고있는 개념이 비밀번호를 암호화라고 하는데, 비밀번호는 암호화가 아니다.
// 비밀번호는 보통 암호화가 아니라 해시인데, 편의상 암호화라고 말하기도 하지만 엄밀하게 말하면 암호화는 아니고 해시라는 것이다.
// ----------------------------------------------------------------
// 해시란?
// 평문을 어떤 암호 같이 만든다.
// 그런데 그 암호를 다시 평문으로 만들 수가 없다.
// 진짜 암호화는 평문을 암호로 만들 수 있고 암호화딘 것도 다시 평문으로 돌릴 수 있는데,
// 해시는 평문을 해시로 만들었다가 다시 평문으로 만들기가 굉장히 어렵다.
// 해시는 보통 비밀번호에서 많이 쓰인다.
// ----------------------------------------------------------------
// 그럼 내가 'abcd'라는 걸로 비밀번호를 설정했는데, 그걸 다시 'abcd'로 못 돌리면 어떻게해요? 라고 생각할 수도 있는데,
// 해시의 특징은 어떤 특정한 문자를 해시로 바꾸면 항상 '같은 해시'로 나온다.
// 'abcd'를 해시화했더니 'qwer'이 됐다면, 'abcd'를 해시화하면 항상 'qwer'이 된다.
// 그럼 서버에서는 'qwer'만 들고있다가 사용자가 'abcd'를 입력하면 해시화돼서 'qwer'이 되겠지?
// 즉, 그 2개를 비교를해서 맞는지를 비교하는거지, 'abcd'는 서버 어디에도 없다.
// 그러니까 안전한 것이다.
// 만약 서버 데이터베이스에 내 비밀번호가 실제로 저장이 되어있으면, 해커들이 털어가면 내 암호가 털리는거잖아?
// 그런데 그걸 방지하기위해 서버엔 'qwer'이라는 해시만 남아있는 것이다.
// 그래서 해커들이 'qwer'을 가져가도 이를 다시 'abcd'로 못 돌리거든?
// 돌릴 수 있는 방법이 있기는 하다.
// 그런데 그런 방법들을 쓴다 하더라도 매우 오래걸려서(몇십년, 최신 해시 알고리즘을 사용한다면 더더욱 오래걸림)
// 해커들이 이 짓을 안한다.
// 이 해시 기법은 알고리즘만 잘 선택하면 매우 안전한 방식이고,
// 노드에서도 이 해시 기법을 사용한다.
// ----------------------------------------------------------------
// Hash 사용하기 (sha512)
// createHash(알고리즘): 사용할 해시 알고리즘을 넣어준다.
// - md5, sha1, sha256, sha512 등이 가능하지만, md5와 sha1은 이미 취약점이 발견되었다.
// - 현재는 sha512 정도로 충분하지만, 나중에 sha512 마저도 취약해지면 더 강화된 알고리즘으로 바꿔야된다.
// update(문자열): 변환할 문자열을 넣어준다.
// digest(인코딩): 인코딩할 알고리즘을 넣어준다.
// - base64, hex, latin1이 주로 사용되는데, 그중 base64가 결과 문자열이 가장 짧아 애용된다.
// 결과물로 변환된 문자열을 반환한다.
// ----------------------------------------------------------------
const crypto = require('server/node/202305ing_node_study/section_3/3_9_crypto_util/3_9_1_crypto');
console.log(crypto.createHash('sha512').update('비밀번호').digest('base64')); // dvfV6nyLRRt3NxKSlTHOkkEGgqW2HRtfu19Ou/psUXvwlebbXCboxIPmDYOFRIpqav2eUTBFuHaZri5x+usy1g==
console.log(crypto.createHash('sha512').update('비밀번호').digest('hex')); // 76f7d5ea7c8b451b773712929531ce92410682a5b61d1b5fbb5f4ebbfa6c517bf095e6db5c26e8c483e60d8385448a6a6afd9e513045b87699ae2e71faeb32d6
console.log(crypto.createHash('sha512').update('다른 비밀번호').digest('base64')); // cx49cjC8ctKtMzwJGBY853itZeb6qxzXGvuUJkbWTGn5VXAFbAwXGEOxU2Qksoj+aM2GWPhc1O7mmkyohXMsQw==
// 위와 같이 해시로 변경된 문자열을 서버에 저장하는 것이다.
// 비밀번호 자체는 저장하지 않는다.
// ----------------------------------------------------------------
// 이 때문에 해시를 탈취하려는 해커들은 없다.
// 오히려 다른 허점을 노린다.
// 개발자가 실수로 console.log로 비밀번호를 노출시키거나
// 프론트단에서 키보드를 해킹해서 알아내는 방식을 사용한다.
// 위와 같이 해시화되면 해커들이 위 해시를 비밀번호로 돌릴려는 시도조차 안한다. 어차피 오래 걸리기 때문에.