모든 글

읽는 데 8분

CardanoWall이 브라우저에서 키를 보관하는 방식

브라우저에서 CardanoWall은 잠금이 해제된 키를 세션 메모리에 보관하고, IndexedDB에는 암호화된 볼트 암호문과 비밀이 아닌 메타데이터만 기록합니다. 평문 신원 시드나 개인 키는 절대 기록하지 않습니다.

브라우저에서 CardanoWall의 잠금을 해제하면, 잠금이 풀린 시드와 그로부터 파생된 개인 키는 세션 메모리에 자리합니다. 세션 메모리는 잠그거나 로그아웃하거나 탭을 닫는 순간 사라지는 일반 애플리케이션 메모리입니다. 영구 브라우저 저장소(IndexedDB, sessionStorage)에는 암호화된 볼트 암호문과 비밀이 아닌 메타데이터만 들어갑니다. 평문 신원 시드와 파생 개인 키는 그곳에 절대 기록되지 않습니다.

바로 이 구분이 핵심입니다. 브라우저는 로컬에서 서명하고 복호화하기 위해 키 자료를 반드시 쥐고 있어야 합니다. 그래야 암호 연산이 성립하기 때문입니다. 따라서 안전성의 물음은 결코 "브라우저가 키를 만질 수 있는가?"가 아닙니다. 만질 수밖에 없습니다. 진짜 물음은 그 키가 어디에 자리하고 무엇이 디스크에 기록되는가입니다. CardanoWall의 웹 모델은 새로고침 이후에 남는 것이 비밀이 아니라 암호문이 되도록 설계되어 있습니다.

신원이 잠금 해제된 동안 브라우저에는 무엇이 필요합니까?

지금 실제로 수행하는 작업에 쓸 개인 키 자료가 필요할 뿐이며, 세션 그 자체보다 더 오래 남는 것은 필요하지 않습니다.

신원의 잠금을 해제한 뒤, 앱은 다음 작업을 수행해야 할 수 있습니다.

  • Label 309 레코드에 서명합니다.
  • 사용자를 대상으로 봉인된 레코드를 복호화합니다.
  • 들어오는 봉인된 레코드를 시험 복호화하여 받은편지함에 담길 것, 즉 사용자를 대상으로 한 레코드를 찾습니다.
  • 패스키를 추가하거나 제거한 뒤 볼트를 다시 암호화합니다.
  • 사용자가 명시적으로 요청할 때 시드를 표시합니다.
  • 로컬 암호화 캐시를 다시 구축합니다.

이 가운데 어느 것도 공개 키만으로는 불가능합니다. 각 연산에는 신원 시드에서 파생된 개인 자료가 필요합니다. 설계상 이 자료는 세션 메모리에 보관되며, 잠금이나 로그아웃 시 지워집니다. 다만 아래에서 설명할 이유로 이는 최선의 노력(best-effort) 차원에서 이루어집니다.

여기서 말하는 세션 메모리란 무엇입니까?

세션 메모리는 잠금 해제 세션이 끝나면 앱이 폐기하는 임시 인프로세스(in-process) 애플리케이션 메모리입니다.

CardanoWall의 브라우저 앱에서 살아 있는 시드와 그로부터 파생된 키는 일반 UI 상태 바깥의 내부 메모리 맵에 보관됩니다. 반응형 UI 상태에는 비밀이 아닌 사실만 담깁니다. 어떤 신원이 잠금 해제되었는지, 언제 해제되었는지, 설정 중 화면에 표시되는 패스키 등록 메타데이터는 무엇인지 같은 정보입니다. 비밀 바이트는 그 반응형 상태에 결코 들어가지 않습니다.

이 분리가 중요한 까닭은, 일반 UI 상태야말로 앱에서 검사되거나 직렬화되거나 영속화되거나, 혹은 그것을 로깅하는 컴포넌트로 실수로 전달될 가능성이 가장 큰 부분이기 때문입니다. 비밀 자료는 더 작고 의도적으로 열거된 노출면을 가질 자격이 있습니다. 앱에서 비밀 바이트를 내어줄 수 있는 모든 지점, 즉 서명 클로저, 복호화 키, 시드 표시용 비상구, 볼트 재구축 경로는 한 파일에 모두 나열되어 있으며, 각 지점은 살아 있는 버퍼가 아니라 방어적 복사본을 반환합니다.

