
최근 앱 개발중에 회원가입시 PASS 본인인증 모듈을 적용시키면서 회원가입 플로우를 개발하고 있었는데
이 과정에서 회원 정보 보호를 위해 userId와 PIN 관리 전략을 분리하여 개발했다.
회원가입시 userId는 서버에서 만들고 이걸 암호화해서 DB에 저장하고,
PIN은 DB에 저장하는것이 아닌 단말기 로컬의 SecureStorage에 암호화된 형태로 저장했다.
로그인시에 SecureStorage에 PIN을 찾아서 사용자가 입력한 PIN과 SecureStorage에 저장된 PIN을 검증해서
PIN을 AES-256 암호화 키로 사용해서 Hive Box 복호화에 사용해 Hive Box를 열고
Hive Box에서 userId(authToken)을 추출해서 서버에 userId로 인증 요청을 보내서 로그인 로직을 완성했다.
이번 기회에 SecureStorage에 대해서 더 알아보고 싶었다.
SecureStorage
iOS Keychain과 Android Keystore를 활용한 네이티브 수준의 보안 저장소다.
운영체제 수준에서 암호화를 제공한다고 한다.
기술적 특징으로는
- 하드웨어 암호화 TEE(Trusted Execution Environment) 활용
- OS수준 보호 - 루팅/탈옥된 기기에서도 상당한 보안성 유지
- 생체 인증 연동 - Face ID, Touch ID, 지문 인식과 연동 가능
- 앱별 격리 - 앱 삭제 시에만 데이터 제거
라는 특징이 있다.
React Native App
↓
Native Bridge (Capacitor/Cordova)
↓
iOS Keychain / Android Keystore
↓
Hardware Security Module (HSM)
단점으로는
- 플랫폼 의존성 - iOS/Android 별도 구현 필요
- 복잡한 설정 - Native 브릿지 구성 필요
- 제한된 용량 - 대용량 데이터 저장 부적합
- 비동기 처리 - 모든 작업이 비동기 처리
라고 한다.
// PIN 기반 보안 체계
const securityFlow = {
// 1. PIN 저장 (6자리 숫자)
store: async (pin: string) => {
await setValue(pin); // SecureStorage에 암호화 저장
},
// 2. PIN 검증 (로그인 시)
verify: async (inputPin: string) => {
return await checkValue(inputPin); // 하드웨어 수준 검증
},
// 3. 생체 인증 연동
biometric: async () => {
const authenticated = await native.authenticate();
if (authenticated) {
return await readValue(); // PIN 반환
}
return null;
}
};