암호화 crypto

반응형

 

결국 React Native 와 Nodejs 서버와의 aes 양방향 대칭키 암호화를 사용하기 위해서는 crypto-js 3.1.8 을 사용하면 된다. 

react-native-crypto-js 가 아니라 그냥 crypto-js@3.1.8 을 React Native 쪽에 사용해야 한다. node 쪽도 crypto-js 설치.

(https://www.npmjs.com/package/crypto-js) 주간 다운로드 수가 500만이 넘어간다.

관련 사항(https://lifeonroom.com/study-lab/react-native-crypto-js/)

 

 

실무에 써먹기 좋은 글. crypto 기준. 단방향 암호화 비밀번호 저장을 위한 로직이 구체적으로 잘 나와 있다.

https://zinirun.github.io/2020/12/02/node-crypto-password/

 

이해를 돕기 위해 좋은 글. 양방향 대칭키 aes-256 암호화를 nodejs 에서 만든 로직이 잘 구성되어 있다.

https://yceffort.kr/2020/06/encryption-decryption-nodejs

 

참고용

https://www.zerocho.com/category/NodeJS/post/593a487c2ed1da0018cff95d

https://velog.io/@kylexid/왜-bcrypt-암호화-방식이-추천되어질까

https://perfectacle.github.io/2019/11/24/aes/

 

암호화는 단방향 해싱 과 양방향 이 있다.

단방향 해싱은 비밀번호 같은 것을 DB 에 저장할 때 사용하는 방식으로 한쪽 방향으로 암호화 되어 secret 같은 것으로 복원 불가이다.

양방향 암호화는 secret 을 가지고 복호화 할 수 있다.

 

개인적으로는 다음과 같은 방식으로 구상함.

서버측에서 aaa.bbb.ccc 로 jwt 을 만들고 검증하며

userKey (uuid v1  형식), secret (uuid v4 형식) 를 생성하여 양방향 암호화하여 base64 인코딩한 것을 ddd 로 사용.

timestamp-userKey 형식이 평문이고 이를 secret 으로 암호화하고 base64 한 것이 ddd 임.

클라에서는 aaa.bbb.ccc 를 가지고 있으며 aaa.bbb.ccc.ddd 로 authorization 헤더에 토큰으로 사용.

서버측에서는 aaa.bbb.ccc 인 jwt 은 동일하게 verify 하며 여기서 사용자 id 값을 얻음.

ddd 부분을 base64 디코딩하고 secret 으로 복호화 하고 timestamp-userKey 정보를 얻음.

timestamp 가 5초 이내인지 확인하고 userKey 가 맞는지 확인. (jwt 은 서버측에서 생성하는 것이므로 클라측에서는 변경불가하기 때문에 ddd 에 이렇게 timestamp 정보를 담아줌. 매 클라 요청시 마다 이값이 달라질 것이기 때문. 클라에서 만드는 정보임)

 

crypto, bcrypt 등 여러 패키지가 있지만 crypto 가 nodejs 기본 탑재된 패키지임. 양방향 단방향 기능 모두 있기 때문에 crypto 가 가장 사용하기 좋은 듯 함. bcrypt 는 단방향 관련된 것만 있음.

 

그런데 react native 측에서도 양방향 암호화를 해야하므로 RN 측에서 동작하는 안정적인 패키지도 있어야 함.

expo-crypto 가 unimodules 설치하고 사용할 수는 있지만 마치 bcrypt 처럼 단방향 해싱 밖에 지원하지 않음.

(https://docs.expo.io/versions/latest/sdk/crypto/)

react-native-crypto 라는 것은 오래되었으며 2년전 업데이트가 마지막이고 node 쪽의 것을 우겨넣는 식으로 만든 것 같음.

(https://github.com/mvayngrib/react-native-crypto)

react-native-simple-crypto (https://github.com/ghbutton/react-native-simple-crypto)

(https://github.com/trackforce/react-native-crypto) 이 패키지를 Fork 해서 만들었다고 함. 이것도 오류남.

react-native-aes-crypto (https://github.com/tectiv3/react-native-aes) 상당히 괜찮다. 굉장히 코드가 깔끔하다. 하지만 node 의 기본 탑재된 crypto 패키지와 서로 연동하는데 실패했다. node 의 crypto 패키지에서 update 하고 final 하는데 이 의미를 잘 모르겠다. 그걸 또 Buffer.concat 까지 해서 합치는데 react-native-aes-crypto 에서는 동일하게 하는 법을 찾지 못하였다. 하지만 NativeModules 사용법의 깔끔한 예제로 매우 좋은 소스코드이다.

crypto-js 라는 패키지가 주간 다운로드가 500만이 넘는다. 이것이 가장 널리 사용되는 듯 하다. 브라우저, 리액트네이티브, 노드서버 모두 동작한다. 그리고 방대한 암호화 기능이 있다. (http://reactspring.io/?page_id=881) 이런 변종 버전도 존재한다. 

 

 

 

* SHA-256 (단방향 해싱 암호화)

복호화가 되지 않는 암호화 방법 중 유명한 것이 SHA 시리즈인데, SHA는 미국 NSA가 제작하고 미국 국립표준기술연구소(NIST)에서 표준으로 제작한 해시 암호 알고리즘이다.
과거 SHA-0, SHA-1 버전을 거쳐 요즘은 SHA-2를 많이 쓰고있는데, SHA-2에는 SHA-224, SHA-256, SHA-384, SHA-512 등의 종류가 있다.
현재 SHA-3도 개발 중이라고한다.
현재 자주쓰는 SHA-2 중에서도 대표적으로 SHA-256 이 인터넷뱅킹이나 비트코인 등에 사용된다.
SHA-2의 특징은 어떤 문자열을 암호화 할 때, "동일한 문자열"은 항상 동일한 다이제스트(해시 함수가 출력하는 압축된 문장)를 출력하고, "다른 문자열"은 항상 다른 다이제스트를 출력한다.
이 중 SHA-256은 다이제스트 출력 값이 256bit인 것을 말하고 SHA-512라면 다이제스트 출력 값이 512bit인 것을 말한다.
비밀번호는 SHA-256을 통해 나온 다이제스트를(256bit 해싱 값) 저장한다.
"동일한 문자열"을 누군가 SHA-256 변환하여, 비교한다면 해킹이 가능하므로 (레인보우 테이블) 솔트를 추가해주면 이를 방지할 수 있다.
키 스트레칭이라하여 SHA-256(단방향 해싱)을 통해 결과로 나온 다이제스트를 또 다시 해싱하는 방식으로 해커가 패스워드를 추측하는 데 많은 시간이 소요되도록 할 수 있다.


* RSA (양방향 비대칭키 암호화)

대표적인 비대칭키 암호화 방식이다.
비대칭키 라는 것은 암호화할 때 키와 복호화할 때 키가 다르다는 의미인데, 암호화할 때 키를 "공개키", 복호화할 때 키를 "개인키"라고 한다.
클라이언트에서 가지고있는 정보를 서버로 보낼 때, 스니핑 등으로 데이터가 노출되면 안되므로 클라이언트가 가지고 있는 "공개키"로 데이터를 암호화하여, 서버로 전달한다.
암호화 가능한 길이가 딱 245byte 까지이므로, 긴 문자열을 암호화하는데는 적합하지 않다.


* AES (양방향 대칭키 암호화)

Advanced Encryption Standard
"대칭키"라는 임의의 키를 만들어서, 암호화하고자 하는 "문자열"을 "대칭키" 라는 키로 암호화 하는 방식이다.
암호화 키의 길이에 따라 AES-128, AES-192, AES-256 종류가 있다.
SHA 처럼 AES 뒤의 숫자가 bit 길이이다.
비대칭키와 다르게 "대칭키" 하나로 암호화 및 복호화 모두 진행하는 방식이다.
문자열 길이에 상관없이 암호화가 가능하다.


* RSA + AES 를 사용하여 문자열 길이가 긴 것도 비대칭키 암호화 방식을 사용할 수 있다.

RSA 공개키, 개인키를 서버에서 생성해서 클라이언트에게 "공개키"를 알려준다.
클라이언트는 "공개키"를 안전한 장소에 보관하고, 서버는 "개인키"를 안전한 장소에 보관한다.
클라이언트에서 서버로 데이터를 보낼 때, AES 대칭키를 생성한다. 이 대칭키로 서버로 보낼 데이터를 AES 암호화 한다.
서버에서는 클라이언트가 생성한 AES 대칭키를 알고있어야 전달받은 데이터를 복호화 할 수 있다. 때문에 클라이언트에서 AES대칭키를 안전한 장소에 보관된 "공개키"로 RSA 암호화를 진행한다.
서버에서는 RSA 암호화된 AES 대칭키를 "개인키"로 RSA 복호화하고, 복호화된 AES 대칭키로 실제 데이터를 AES 복호화한다.

 

 

 

 

 

반응형

댓글

Designed by JB FACTORY