잠금이 해제된 동안 브라우저는 여전히 비밀을 쥐고 있습니다. 다만 그것을 평범한 앱 데이터로 취급하지 않을 뿐입니다.

IndexedDB에는 무엇이 기록됩니까?

암호화된 볼트 암호문, 곧 서버가 보관하는 것과 동일한 바이트입니다. 그 안에 든 시드가 아닙니다.

IndexedDB는 사용자의 암호화된 신원 볼트를 로컬에 캐싱하는 용도로 쓰입니다. 계정당 한 행이 들어가며, 서버가 보관하는 age로 암호화된 암호문을 그대로 담습니다. 이를 캐싱해 두면 앱은 새로고침 이후에 볼트를 다시 가져오는 왕복 요청 없이, 패스키 한 번으로 상태를 복원할 수 있습니다.

그 로컬 데이터베이스만 읽는 공격자는 사용자의 패스키를 대상으로 암호화된 볼트 바이트를 볼 뿐, 평문 시드를 보지는 못합니다. 그래도 이 캐시는 여전히 민감한 서비스 데이터이므로, 앱은 로그아웃, 계정 삭제, 패스키 변경 시 이를 지웁니다. 그러나 캐시는 신원 자체가 아닙니다. 오직 사용자의 인증기 안에만 그 키가 있는 잠긴 상자입니다. (이 상자를 봉인하는 방식은 CardanoWall이 신원을 저장하는 방식패스키가 신원 볼트를 보호하는 방식을 참고하십시오.)

이러한 기록은 공용 컴퓨터 모드에서, 그리고 기기를 기억하지 않도록 선택한 경우에 완전히 억제됩니다.

sessionStorage에는 무엇이 들어갑니까?

비밀이 아닌 등록 메타데이터만 들어가며, 키 자료는 결코 들어가지 않습니다.

신원 생성 중에 앱은 패스키 등록 메타데이터를 sessionStorage에 미러링합니다. 설정 도중 실수로 새로고침이 일어나도 화면에 보이던 상태가 날아가지 않도록 하기 위함입니다. 이 메타데이터는 본질적으로 비밀이 아닙니다. 자격 증명 ID, 공개 키, 전송 방식, 기기 유형 및 백업 플래그 등 공격자가 얻을 것이 없는 정보뿐입니다.

sessionStorage에서 명시적으로 배제하는 것은 다음과 같습니다.

  • 신원 시드
  • 파생 개인 키
  • WebAuthn PRF(의사 난수 함수) 출력 — 볼트를 잠금 해제하기 위해 패스키가 반환하는 비밀
  • 볼트 평문
  • 복호화된 봉인 콘텐츠

원칙은 단순합니다. 인터페이스 연속성은 새로고침을 넘어 유지되어도 되지만, 신원 비밀은 그래서는 안 됩니다.

어떤 것이 애초에 브라우저 저장소에 절대 들어가서는 안 됩니까?

평문 신원 자료입니다. 어떤 저장소에도 들어가서는 안 됩니다.

다음은 localStorage, sessionStorage, IndexedDB, 쿠키, 로그, 일반 앱 상태에서 모두 배제됩니다.

  • 신원 시드
  • Ed25519 서명 개인 키
  • X25519 수신 개인 키
  • 하이브리드 포스트 양자 수신 비밀(선택적 age1pqc... 주소 뒤에 있는 시드)
  • WebAuthn PRF 출력
  • 볼트 평문
  • 복호화된 봉인 콘텐츠 — 단, 사용자가 명확한 통제권을 가지고 암호화된 로컬 캐시에 명시적으로 저장한 경우는 제외합니다.

근거는 설계 전반을 관통하는 것과 같습니다. 비밀이 기록되는 곳이 많아질수록 그것을 삭제하는 일을 따지기가 어려워지고, 침해가 읽어낼 수 있는 노출면도 커집니다.

