Android / 실전 사례 분석 / 읽는 시간: 18분

Aegis: 인증 코드가 60초에 바뀌는 이유는?

인증 앱은 여섯 자리 숫자와 타이머처럼 보입니다. REA의 Aegis 분석 기록을 따라가고 시간을 직접 조절할 수 있는 작은 구현을 체험해 보세요.

이 페이지의 내용
목표

시간 기반 코드 계산 하나를 파악해 브라우저에서 재구현하고 30초 구간이 바뀌는 경계를 검증합니다.

시작하기 전에

데모는 바로 사용할 수 있습니다. APK 분석을 직접 진행하려면 REA, Aegis v3.4.3, 전체 JDK 17+와 다음 가이드의 jadx 프로바이더가 필요합니다: Android 가이드.

01. 59초에서 60초로 이동하기

아래 두 시간 버튼을 눌러 보세요. 고정된 공개 테스트 키를 사용하면 59초의 코드는 287082이며 60초의 코드는 359152입니다. 30초로 돌아가면 첫 코드가 다시 나옵니다. 30초와 59초가 같은 시간 구간에 속하기 때문입니다.

30초 인증 코드 체험형 실습

공개 테스트 키 · SHA-1 · 6자리

287082

Unix 시간 59초 카운터 1

0초30초60초90초120초

59 ÷ 30 → 카운터 1. 60초가 되면 카운터가 2가 됩니다.

RFC 6238의 공개 테스트 키로 새로 작성한 학습용 구현입니다. 계정 비밀 키를 사용하지 않으며 브라우저에서 REA를 호출하지 않습니다.

여기서 숫자는 시계에 표시되는 초가 아닌 Unix 에포크 이후 경과한 초입니다. 데모는 표준 TOTP를 구현하며 다음 공개 ASCII 키를 사용합니다: 12345678901234567890. Aegis 보관함을 읽거나 계정 비밀 키를 사용하지 않습니다.

02. APK에서 시간 기반 메서드 찾기

REA 공식 보고서 는 REA 6.1.0으로 Aegis v3.4.3을 분석한 기록입니다. 과정을 따라가려면 해당 릴리스 받기후 해시를 기록하고 TOTP 클래스를 검색하세요. 아래 명령은 REA 6.4.0을 사용합니다.

터미널
npx -y rea-agents@6.4.0 inspect-android-package "/absolute/path/aegis-v3.4.3.apk" --json
npx -y rea-agents@6.4.0 search-android-classes "/absolute/path/aegis-v3.4.3.apk" Totp --json

반환된 정확한 클래스 이름으로 멤버를 확인합니다. 시간을 직접 지정할 수 있는 다음 메서드의 타임스탬프 오버로드가 유용합니다: getOtp . 같은 이름의 첫 메서드가 맞다고 가정하지 말고 목록에서 올바른 오버로드를 선택하세요.

분석 프롬프트
REA로 /absolute/path/aegis-v3.4.3.apk의 TotpInfo 클래스를 분석하세요. 타임스탬프를 받는 getOtp 오버로드를 선택하고 카운터 인코딩, HMAC, 절단, 십진수 형식화까지 호출을 추적하세요. 기본 주기, 해시, 자릿수를 파악하고 확인한 각 메서드를 명시하세요. 기본값과 계정별 설정을 구분하고 APK는 실행하지 마세요.

03. 전체 계산 과정 파악하기

30으로 나누는 코드를 찾는 것은 시작일 뿐입니다. 원본 보고서는 다섯 단계를 연결합니다. 시간을 내림해 카운터로 바꾸고, 8바이트 빅 엔디언으로 인코딩한 뒤 키로 HMAC을 계산합니다. 해시에서 양의 31비트 값을 선택하고 선행 0을 보존하며 여섯 자리로 줄입니다.

시간→카운터→HMAC→6자리

익숙한 소스 이름에 의존하지 말고 반환된 메서드 호출을 따라가세요. 분석한 버전에서는 최적화로 생성 헬퍼가 다음 위치에 배치되었습니다: kotlin.ExceptionsKt. 보고서는 기본값인 SHA-1, 여섯 자리, 30초와 계정별 설정도 구분합니다.

04. 규칙을 재구현하고 경계 테스트하기

파악한 동작을 독립적으로 구현하고 공개 테스트 벡터로 확인하세요. 시간 경계 직전·직후, 선행 0이 있는 결과, 여섯 자리와 여덟 자리 출력을 테스트합니다. 이 예제에서는 인접 구간의 코드가 다르지만 수학적으로 항상 다르다는 보장은 없습니다.

재구현 프롬프트
파악한 동작을 바탕으로 작은 독립 TOTP 구현을 작성하세요. RFC 6238 공개 테스트 키만 사용하고 SHA-1 참조 타임스탬프 여섯 개 모두의 여덟 자리 값과 여섯 자리 나머지를 검증하세요. 29/30 및 59/60 경계를 테스트하고 선행 0을 보존하세요. 분석한 메서드와의 차이를 설명하고 보관함이나 Android 앱 전체를 재구현했다고 주장하지 마세요.
Unix 시간카운터6자리 결과검증 내용
290755224첫 구간의 끝
301287082경계 통과
591287082같은 시간 구간
602359152다음 카운터 값
111111110937037036081804선행 0 유지

05. ‘133개 검증’의 의미

원본 프로젝트는 선택한 디컴파일 메서드로 구성한 JVM 검증 환경과 독립 재구현 사이에서 133개 입력 결과가 일치했다고 보고합니다. 원본 APK를 실행하지는 않았습니다. 이는 해당 계산만 뒷받침하며 앱 전체의 동등성을 입증하지 않습니다.

이 사이트는 별도의 WebCrypto 데모를 작성해 공개 SHA-1 벡터 여섯 개를 두 가지 출력 자릿수로 검증했습니다. 또한 0~120의 모든 정수 초를 별도 Node HMAC 구현과 비교했습니다. 원본 APK 분석이나 Java 검증 환경 실행을 재수행한 것은 아닙니다.

출처: REA Aegis 검증 보고서 · RFC 6238 테스트 벡터. 데모와 설명은 독립적으로 제작했습니다. Aegis 앱 소스는 재배포하지 않습니다.

다음 분석Notion은 서식 있는 텍스트를 어떻게 복사할까요? →

REA가 처음인가요? REA란? · 가이드 검증 방법