핵심 명제 — "절대적으로 안전한 보관 방식"은 존재하지 않는다. 휴대폰에 지갑 키를 보관하는 것은 실용적으로 충분히 안전할 수는 있지만, 완벽하게 안전할 수는 없다.
1. "완벽한 안전"이라는 질문의 함정
"완벽하게 안전한가?"라는 질문은 사실상 기밀성·가용성·사용성의 트릴레마를 간과한 질문이다. 어떤 시스템도 이 세 가지를 동시에 보장할 수 없다.
- 기밀성(Confidentiality) — 키가 절대 유출되지 않음
- 가용성(Availability) — 사용자가 필요할 때 항상 키에 접근 가능
- 사용성(Usability) — 평범한 사용자가 실수 없이 다룰 수 있음
이 세 가지는 서로 맞물려 있어, 하나를 높이면 다른 쪽이 흔들린다. 키를 종이에 적어 금고에 넣고 인터넷과 완전히 단절하면 기밀성은 올라가지만 가용성과 사용성은 무너진다. 휴대폰은 정반대 지점, 즉 가용성·사용성을 높이는 대신 공격 표면을 넓힌 선택이다.
따라서 물어야 할 것 — "완벽하게 안전한가?"가 아니라 "어떤 위협 모델을 전제로, 어느 정도까지 안전한가?" 이다.
2. 위협 모델 (Threat Model)
키 보관의 안전성은 "누구로부터, 무엇을 지키려 하는가"를 정의하지 않으면 평가할 수 없다.
| 공격자 유형 | 역량 | 휴대폰 키 보관의 방어 수준 |
|---|---|---|
| 일반 절도범 (기기 분실/도난) | 물리적 접근, 비밀번호 모름 | 🟢 강함 — Secure Enclave + 생체인증으로 사실상 차단 |
| 원격 멀웨어 / 악성 앱 | 앱 권한 내 코드 실행 | 🟡 중간 — 샌드박스·키스토어로 키 추출은 어렵지만 화면·입력 가로채기 위험 |
| 피싱 / 소셜 엔지니어링 | 사용자를 속여 서명·시드 입력 유도 | 🔴 약함 — 하드웨어가 아무리 강해도 사용자가 직접 승인하면 무력 |
| 정교한 표적 공격 (0-day) | 커널/OS 취약점, 무클릭 익스플로잇 | 🔴 약함 — Pegasus류 공격 앞에서는 격리 경계 붕괴 가능 |
| 국가급 / 공급망 공격 | 펌웨어·하드웨어·인증서 체인 침투 | 🔴 매우 약함 — 신뢰 기반 자체가 침해됨 |
핵심 통찰 — 휴대폰 키 보관은 일상적 위협(절도·분실)에는 매우 강하지만, 사용자를 속이는 공격(피싱)과 국가급 표적 공격에는 본질적으로 취약하다. 실제 자산 탈취의 상당수도 0-day가 아니라 피싱과 사용자 실수에서 발생한다.
3. 휴대폰은 키를 어떻게 보관하는가
현대 스마트폰은 키를 디스크에 평문으로 저장하지 않는다. 그러나 "어떻게 보관하는가"를 제대로 답하려면 한 문장으로는 부족하다. 키 보관을 세 가지 질문으로 분해해서 보자.
- 키는 어디에 사는가 — 저장 계층
- 무엇이 키 사용을 통제하는가 — 보호 메커니즘
- 보안 영역은 무엇을 보장하고, 무엇을 보장하지 못하는가 — 신뢰 경계와 그 한계
3.1 키는 어디에 사는가 — 저장 계층의 스펙트럼
같은 Keystore API를 호출해도, 실제 키가 어느 계층에 backing되는지에 따라 안전성은 완전히 달라진다. 키 저장 위치는 단일 지점이 아니라 보호 강도의 스펙트럼이다.
- 소프트웨어 키스토어 — 키가 OS가 접근 가능한 영역에 (보통 암호화되어) 저장된다. 사용 시점에는 normal-world 메모리로 복호화되므로, OS가 뚫리면 키도 함께 위험해진다. 가장 약한 계층이다.
- TEE(Trusted Execution Environment) — ARM TrustZone의 secure world에서 키 연산이 일어난다. normal-world의 안드로이드 커널과 격리되어 있어, 단순 루팅만으로는 키를 추출할 수 없다. 다만 TEE 자체의 취약점은 별도로 존재한다.
- 전용 보안 칩(Secure Element) — iOS의 Secure Enclave, 안드로이드의 StrongBox(예: Pixel의 Titan M2)처럼 물리적으로 분리된 칩이다. 자체 CPU·메모리·난수원·내결함성을 갖춰 키 추출 난이도가 가장 높다. 단, StrongBox는 기기에 따라 없을 수 있다.
| 저장 계층 | 격리 경계 | OS 루팅 시 키 추출 | 예시 |
|---|---|---|---|
| 소프트웨어 | 프로세스 · 디스크 암호화 | 🔴 가능 — 메모리에서 복호화돼 노출 | 구형·저가 기기 fallback |
| TEE | TrustZone secure world | 🟡 어려움 — TEE 취약점이 필요 | 대부분의 안드로이드 |
| 전용 보안 칩 | 물리적으로 분리된 SE | 🟢 사실상 불가 | SEP(iOS), StrongBox / Titan M2 |
같은 "휴대폰에 키를 둔다"도 이 표의 어느 행에 해당하느냐에 따라 위협 모델이 달라진다. 지갑이 어떤 계층을 요구하는지(예: 안드로이드의 setIsStrongBoxBacked(true))가 실제 보안 수준을 좌우한다.
3.2 무엇이 키 사용을 통제하는가 — 네 가지 보호 메커니즘
키를 "꺼낼 수 없게" 만드는 것(격리)은 네 가지 메커니즘 중 하나일 뿐이다. 현대 보안 칩은 다음을 함께 강제한다.
- 격리(Isolation) — 개인키 비트가 보안 경계 밖 메모리에 절대 나타나지 않는다. 앱이 다루는 것은 키가 아니라 키 핸들이다.
- 접근 게이팅(Auth binding) — 키 사용을 생체·패스코드 인증과 묶는다. iOS는
kSecAccessControl, 안드로이드는setUserAuthenticationRequired. 인증 유효 범위는 시간 기반(한 번 인증 후 N초 동안 허용)과 건별(서명 한 번마다 재인증)으로 나뉜다. - 레이트 리밋과 소거(Rate limiting / wipe) — 무차별 대입을 하드웨어 카운터로 지연시키고, 임계치를 넘으면 데이터를 소거한다. iOS는 패스코드 시도 간 지수적 지연과 자동 소거 옵션, 안드로이드는 Gatekeeper·Weaver throttling과 StrongBox의 모노토닉 카운터를 쓴다.
- 어테스테이션(Attestation) — 키가 실제로 하드웨어에 backing됐음을 인증서 체인으로 증명한다. 안드로이드 Key Attestation, iOS App Attest가 여기 해당한다. 서버가 "이 키는 진짜 보안 칩 안에 있다"를 원격으로 검증할 수 있다.
이 네 가지의 공통 뿌리는 하드웨어 신뢰의 근원(root of trust)이다. 칩에 영구 기록된 device UID와 부트 체인 검증이 깨지지 않았다는 가정 위에서만 위 보장이 성립한다.
3.3 iOS vs Android — 구현 비교
| 구분 | iOS | Android |
|---|---|---|
| 보안 하드웨어 | Secure Enclave (SEP) | TEE (TrustZone) / StrongBox (전용 보안 칩) |
| 키 저장 API | Keychain + Secure Enclave | Android Keystore |
| 저장 계층 결정 | 항상 SEP 또는 Data Protection 클래스 키로 보호 | 소프트웨어 / TEE / StrongBox 중 기기·요청에 따라 결정 |
| 접근 통제 | Data Protection 클래스 + kSecAccessControl | setUserAuthenticationRequired + BiometricPrompt |
| 키 추출 가능성 | 비대칭 키는 SEP 밖으로 추출 불가 (서명만 위임) | StrongBox·TEE 키는 추출 불가, 소프트웨어 키스토어는 상대적으로 약함 |
| 무차별 대입 방어 | 패스코드 지연 + 자동 소거 옵션 | Gatekeeper·Weaver throttling, StrongBox 카운터 |
| 하드웨어 증명 | App Attest / DeviceCheck | Key Attestation (구글 루트 체인) |
| 생체 연동 | Face ID / Touch ID로 접근 게이팅 | BiometricPrompt + setUserAuthenticationRequired |
3.4 신뢰 경계 (Trust Boundary) 구조
멀웨어가 앱을 완전히 장악해도 키는 못 꺼낸다. 단, 원하는 트랜잭션에 서명을 '요청'할 수는 있다 (Fig 4).
핵심은 개인키가 보안 영역 밖으로 나오지 않고, 서명 연산만 맡긴다는 점이다. 이상적으로 동작하면 멀웨어가 앱을 완전히 장악해도 키 자체는 빼낼 수 없다. 그러나 이 모델에는 두 가지 근본적 한계가 있다.
- 서명 위임의 역설 — 키를 빼내지 못해도, 멀웨어가 원하는 트랜잭션에 서명을 요청하면 보안 영역은 그대로 서명해준다. 키의 기밀성은 지켜지지만 자산은 털릴 수 있다.
- 신뢰 경계의 전제 — "보안 영역은 안전하다"는 가정은 펌웨어·OS·하드웨어가 침해되지 않았을 때만 성립한다.
3.5 Secure Enclave의 두 가지 결정적 제약 — Export 불가, 그리고 알고리즘 불일치
블록체인 지갑 관점에서 Secure Enclave(SEP)에는 흔히 간과되는 두 가지 제약이 있다.
① 개인키를 export할 수 없다 (Non-exportable by design)
SEP에서 생성된 키는 칩 내부에서 만들어지며, 개인키 비트는 SEP 경계를 절대 벗어나지 않는다. 앱이 다루는 것은 키 자체가 아니라 키를 가리키는 불투명한 참조값(iOS의 SecKey, Android의 KeyStore alias)뿐이다.
- 앱은 "이 데이터에 서명해줘" / "이 값과 ECDH 해줘"라고 요청만 할 수 있고, 키 원본(raw bytes)은 읽을 수 없다.
- 루팅·탈옥으로 OS를 장악해도 SEP 밖으로 키를 꺼낼 수 없다 (얻는 것은 여전히 핸들뿐).
- 장점: 멀웨어가 키를 복사해 다른 기기로 가져갈 수 없다.
- 단점(역설): 백업·다른 기기로의 이전·시드 문구 표시가 원천적으로 불가능하다. 그래서 SEP 키는 "분실하면 끝"이며, 가용성 측면에서는 오히려 부담이 된다.
② 지원 알고리즘이 달라 블록체인 키로 직접 쓸 수 없다
여기가 핵심이다. Secure Enclave가 하드웨어 수준에서 지원하는 것은 NIST P-256(secp256r1, prime256v1) 곡선의 ECC 키와 ECDSA/ECDH 연산뿐이다.
| 구분 | 곡선 / 알고리즘 | SEP에서 직접 서명 가능? |
|---|---|---|
| Bitcoin / Ethereum (EOA) | secp256k1 (ECDSA) | ❌ 불가 — SEP가 지원하지 않는 곡선 |
| Solana / Aptos 등 | Ed25519 | ❌ 불가 — SEP 미지원 |
| Secure Enclave 네이티브 | secp256r1 (P-256) | ✅ 가능 — 단, 체인이 P-256 검증을 지원해야 의미 있음 |
즉 이더리움 개인키를 SEP 안에 넣고 secp256k1 서명을 만들어내는 것은 불가능하다. secp256k1과 secp256r1은 곡선 파라미터가 다른 별개의 암호 체계이기 때문이다. 그래서 현실의 모바일 지갑은 두 가지 우회 패턴 중 하나를 쓴다.
- SEP 키를 래핑 키(KEK)로 사용 — 실제 secp256k1 개인키는 Keychain/Keystore에 암호화된 상태로 저장하고, 그 암호화 키를 SEP가 생체인증으로 게이팅한다. 서명 시점에 키를 앱 메모리로 복호화해야 하므로 짧은 노출 구간이 남는다.
- P-256 키를 AA 계정의 서명자로 사용 — Ethereum EOA 자체를 secp256r1로 바꾸는 것이 아니라, AA(Account Abstraction) 계정이 P-256 서명을 유효한 소유자 서명으로 인정하게 만든다. ERC-4337은 실행 모델을, ERC-1271은 컨트랙트 서명 검증 인터페이스를, ERC-7913은 Ethereum 주소가 없는 키를 서명자로 표현하는 방식을 제공하고, RIP-7212/EIP-7951 계열 precompile은 P-256 검증 비용을 낮춘다.
정리하면 — SEP는 "키를 빼낼 수 없는 금고"지만, 그 금고가 다룰 수 있는 열쇠 모양(P-256)이 블록체인이 요구하는 열쇠 모양(secp256k1)과 다르다. 이 불일치가 모바일 지갑 설계의 핵심 제약이자, Passkey 기반 AA로 전환하게 만드는 동력이다.
4. 공격 경로별 분석
4.1 물리적 탈취 — 방어 우수 🟢
기기를 훔쳐도 잠금 화면·생체인증·SEP 결합으로 키 접근이 차단된다. 무차별 대입은 하드웨어 레벨에서 시도 횟수가 제한되고 데이터가 소거된다. 이 영역에서 휴대폰은 종이지갑보다 안전할 수 있다.
4.2 멀웨어 / 악성 앱 — 부분 방어 🟡
- 앱 샌드박스와 키스토어 덕분에 키 추출은 어렵다.
- 그러나 오버레이 공격(가짜 화면), 접근성 권한 남용, 클립보드 하이재킹(주소 바꿔치기), 스크린 캡처로 시드 문구를 노릴 수 있다.
- 특히 시드 문구를 사용자가 화면에 입력·표시하는 순간이 가장 약한 고리다.
아래는 앞에서 말한 서명 위임의 역설—키는 안전하지만 자산은 털리는 공격 흐름이다.
4.3 사이드채널 / 추론 공격 — 잔존 위험 🟡
전력 분석, 타이밍, 캐시 공격 등은 학술적으로 입증되어 있다. 일반 사용자에게는 비현실적이지만 고가치 표적에는 유효할 수 있다.
4.4 OS / 커널 0-day — 막아내기 어려운 영역 🔴
Pegasus나 무클릭 iMessage 익스플로잇 사례처럼, 커널 권한을 탈취한 공격자는 신뢰 경계 자체를 우회하거나 서명 흐름을 조작할 수 있다. 이 단계에 이르면 "하드웨어가 키를 지킨다"는 보장은 크게 약해진다.
4.5 피싱 / 소셜 엔지니어링 — 최대 위협 🔴
기술적으로 가장 견고한 지갑도, 사용자가 악성 트랜잭션에 직접 서명하거나 시드를 가짜 사이트에 입력하면 무력해진다. 실제 손실의 대부분이 여기서 발생한다. 이는 휴대폰만의 문제가 아니라, 신뢰 여부를 마지막에 판단하는 주체가 결국 사람이라는 구조적 한계다.
5. 왜 "완벽"이 불가능한가 — 구조적 이유
구조의 문제 — 완벽한 안전을 가로막는 것은 특정 버그 하나가 아니라 시스템 구조 자체다.
- 겹겹이 쌓인 신뢰 전제 — 칩 제조사 → 펌웨어 → OS → 앱 → 사용자까지 여러 단계가 모두 안전하다고 가정해야 한다. 이 중 어느 한 단계만 깨져도 전체 보장은 무너진다. 사용자는 이 전제들을 직접 검증할 수 없다.
- 검증하기 어려운 TCB(Trusted Computing Base) — Secure Enclave 펌웨어는 폐쇄적이며 사용자가 직접 감사할 수 없다. 결국 "안전하다고 믿는" 영역이지, 사용자가 스스로 증명할 수 있는 영역은 아니다.
- 마지막 판단자인 사람 — 최종 승인은 사람이 한다. 사회공학은 암호학을 정면으로 깨지 않고도 우회한다.
- 방어와 공격의 비대칭성 — 방어자는 모든 구멍을 막아야 하지만, 공격자는 하나만 찾으면 된다.
- 시간차 문제(TOCTOU 류) — 검증한 시점과 실제로 사용하는 시점 사이에 상태가 바뀔 수 있다. 안전은 한순간의 스냅샷이 아니라 계속 흔들리고 침식되는 상태다.
방어와 공격의 비대칭 — 방어자는 모든 구멍을 막아야 하지만, 공격자는 단 하나만 찾으면 된다.
6. 그렇다면 어떻게 "충분히" 안전하게 만드는가
완벽이 불가능하다고 해서 "포기하라"는 뜻은 아니다. 핵심은 단일 실패점(single point of failure)을 없애고 위험을 분산하는 것이다.
| 완화 전략 | 막아내는 위협 | 트레이드오프 |
|---|---|---|
| 하드웨어 키스토어 강제 (StrongBox/SEP) | 키 추출, 물리적 탈취 | 구형 기기 호환성 |
| 생체 + 트랜잭션 단위 인증 | 무단 서명, 백그라운드 멀웨어 | 사용성 마찰 증가 |
| MPC (다자간 연산) / 키 분할 | 단일 기기 침해 | 구현 복잡도, 인프라 의존 |
| 멀티시그 (다중 서명) | 단일 키 탈취, 내부자 | UX 복잡, 가스 비용 |
| 소셜 리커버리 / AA 계정 | 키 분실, 가용성 문제 | 가디언 신뢰·담합 위험 |
| 거래 한도 · 화이트리스트 · 타임락 | 피싱 후 즉시 탈취 | 긴급 송금 불편 |
| 하드웨어 지갑 분리 (콜드 키) | 온라인 공격 전반 | 휴대성·편의성 희생 |
여러 방어막을 겹겹이 쌓아 한 계층이 뚫려도 다음 계층이 막아주게 만드는 계층 방어(defense in depth) 구조는 다음과 같다.
실무 권고 — 휴대폰에 키를 두는 것은 소액·일상 거래에 합리적인 선택이다. 단, ① 하드웨어 키스토어를 강제하고 ② 트랜잭션마다 명시적으로 생체 승인을 받으며 ③ 고액 자산은 멀티시그/MPC 또는 콜드 월렛으로 분리하고 ④ 한도·화이트리스트로 피싱 피해를 제한하는 계층 방어(defense in depth)가 필요하다. "키를 어디 두느냐"보다 "위험을 어떻게 분산하느냐"가 더 중요하다.
자산 규모에 따른 보관 전략 선택은 대략 다음 기준을 따른다.
7. Passkey로 키 관리를 대체하는 기법
앞서 본 SEP의 제약(내보내기 불가 + P-256만 지원)은 역설적으로 Passkey와 정확히 맞물린다. Passkey는 본질적으로 SEP/StrongBox에 저장되는, 밖으로 꺼낼 수 없는 P-256(secp256r1) 키쌍이기 때문이다. 시드 문구 기반 키 관리를 Passkey로 대체하려는 흐름은 다음과 같이 정리된다.
7.1 Passkey란
- WebAuthn/FIDO2 표준의 자격증명으로, 하드웨어 보안 영역에 저장된 P-256 키쌍이다. 개인키는 SEP 밖으로 나오지 않는다.
- 출처 바인딩(origin-bound)이라 가짜 사이트에서는 서명 요청 자체가 성립하지 않는다 → 구조적으로 피싱에 강하다. (시드 문구의 가장 큰 약점을 정면으로 보완)
- iCloud Keychain / Google Password Manager로 동기화(synced passkey)되거나, 특정 기기에 묶이는 device-bound passkey로 운용된다.
7.2 Passkey 기반 지갑을 구성하는 표준 조합
Passkey가 "지갑 키를 대체한다"는 말은 Ethereum EOA가 곧바로 secp256r1 트랜잭션을 서명한다는 뜻이 아니다. 더 정확히는 Passkey의 P-256 키를 AA(Account Abstraction) 계정의 소유자 키로 인정하고, 그 서명을 표준화된 검증 경로로 처리한다는 뜻이다.
| 구성 요소 | 담당하는 층 | 핵심 역할 |
|---|---|---|
| Passkey / WebAuthn | 사용자 기기 | SEP/StrongBox 안의 P-256 키가 사용자 생체 인증 후 서명한다. 개인키는 기기 밖으로 나오지 않는다. |
| ERC-4337 | AA 실행 모델 | EOA 서명 없이 UserOperation을 제출하고, AA 계정의 validateUserOp가 소유자 서명을 검증한다. |
| ERC-1271 | 컨트랙트 서명 호환성 | AA 계정이 isValidSignature(hash, signature)로 "이 서명은 이 계정에 대해 유효하다"고 표준 방식으로 응답한다. |
| ERC-7913 | 주소 없는 서명자 표현 | P-256처럼 Ethereum 주소가 없는 키를 verifier || key 형태의 signer로 표현하고, 전용 verifier가 검증한다. |
| RIP-7212 / EIP-7951 | EVM precompile | secp256r1 서명 검증을 EVM에서 싸고 빠르게 처리해 Passkey 기반 AA를 실용화한다. |
이 조합에서 각 표준의 역할은 서로 겹치지 않는다. ERC-4337은 "어떻게 AA 계정이 트랜잭션을 실행할 것인가"를 다루고, ERC-1271은 "컨트랙트 계정의 서명을 외부에서 어떻게 검증할 것인가"를 다루며, ERC-7913은 "Ethereum 주소가 없는 키를 signer로 어떻게 표현할 것인가"를 다룬다. RIP-7212/EIP-7951은 이 모든 구조가 가스 비용 때문에 비현실적으로 변하지 않도록 P-256 검증을 네이티브 연산에 가깝게 낮춰주는 기반이다.
7.3 ERC-1271 — AA 계정의 서명을 외부 세계와 호환시키는 표준
EOA는 주소와 개인키가 1:1로 묶여 있고, 서명 검증도 ecrecover 중심으로 동작한다. 반면 AA 계정은 컨트랙트이므로 "이 계정이 어떤 서명을 유효하다고 볼 것인가"를 내부 로직으로 정할 수 있다. 이때 외부 dApp, 프로토콜, 컨트랙트가 매번 각 지갑의 내부 구현을 알 필요는 없다. ERC-1271은 컨트랙트 계정이 서명 유효성을 표준 인터페이스로 답하게 해주는 규격이다.
- 핵심 함수는
isValidSignature(hash, signature)다. - AA 계정은 내부에서 P-256, secp256k1, 멀티시그, 세션 키, 소셜 리커버리 등 어떤 검증 방식을 쓰든 상관없이, 최종적으로 "유효함" 또는 "유효하지 않음"을 표준 형식으로 반환한다.
- Passkey 지갑에서는
signature안에 WebAuthn 서명 데이터와 필요한 메타데이터가 들어가고, AA 계정은 이를 해석해 P-256 검증 경로로 넘긴다. - 즉 ERC-1271은 P-256을 직접 정의하는 표준이 아니라, P-256 기반 AA 계정이 기존 dApp 생태계와 호환되도록 해주는 접점이다.
한 문장 요약 — ERC-1271은 "컨트랙트 지갑도 표준 방식으로 서명 검증 결과를 말할 수 있게 해주는 규격"이다. Passkey는 이 내부 검증 로직의 한 종류로 들어간다.
7.4 ERC-7913 — Ethereum 주소가 없는 키를 signer로 다루는 방식
P-256 Passkey의 어려움은 단지 검증 비용만이 아니다. secp256k1 EOA처럼 자연스럽게 Ethereum 주소가 생기는 키가 아니기 때문에, "이 P-256 공개키를 어떤 signer로 표현할 것인가"라는 문제가 생긴다. ERC-7913은 이 지점을 다룬다.
- 기존 모델에서는 signer가 대체로 Ethereum address다.
- 하지만 Passkey, 하드웨어 보안 키, RSA 키, 다른 체계의 공개키는 그 자체로 Ethereum 주소를 갖지 않는다.
- ERC-7913은 signer를 단순 주소가 아니라
verifier || key형태의 바이트열로 표현한다. - 여기서
verifier는 해당 키 타입을 검증할 컨트랙트 주소이고,key는 P-256 공개키 등 실제 식별자다. - 검증 시에는 signer에 포함된 verifier가 signature를 해석하고, 필요한 경우 P-256 precompile을 호출해 서명을 검증한다.
이 방식의 장점은 AA 계정이 여러 종류의 키를 같은 틀 안에서 다룰 수 있다는 점이다. 예를 들어 한 계정이 다음과 같은 signer 조합을 가질 수 있다.
- iPhone Passkey P-256 키
- Android StrongBox P-256 키
- 하드웨어 보안 키
- 복구용 guardian 키
- 세션 키 또는 제한 권한 키
즉 ERC-7913은 Passkey를 "특수 예외"로 처리하기보다, 주소 없는 키 전반을 AA 계정의 signer로 편입시키는 일반화된 표현 방식에 가깝다.
7.5 RIP-7212와 EIP-7951 — P-256 검증을 실사용 가능한 비용으로 낮추는 기반
P-256 서명은 원래 WebAuthn·Passkey·Secure Enclave·Android Keystore가 널리 쓰는 곡선이다. 문제는 EVM이 전통적으로 secp256k1 중심으로 설계되어 있었고, P-256 검증을 Solidity만으로 구현하면 가스 비용이 너무 크다는 점이다.
- RIP-7212는 주로 L2/rollup 환경에서 secp256r1 검증 precompile을 제공하려는 제안이다. Passkey 기반 지갑이 L2에서 빠르게 실험되고 실용화될 수 있었던 이유가 여기에 있다.
- EIP-7951은 Ethereum 본류의 EIP 흐름에서 secp256r1 검증 precompile을 표준화하려는 방향이다. RIP-7212 계열 구현과의 호환성을 고려하면서, P-256 검증을 더 안전하고 명확한 체인 레벨 기능으로 다루려는 성격이 강하다.
- precompile이 있으면 AA 계정이나 verifier 컨트랙트는 복잡한 타원곡선 연산을 Solidity로 직접 수행하지 않고, 정해진 precompile에
hash,r,s, 공개키 좌표 등을 넘겨 검증 결과를 받을 수 있다. - 결과적으로 P-256 검증은 "가능은 하지만 비싼 기능"에서 Passkey 지갑에 실제로 쓸 수 있는 기능으로 바뀐다.
precompile의 핵심 — RIP-7212/EIP-7951의 핵심은 "Passkey가 서명하게 해준다"가 아니라, Passkey가 만든 P-256 서명을 온체인에서 감당 가능한 비용으로 검증하게 해준다는 점이다. 서명은 기기 안의 SEP/StrongBox가 만들고, 체인은 그 서명이 유효한지만 확인한다.
7.6 secp256r1을 직접 서명자로 쓴다는 말의 정확한 의미
곡선 불일치 문제는 "EOA 서명 알고리즘을 바꾼다"기보다 서명 검증의 위치를 AA 계정으로 옮긴다는 방식으로 해결된다.
- EOA는 여전히 secp256k1 중심 — 기본 Ethereum 계정의 트랜잭션 서명 체계는 secp256r1로 바뀐 것이 아니다.
- AA 계정은 서명 규칙을 스스로 정의 — ERC-4337 계정은
validateUserOp안에서 P-256, 멀티시그, 소셜 리커버리 등 원하는 소유자 규칙을 구현할 수 있다. - ERC-1271은 외부 호환성을 제공 — dApp이나 다른 컨트랙트는 AA 계정의 내부 키 종류를 몰라도 표준 인터페이스로 서명 유효성을 확인할 수 있다.
- ERC-7913은 P-256 키를 signer로 표현 — Passkey처럼 Ethereum 주소가 없는 키도 독립적인 signer로 다룰 수 있게 해준다.
- RIP-7212/EIP-7951은 비용 문제를 해결 — P-256 검증을 Solidity로만 처리하면 비싸지만, precompile이 있으면 실사용 가능한 수준으로 낮아진다.
전체 흐름은 다음과 같다. 시드 문구나 secp256k1 EOA 키가 아니라, SEP 안의 Passkey가 AA 계정의 소유자 서명자로 동작한다.
7.7 트레이드오프 — Passkey가 만능은 아니다
반드시 인지할 것 — Passkey는 피싱 저항성·내보내기 불가·UX 개선이라는 큰 장점이 있지만, 키 보관의 신뢰 기반을 클라우드 계정 쪽으로 옮긴다는 점을 반드시 인지해야 한다.
- 동기화 Passkey의 커스터디 이전 — iCloud/Google 계정이 탈취되면 동기화된 Passkey도 위험하다. 즉 지갑 보안이 클라우드 계정 보안에 종속된다. (device-bound로 두면 안전하지만 분실 시 복구 불가)
- 곡선/가스 비용 — precompile이 없는 체인에서는 P-256 온체인 검증이 비싸다.
- AA 인프라 의존 — Passkey가 직접 서명자로 쓰이는 경로는 EOA가 아니라 AA 계정을 전제한다. 따라서 ERC-4337 번들러, Paymaster, verifier 컨트랙트, 그리고 체인의 P-256 precompile 지원 여부에 영향을 받는다.
- "키 제거"가 아니라 "키 위임" — Passkey도 결국 키다. 단일 Passkey에만 의존하면 단일 실패점이 되므로, 다중 Passkey·멀티시그·소셜 리커버리와 결합해야 한다.
요약 — Passkey 기반 설계는 "시드 문구를 사람이 보관·입력"하는 모델의 약점(피싱·분실·노출)을 구조적으로 줄인다. 특히 Passkey(P-256) → ERC-7913/1271 서명 검증 → ERC-4337 AA 계정 → RIP-7212/EIP-7951 precompile 조합은 SEP의 알고리즘 제약을 우회하면서 export 불가 보안을 그대로 살리는, 현재 가장 유망한 방향이다. 다만 이는 EOA 자체의 서명 체계를 바꾸는 것이 아니라 AA 계정의 소유자 검증 방식을 바꾸는 것이며, 신뢰 가정이 클라우드 계정으로 이동한다는 점도 위협 모델에 반드시 반영해야 한다.
8. 결론
휴대폰에 지갑 키를 보관하는 것은 완벽하게 안전할 수 없다. 그러나 그것은 휴대폰의 결함이라기보다, 어떤 키 보관 방식도 완벽할 수 없다는 보안의 근본 명제에서 비롯된다.
- 완벽한 안전은 존재하지 않는다. 겹겹의 신뢰 전제, 검증하기 어려운 TCB, 마지막 판단자인 사람이라는 구조적 한계 때문이다.
- 휴대폰은 일상 위협(분실·도난)에 강하고, 표적 공격·피싱에 약하다. 위협 모델에 따라 평가가 완전히 달라진다.
- 실제 손실의 대부분은 암호학의 붕괴가 아니라 사용자 기만에서 온다. 따라서 UX와 권한 설계가 암호 알고리즘만큼 중요하다.
- Secure Enclave는 키를 export할 수 없게 만들지만, secp256k1을 직접 지원하지 않는다. 그래서 SEP는 보통 래핑 키로 쓰이거나, Passkey(P-256)를 ERC-4337 AA 계정의 소유자 키로 쓰고 ERC-1271/7913 및 RIP-7212/EIP-7951 계열 검증 경로로 처리하는 흐름이 부상하고 있다.
- 올바른 목표는 "완벽"이 아니라 "단일 실패점 제거 + 위험 분산 + 피해 한정"이다.
결국 보안은 상태(state)가 아니라 과정(process)이다. "완벽하게 안전한가?"라는 이분법적 질문을 "내 위협 모델에 대해 수용 가능한 위험 수준인가?"라는 공학적 질문으로 바꾸는 것이, 이 주제에 대한 가장 정확한 답이다.
부록 — 직접 실험으로 확인하기
이 글의 핵심 주장들은 추상적 설명에 그치지 않는다. 로컬에서 직접 실험으로 확인했고, 전체 코드는 공개 저장소 passkey-lab에 있다.
- Passkey = P-256 키 — 브라우저 WebAuthn으로 Passkey(ES256/P-256)를 만들고 서명한 뒤, 그 서명을
crypto.subtle.verify로 검증했다. 개인키는 보안 영역 밖으로 나오지 않고, 나오는 것은 공개키와 서명뿐이다. - Secure Enclave 서명 — Apple Silicon Mac에서 CryptoKit
SecureEnclave.P256.Signing.PrivateKey()로 SEP 안에 키를 만들고 서명·검증했다 (Secure Enclave available: true,verified locally: true). - AA 계정의 P-256 소유자 (ERC-1271) — secp256k1 EOA 없이, P-256 공개키를 소유자로 갖는 컨트랙트가
isValidSignature에서 Passkey 서명에 ERC-1271 매직값0x1626ba7e를 돌려준다. - 온체인 P-256 검증 비용 — 같은 서명을 온체인에서 검증할 때 순수 Solidity 구현은 약 255,423 가스로 측정됐고, RIP-7212/EIP-7951 precompile은 명세상 3,450 가스다. 이 약 74배 차이가 precompile이 Passkey 기반 AA를 실용화하는 이유를 그대로 보여준다.
특히 브라우저 데모가 출력하는 서명을 그대로 Foundry 테스트에 넣으면, 내 실제 Passkey 서명이 컨트랙트에 의해 온체인에서 검증된다.
ERC-1271 + P-256 검증의 핵심은 짧다.
// P256Account.sol — 소유자가 secp256k1 EOA가 아니라 P-256(Passkey) 키다.
function isValidSignature(bytes32 hash, bytes calldata signature)
external view returns (bytes4)
{
(bytes32 r, bytes32 s) = abi.decode(signature, (bytes32, bytes32));
return P256.verify(hash, r, s, qx, qy) ? bytes4(0x1626ba7e) : bytes4(0xffffffff);
}참고 자료
모바일 보안 하드웨어
- Apple — Apple Platform Security: Secure Enclave
- Android — Android Keystore system
- Android — Key and ID Attestation
Passkey · WebAuthn
- W3C — Web Authentication (WebAuthn) Level 2
- FIDO Alliance — Passkeys
계정 추상화 · 서명 검증 표준
- ERC-4337: Account Abstraction Using Alt Mempool
- ERC-1271: Standard Signature Validation Method for Contracts
- ERC-7913: 주소 없는 키의 signer 표현
- RIP-7212: secp256r1 검증 precompile
- EIP-7951: secp256r1 (P-256) 검증 precompile
실험 코드
- passkey-lab — 이 글의 개념을 직접 확인한 실험 코드 (Passkey · Secure Enclave · 온체인 P-256).