공용 컴퓨터 모드란 무엇입니까?

명시적인 공유 기기 모드입니다. 켜져 있는 동안에는 신원과 관련된 어떤 것도 브라우저 저장소에 전혀 기록되지 않습니다.

이를 켜면 앱은 신원 관련 영속화 경로를 모두 건너뜁니다. PIN 볼트도, IndexedDB 볼트 캐시도, 버전 고정도, sessionStorage 등록 미러링도 없습니다. 잠금이 해제된 키는 오직 세션 메모리에만 자리하며, 탭 안에서의 앱 내 이동에는 살아남지만 탭을 닫거나 새로고침하면 사라집니다. 이 토글 자체를 메모리 전용으로 둔 것은 의도된 선택입니다. "나는 공용 컴퓨터를 쓰는 중"이라는 사실을 영속화하면 그 자체가 또 하나의 브라우저 저장소 기록이 되며, 공유 기기는 언제나 다시 묻는 안전한 기본값으로 열려야 하기 때문입니다. 도서관 컴퓨터, 빌린 노트북, 학회장 기기, 뉴스룸 키오스크처럼 사용자가 통제하지 못하는 모든 곳에서 이 모드를 사용하십시오.

이 모드가 하지 못하는 일은 신뢰할 수 없는 기기를 안전하게 만드는 것입니다. 사용자가 시드를 입력하거나 신원을 잠금 해제하는 동안 기기가 이미 침해된 상태라면, 그 기기는 여전히 메모리에서 비밀을 관찰할 수 있습니다. 이 모드는 사용자가 떠난 뒤에 남는 것을 줄여 줄 뿐, 활성 상태의 로컬 멀웨어를 무력화하지는 못합니다. 공용 컴퓨터 모드에서 전체 워크플로를 다룹니다.

JavaScript에서 제로화(zeroization)란 무엇을 뜻합니까?

앱이 비밀 바이트 배열을 다 쓰는 즉시 그것을 0으로 채워 덮어쓰는 것을 뜻합니다.

CardanoWall은 신원이 잠기거나 사용자가 로그아웃할 때 Uint8Array 키 버퍼를 제로화합니다. 가비지 컬렉터가 언젠가 회수해 주기를 막연히 기다리는 대신 능동적으로 처리하는 방식입니다. 이는 좋은 위생 관행이며 충분히 할 가치가 있습니다.

그러나 JavaScript는 비밀을 다루기 위해 견고하게 설계된 환경이 아니며, 이를 솔직히 밝히는 것이 옳습니다. 문자열은 불변이므로, 한 번이라도 문자열이 된 비밀은 그 자리에서 지울 수 없습니다. 가비지 컬렉션 시점은 앱의 통제 밖에 있습니다. 엔진은 메모리를 내부적으로 복사할 수 있습니다. 개발자 도구, 확장 프로그램, 침해된 오리진은 위협 모델 자체를 완전히 바꿔 놓습니다.

따라서 여기서의 제로화는 최선의 노력에 해당하는 조치이지, 보장된 삭제가 아닙니다. 흘러나온 복사본이 떠도는 시간 창을 의미 있게 줄여 주지만, 모든 곳에서 바이트가 사라졌음을 약속하지는 않습니다.

잠금이 해제된 동안 페이지가 침해되면 어떻게 됩니까?

그렇다면 신원은 실제로 위험에 처합니다. 이는 브라우저 기반 암호 연산에서 가장 까다로운 경계입니다.

페이지 콘텐츠에 접근할 수 있는 악성 브라우저 확장 프로그램, 침해된 기기, 혹은 잠금이 해제된 세션 도중에 실행되는 심각한 크로스 사이트 스크립팅(XSS) 버그는 메모리에서 비밀을 읽어내거나, 사용자가 의도하지 않은 대상에 앱이 서명하거나 복호화하도록 만들 수 있습니다. 어떤 웹 앱도 이를 완전히 제거할 수는 없습니다. 네트워크를 통해 도착한 뒤 키를 다루는 코드는, 같은 오리진에서 실행되는 다른 모든 것에 노출되기 때문입니다.

