Private Key 관리하기

Posted on January 4, 2021 by 주형

블록체인에서 비밀키는 유일하고 대체 불가능한 신분증입니다. 잃어버리면 다시는 재발급받을 수 없고, 묶여있던 재화를 모두 잃어버립니다. 비밀키는 어떻게 해야 잘 괸리할까요?

첫 번째는 백업입니다. 인터넷과 연결되지 않은 매체에 저장하길 추천합니다. USB 기반의 하드웨어 월렛도 좋습니다. QR코드로 변환해서 프린트해놓는 것도 좋고, Mnemonic 키를 일기장에 적어놓는 것도 좋습니다.

이렇게 백업한 키를 사용할 때는 역시 인터넷이 연결안 된 컴퓨터에서 트랜잭션을 서명하기 위해서만 잠시 사용하고 다시 지우는 게 좋습니다.

귀찮아서, 혹은 내가 비트코인이나 이더리움을 얼마 가지지 않고 있다면 자주 쓰는 컴퓨터에 저장해도 괜찮습니다. 단 이 때는 비밀키를 암호화해야 합니다. 이더리움 지갑들은 키를 생성할 때 비밀번호를 받아서 키를 암호화해서 저장합니다. 지갑에서 비밀키를 내보낼 때도 일반적으로 비밀번호를 받아서 암호화해서 저장합니다. 비밀번호는 암호화된 비밀키와 다른 매체에 저장해야 안전합니다.


어플리케이션에서 사용하는 비밀키는 어떻게 관리할까요. 비트코인, 이더리움과 연동되어 트랜잭션을 생성하는 프로그램은 평문으로된 비밀키 값을 얻을 수 있어야 합니다. 일반적으로 파일 시스템에 비밀키를 저장합니다. 적어도 키 값을 저장한 파일의 소유권을 잘 지정하고, 서버 자체가 해킹당하지 않도록 방화벽과 계정을 잘 관리해야 합니다.

트랜잭션 서명만 하는 별도의 서버를 만들면 더 안전합니다. 해당 서버는 서명을 요청하는 서비스만 접근할 수 있게 방화벽을 잘 설정해두어야 합니다. 서명할 때에도 트랜잭션의 내용을 확인하고 특정 규칙에 맞는 트랜잭션만 서명하도록 하면 더 좋습니다. 하루에 출금할 수 있는 금액의 제한을 건다거나 특정 계좌로만 보낼 수 있게 만들 수 있습니다.


키를 여러개 나누는 것도 보안의 이점이 있습니다. 비트코인이나 이더리움이나 멀티시그니쳐지갑을 쓸 수 있습니다. 멀티시그니쳐지갑은 n개의 키 중 m개의 키로 만든 서명이 있을 때만 비트코인이나 이더리움을 송금하게 만들 수 있습니다. 여러 사람이 멀티시그니쳐지갑의 키를 하나씩 가지는 게 기본 사용법입니다. 키를 한 사람이 가지되 각각의 키의 백업 방식을 다르게 저장하는 것도 응용법입니다. 3개의 키중 2개의 서명으로 비트코인을 보낼 수 있는 멀티시그니쳐지갑이 있으면, 키 하나를 구글 드라이브에, 하나를 1password에, 남은 하나를 하드웨어지갑에 저장할 수 있습이다. 이렇게하면 1개를 해킹당해도 안전합니다.

Shamir Secret Sharing을 통해서 n개의 키 분할 중 m개의 키를 모으면 원본 키가 만들어지게 할 수 있습니다. Shamir Secret Sharing과 멀티시그니쳐지갑은 큰 차이점이 있습니다. Shamir Secret Sharing은 하나의 키를 여러개로 나눈 뒤 나중에 다시 헙쳐서 원본 키를 만드는 방식입니다. 멀티시그니쳐지갑은 애초에 서로 다른 키가 여러개 있습니다. 각각의 키로 서명을 한 뒤 서명의 갯수를 확인하는 방법입니다.

다만 Shamir Secret Sharing은 쓸 때 신중해야 합니다. Shamir Secret Sharing은 한 번 키를 모으면 원본키가 복원됩니다. 1회용이라 생각하고 사용해야 합니다. Shamir Secret Sharing에서 여러 키를 만들 때 가장 간단한 방법은 원본 키를 먼저 만들고 이를 나누는 것입니다. DKG와 같은 복잡한 단계를 거치면 아무도 원본키를 모르는 상태로 키를 나눌 수 있습니다.


비밀키를 사용하는 어플리케이션을 만들 때에도 보안에 신경쓸 점들이 있습니다. 가능한한 메모리에 비밀키가 있는 시간을 줄이는 것이 좋습니다. 많은 crypto 라이브러리들이 메모리를 청소하는 함수들을 제공해줍니다. 잊지 말고 잘 호출해 주어야 합니다.

비밀키는 평범한 String이나 buffer를 쓰기보다, 특별한 타입을 선언해서 써야 합니다. 실수로 serialize되거나 ToString 같은 함수로 내부 정보가 출력되지 않게 만들어야 합니다. 직접 serialize를 하지 않더라도, 프로그램이 예상치 못하게 종료될 때 콜스택에 있는 값들을 출력해줄 때가 있습니다. 자신이 사용하는 언어가 언제 값을 출력하고, 어떻게 해야 그것을 막을 수 있는지 알아야 합니다.


당연하지만, 서명을 하려면 메모리에 암호화가 되지 않은 비밀키 정보가 있어야 합니다. Intel SGX와 같은 TEE(Trusted Execution Environment)를 사용하면, 서명 알고리즘이 동작하고 있는 와중에도 메모리에 있는 비밀키가 암호화되어 있도록 만들 수 있습니다.