NodeJs.crypto와 암호화
목차 |
1. crypto |
2. 단방향 암호화 |
3. 단방향 암호화 하기(crypto 메서드) |
4. 양방향 암호화 |
1. crypto
crypto란 암호화하다 라는 의미를 가지고 있다.
crypto는 노드가 제공하는 내장 모듈중 하나이며, 다양한 방식의 암호화를 도와주는 모듈이다.
서버에 비밀번호를 저장할 때에는 암호화가 필수이다.
만약 서버의 데이터베이스가 해킹 당했는데,
암호화가 되어있지 않다면 회원들의 정보가 그대로 유출될 수도 있기 떄문이다.
crypto 안에 있는 메서드를 이용하면 단방향, 양방향 어느 암호화던 진행이 가능하다.
아래에서 암호화와 crypto 안에 있는 다양한 메서드를 한번 알아보도록 하자.
2. 단방향 암호화
비밀번호는 일반적으로 단방향 암호화 알고리즘을 사용해서 암호화한다.
단방향 암호화는 복호화를 할 수 없다. 즉, 한번 암호화가 진행되면 되돌릴 수 없다.
복호화할 수 없는 암호화를 해시 함수라고 부르기도한다.
복호화할 수 없는 암호화가 왜 필요한가 의문이 들수도 있지만, 잘 생각해보면 비밀번호를 굳이 복호화를 할 필요가 없다.
비밀번호의 목적은 누군가의 신원을 증명하기 위함이다.
입력받은 비밀번호를 같은 알고리즘으로 암호화한 후에 데이터베이스에 저장된 암호화와 비교하여 같다면,
신원이 증명되므로 굳이 데이터베이스에 복호화한 비밀번호를 넣어둘 필요가 없다.
단방향 암호화 알고리즘 : 해시
단방향 암호화 알고리즘은 주로 해시 기법이 사용된다.
해시
어떠한 문자열을 고정된 길이의 다른 문자열로 바꾸는 방식
길이가 다른 문자열을 입력해도 항상 같은 길이의 문자로 나타낼 수 있다.
3. 단방향 암호화 하기(crypto 메서드)
위에서 배운 개념과 crypto안의 메서드를 이용해 암호화를 진행해 보도록하자.
const crypto = require('crypto')
let str = "char1ey"
const hash = crypto.createHash('sha256').update(str).digest('base64url')
const hash2 = crypto.createHmac('sha256', "char1ey").update(str).digest('base64url')
console.log(hash) // skdY_On4am6gHckSEkZnLlfWmzMX0oEIkVJnOlmkri0
console.log(hash2) // aaZQpDkIzr-2XUPwBjCsUPKe7Mu0-eci14HaMhebwMw
위의 코드는 "char1ey"라는 문자열을 암호화한 것이다.
어떤 메서드들이 사용되었는지 한 번 알아보도록 하자.
createHash
사용할 해시 알고리즘을 넣어준다.
sha1, sha256, sha512 등등 알고리즘이 존재하며 해킹에 취약해지면 강화된 알고리즘으로 바꾸면된다.
문법(Syntax)
crypto.createHash( 해시 알고리즘 )
update
변환할 문자열을 넣어준다.
문법(Syntax)
update( 변환할 문자열 )
digest
인코딩할 알고리즘을 넣어준다.
base64(64진수), hex(16진수) 등등이 사용되며, 주로 base64가 가장 짧아 애용된다.
결과물은 변환된 문자열(String)이다.
문법(Syntax)
digest( 인코딩 )
createHmac
지정한 해시 알고리즘과 키(salt)를 이용하여 사용할 수 있다.
원리는 원래의 문자열에 키(salt)라는 문자열을 붙여 암호화를 진행한다.
키값을 알지못하면 어떤방식으로 암호화를 했는지 알 수 없으며,
키(salt)가 알려지면 누구나 같은 암호화를 진행할 수 있으니 알려지면 안된다.
문법(Syntax)
crypto.createHmac( 해시 알고리즘, 키(salt) )
4. 양방향 암호화( 대칭형, 비대칭형 )
양방향 암호화는 단방향과 다르게 복호화가 가능하다.
단, 복호화를 진행할 때에는 키라는 것을 사용해야한다.
암호화된 것을 복호화하기 위해서는 암호화할 때 사용한 것과 같은 키를 사용해야한다.
노드로 양방향 암호화를 진행할 수는 있다.
하지만, 코드를 이해하기 위해선 암호학에 대해 학습해야하므로 그냥 있다는 것만 알아두도록 하자.
아래의 코드는 참고자료의 예시를 가져온 것이다.
const crypto = require('crypto')
const alg = 'aes-256-cbc'
const key = 'charleycharleycharleycharleychar'
const iv = '1234567890123456'
// 암호화
const cipher = crypto.createCipheriv(alg, key, iv)
let result = cipher.update('암호화할 문자열', 'utf8', 'base64url')
result += cipher.final('base64url')
console.log(result) // T4Vv73MzTCYj3b5LqWhQ4Yqdl9ltXW2YEtXvjjfzKno
// 복호화
const decipher = crypto.createDecipheriv(alg, key, iv)
let result2 = decipher.update(result, 'base64url', 'utf8')
result2 += decipher.final('utf8')
console.log(result2) // 암호화할 문자열
코드를 보고 진행은 이해가 되겠지만, 왜 저렇게 하는지는 이해하지 못할 수도 있다.
암호학에 대해 공부해야만 이해가 가능하니 일단 눈으로 익혀만 두자.
crypto.createCipheriv
(※ 이해하기 위해서는 암호학에 대해 알아야한다.)
암호화 알고리즘과 키, iv를 넣어준다.
위에선 aes-256-cbc 알고리즘이 사용되었고, 이 알고리즘의 경우 키(salt)는 32바이트를, iv는 16바이트를 사용해야한다.
iv는 암호화할 때 사용하는 초기화 벡터를 의미한다.
사용가능한 알고리즘 목록은 crypto.getCiphers( )를 호출하면 볼 수 있다.
문법(Syntax)
crypto.createCipheriv( 알고리즘, 키, iv )
cipher.update
암호화할 대상과 대상의 인코딩, 출력 결과물의 인코딩을 넣어준다.
보통 문자열은 utf8 인코딩을, 암호는 base64를 많이 사용한다.
문법(Syntax)
cipher.update( 문자열, 인코딩, 출력 인코딩 )
cipher.final
출력 결고물의 인코딩을 넣으면 암호화가 완료된다.
문법(Syntax)
cipher.final( 출력 인코딩 )
crpyto.createDecipheriv
복호화할 때 사용되며, 암호화시 사용했던 알고리즘, 키, iv를 똑같이 넣어야한다.
문법(Syntax)
crypto.createDecipheriv( 알고리즘, 키, iv )
decipher.update
암호화된 문장과 대상의 인코딩, 복호화할 인코딩을 넣어준다.
cipher.update의 인코딩 값, 두 번째와 세 번째 인자를 바꾸어 넣으면된다.
문법(Syntax)
decipher.update( 문자열, 인코딩, 출력 인코딩 )
decipher.final
복호화 결과물의 인코딩을 넣어준다.
문법(Syntax)
decipher.final( 출력 인코딩 )
crypto를 이용한 암호화를 알아보았다.
이를 이용해 암호화를 진행할 수 있지만,
다양한 암호화 패키지가 있으므로 원리를 이해(학습)하는데 crypto를 이용하고, npm 패키지를 사용하도록 하자.