CardanoWall은 시간 창을 줄이기 위해 심층 방어에 기댑니다. 스크립트를 앱 자체의 오리진으로 한정하는 엄격한 콘텐츠 보안 정책(인라인 스크립트 없음, eval 없음, 서드파티 스크립트 일절 로드 없음), 에지에서 모든 응답에 찍히는 보안 헤더, 의도적으로 작게 유지한 비밀 노출면, 평문 영속화 없음, 그리고 탭 포커스 시 자동이 아니라 명시적인 사용자 동작에서만 이루어지는 잠금 해제와 복호화가 그것입니다. 이러한 장치는 가능성과 피해 범위를 줄여 줍니다. 그러나 잠금이 해제된 오리진 안의 악성 스크립트를 무해하게 만들지는 못합니다. 그것은 여전히 이 브라우저 모델이 감수하는, 영향이 가장 큰 위협으로 남습니다.

가장 민감한 신원이라면, 올바른 답은 키 자료를 공유되는 웹 노출면 바깥으로 옮기는 것입니다. 전용의 신뢰할 수 있는 기기에 보관하고, 비밀이 아예 브라우저에 닿지 않는 워크플로를 우선하십시오. 자동화에서의 CLI나, 키를 웹 오리진 대신 로컬 Rust 코어에 보관하는 CardanoWall Desktop이 그렇습니다. (더 넓은 원칙은 키가 기기를 떠나지 않는 이유를 참고하십시오.)

그렇다면 실제로 무엇을 해야 합니까?

브라우저 모델을 의식적으로 사용하고, 작업의 민감도에 맞춰 주의 수준을 조절하십시오.

일상적인 사용에서는 다음과 같이 하십시오.

  • 신원 시드를 안전한 곳에 저장하십시오. 이것이 진짜 백업입니다.
  • 매일 잠금 해제할 패스키를 추가하십시오.
  • 작업을 마치면 잠그거나 로그아웃하십시오.
  • "이 기기 기억하기"는 신뢰하는 기기에서만 사용하십시오.
  • 브라우저와 OS를 최신 상태로 유지하십시오.
  • 위험도가 높은 브라우저 확장 프로그램을 피하십시오.
  • 공유 기기에서는 공용 컴퓨터 모드를 켜십시오.

민감한 작업에는 다음을 추가하십시오.

  • 전용 브라우저 프로필, 더 나아가 전용 기기를 사용하십시오.
  • 빌린 기기에서는 잠금을 해제하지 마십시오.
  • 하드웨어 보안 키를 잠금 해제 요소로 사용하십시오.
  • 위험도가 높은 신원과 일반 신원을 분리하십시오.
  • 봉인된 레코드를 다룰 때 주의하십시오. 복호화할 수 있는 수신자는 그 뒤에 평문을 유출할 수도 있습니다.

요약

CardanoWall의 브라우저 앱은 신원이 잠금 해제된 동안 개인 키가 필요하므로, 이를 영구 저장소가 아니라 세션 메모리에 보관합니다. IndexedDB는 암호화된 볼트 암호문만 캐싱하고, sessionStorage는 비밀이 아닌 설정 메타데이터만 담습니다. 신원 시드와 개인 키는 평범한 브라우저 데이터로서 결코 기록되지 않습니다.

호스팅 볼트 모델과 브라우저 저장소 모델은 서로를 강화합니다. 서버는 자신이 복호화할 수 없는 암호문을 보관하고, 브라우저는 시드를 뒤에 남기지 않으려 최선을 다합니다. 두 주장 가운데 어느 것도 이미 침해된 기기에 대한 보장은 아닙니다. 그리고 그 한계를 분명히 밝히는 것이야말로 이를 진지하게 다루는 일의 일부입니다. 이 서비스가 무엇을 관찰할 수 있고 무엇은 관찰할 수 없는지에 대한 전체 그림은 CardanoWall이 볼 수 있는 것에서 확인하십시오.

securitybrowser-securityidentity