ERC-2335 BLS12-381 키스토어 (BLS12-381 Keystore)

Review · 계정·지갑 · 2019-09-30 작성

BLS12-381 개인키를 비밀번호로 암호화해 JSON 파일 하나로 저장하고 기기 사이에서 안전하게 주고받을 수 있게 하는 표준입니다.

왜 필요한가

이더리움에서는 사용자가 자기 열쇠(개인키)를 직접 보관해야 하므로, 키를 안전하게 저장하고 옮기는 방법이 사용자 경험의 핵심입니다. 기존에는 웹3 시크릿 스토리지(Web3 Secret Storage)라는 키스토어 형식이 이 역할을 맡았지만 두 가지 문제가 있습니다. 첫째, 검증값 계산에 케착256(Keccak256) 해시를 씁니다. BLS 서명과 키는 여러 체인이 함께 쓰는 표준이라 특정 체인에 치우치지 않아야 하는데, 케착은 이더리움 색이 짙은 선택이라 중립적이지 않습니다. 둘째, 기존 형식은 필요할 때마다 기능을 덧붙이며 자란 결과물이라 구조적인 추상화가 없어 암호 구성 요소를 바꾸거나 단순화하기 어렵습니다. 이 표준은 BLS12-381 키를 위해 체인 중립적인 해시를 쓰고 각 암호 단계를 모듈로 추상화한 새 키스토어 형식을 정의합니다.

심층 설명

모듈 추상화

키스토어의 암호 구성 요소는 모두 모듈이라는 같은 틀로 표현합니다. 모듈은 어떤 암호 구성을 쓰는지 가리키는 function, 그 함수에 필요한 파라미터인 params, 함수의 주 입력인 message 세 필드로 이루어집니다. crypto 필드 아래에 kdf, checksum, cipher 세 모듈이 들어가며 각각 복호화 키 유도, 비밀번호 검증, 비밀 복호화를 담당합니다. 덕분에 구성 요소를 바꿔야 할 때 나머지 명세에 영향을 주지 않고 해당 모듈만 교체할 수 있습니다. Rationale에서는 KDF, 체크섬, 암호를 같은 것의 인스턴스로 다룰 수 있게 해 최소한의 노력으로 대체할 수 있다고 설명합니다.

비밀번호 처리 규칙

비밀번호는 임의의 유니코드 문자열입니다. 먼저 NFKD 표현으로 변환하고 제어 문자를 제거한 뒤 UTF-8로 인코딩합니다. 제거 대상은 C0 제어 코드(0x00~0x1F), C1 제어 코드(0x80~0x9F), 그리고 Delete 문자(0x7F)입니다. 공백(0x20)은 유사 제어 문자지만 비밀번호에서 유효한 문자로 인정합니다. 테스트 벡터에서는 수학용 특수 글꼴로 쓴 비밀번호가 NFKD 정규화를 거쳐 일반 라틴 문자 기반의 바이트열로 인코딩되는 예를 보여 줍니다.

복호화 키 유도(kdf 모듈)

복호화 키는 비밀번호에서 유도되는 중간 키로, 비밀번호 검증과 최종 비밀 복호화 양쪽에 쓰입니다. kdf 모듈의 function과 params에 따라 유도하며 두 가지 KDF를 정의합니다. PBKDF2-SHA-256은 function이 "pbkdf2"이고 params로 c, dklen, prf("hmac-sha256"), salt를 받습니다(RFC 2898). scrypt는 function이 "scrypt"이고 params로 dklen, n, p, r, salt를 받습니다(RFC 7914). 두 경우 모두 message는 비어 있습니다.

비밀번호 검증(checksum 모듈)

비밀번호가 맞는지는 checksum.message, cipher.message, kdf를 함께 써서 확인합니다. 절차는 복호화 키의 두 번째 16바이트 조각(decryption_key[16:32])을 떼어 내고 그 뒤에 cipher.message를 이어 붙인 뒤 SHA256 해시를 구해 checksum.message와 비교하는 것입니다. 같으면 비밀번호가 유효합니다. 체크섬 해시 함수로는 SHA-256(function "sha256")만 정의되어 있으며 params와 message 입력은 비어 있습니다. 기존 표준의 케착256 대신 SHA-256을 쓴 것이 이 표준의 중요한 차이입니다.

비밀 복호화(cipher 모듈)

비밀은 cipher.function으로 복호화 키를 써서 암호화되어 있으므로, 풀 때도 복호화 키와 cipher.function, cipher.params를 사용합니다. 복호화 키가 암호 알고리즘이 요구하는 키 길이보다 길면 올바른 비트 수로 잘라 씁니다. 정의된 암호는 AES-128 카운터 모드(function "aes-128-ctr", RFC 3686) 하나이며 params로 iv를 받습니다. aes-128-ctr의 경우 복호화 키의 첫 16바이트만 AES 키로 사용합니다.

메타데이터 필드와 버전

description은 키스토어의 용도를 설명하는 선택 필드로, 구분에 도움이 되지만 반드시 고유하지는 않습니다. pubkey는 보관된 개인키에 대응하는 공개키로, 비밀번호 입력 없이 공개키를 얻을 수 있게 해 사용자 경험과 보안을 높이며 비밀이 개인키라면 필수입니다. path는 ERC-2334가 정의하는 키 트리 상의 위치 문자열로, 경로를 모르거나 무관하면 빈 문자열 ""을 씁니다. uuid는 RFC 4122에 따라 무작위 생성한 UUID로 특정 키 집합이나 계정을 가리키는 128비트 식별자입니다. version은 4로 고정하며 기존 이더리움 키스토어 표준과의 충돌을 막기 위한 값입니다. JSON 스키마상 필수 필드는 crypto, path, uuid, version입니다.

기존 키스토어와의 호환성

이 명세는 케착256 체크섬을 지원하지 않으므로 기존 이더리움 웹3 시크릿 스토리지 정의와 하위 호환되지 않습니다. 체크섬 모듈 구조상 케착 체크섬을 담는 것 자체는 가능하지만 그러면 다른 프로젝트들에 대해 중립적이라는 이 표준의 목적이 무너지므로 포함하지 않습니다. 또한 이 제안은 ERC-2333(BLS 키 생성)과 ERC-2334(키 경로)를 전제로 합니다.

제안 상태

이 제안은 아직 Review 상태입니다. 검토 과정에서 내용이 바뀔 수 있는 단계이므로, 구현할 때는 원문의 최신 버전을 확인하는 것이 좋습니다.

ERC 원문 · ← ERCs