암호화 crypto
- REACT & NODE
- 2021. 5. 20.
결국 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 복호화한다.
'REACT & NODE' 카테고리의 다른 글
throttle 과 debounce 그리고 lodash 를 사용하여 실제 React 에 적용하는 법. 그리고 useCallback 에서의 lint 에러. (0) | 2021.05.29 |
---|---|
Fix the "Maximum Update Depth Exceeded" Error in React (0) | 2021.05.25 |
dns (0) | 2021.05.11 |
테스트 json api 제공 서비스 (0) | 2021.05.10 |
리덕스 스타일링 가이드 요약 (0) | 2021.05.10 |