K = k * G
곱셈은 G를 k번 더하는 연산으로 생각할 것...
이더리움에서는 16진수 문자 130개(65바이트)의 sirialization으로 표시되는 공개키를 볼 수 있다.
0X00: 무한대를 가리킨다. 바이트 수는 1
0x04: 압축되지 않은 지점. 바이트 수는 65
0x02: 짝수 y의 압축된 점. 바이트 수는 33
0x03: 홀수 y의 압축된 점. 바이트 수는 33
serialization은 공개키의 x와 y 좌표를 연결한다.
04 + x 좌표(32 bytes / 64(16진수)) + y 좌표(32 bytes / 64(16진수))
이더리움 공개키를 주소로 변환하는 작업에서 해시 함수가 기여하는 바가 있고, 디지털 지문을 만드는 데에 사용할 수 있다.
암호 해시 함수는 임의 크기의 데이터를 고정 크기의 비트 열로 매핑하는 단방향 해시 함수이다.
즉 결과값 해시를 알고 있을 때 입력 데이터를 다시 작성하는 것이 계산적으로 불가능함을 의미한다.
vs SHA-3
NIST에서 수정한 SHA-3의 경우 미국 국가안보국의 영향을 받아 난수 생성기에 백도어를 배치했다는 것이 내부 고발로 드러나게 되어 Keccak 알고리즘이 쓰이고 있다.
국제 은행 계좌 번호(IBAN)화 부분적으로 호환되는 인코딩 방식.
IBAN과 호환 가능한 '직접' 인코딩, 기본, 간접 인코딩 등의 구조가 있다.
ICAP와 ENS의 늦은 개발 때문에, EIP-55로 다른 표준이 제안되었다.
EIP-55는 16진수 주소 중 일부를 대문자화하여 구버전과 호환되는 이더리움 주소 체크섬을 제공한다.
이더리움 주소는 대소문자 구분없이 사용할 수 있다는 점을 이용한 아이디어이다.
일반 이더리움 주소
0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
EIP-55 적용한 주소
0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
두 주소의 차이점은 중간 중간 대문자로 변경된 영문자가 보인다는 것이다.
해당 16진수의 해시값이 0x8이상인 경우에 알파벳을 대문자로 만든다.
지갑: 사용자의 키를 보관하고 관리하기 위해 사용되는 시스템.
지갑을 설계할 때 중요한 고려 사항은 편의성과 프라이버시 사이의 균형을 맞추는 것.
많이 하는 오해!!!
보통 이더리움 지갑이 이더 혹은 토큰을 보유한다고 생각하지만 지갑은 키만 보유하고 있다.
이더 혹은 토큰은 블록체인에 기록된다.
기존 은행은 은행만이 계좌에 있는 돈을 볼 수 있고 트랜잭션 진행을 위해 자금을 옮기고 싶다면 은행만 납득시키면 된다.
그러나 블록페인 플랫폼에서는 모든 사람이 계좌의 잔액을 볼 수 있고 주인을 알지 못하지만 트랜잭션 진행을 위해 자금을 옮기고 싶어한다는 것을 모든 사람에게 납득시켜야 한다.
: 무작위적으로 키를 추출.
모든 트랜잭션마다 새로운 주소를 사용하게 됨...
--> 편의성 면에서 매우 불편하다
그럼에도 불구하고 많은 이더리움 클라이언트는 보안 강화를 위해 암호문으로 암호화된 단일 개인키가 들어 있는 JSON 인코딩 파일인 keystore 파일을 사용한다.
{
"version": 3,
"id": "4c07993f-ded2-405a-b83d-3b627eebe5cd",
"address": "e449efddf8c9b174bbd40a0e0e1902d6eee72068",
"crypto": {
"cipher": "aes-128-ctr",
"cipherparams": {
"iv": "7d416faf14c88bb124486f6cd851fa88"
},
"ciphertext":"e99f6d0e37f33124ee3020fad01363d9d7500efce
913aede8a8119229b7a5f2e",
"kdf": "scrypt",
"kdfparams": {
"dklen": 32,
"salt": "c47f395c9031233453168f01b5a9999a06ec97c829
a395ecd16e1ad37102ec7f",
"n": 8192,
"r": 8,
"p": 1
},
"mac": "82078437ee94331c69125eef4001ff4b78b481e909a6
2a9ac25aa916237b70be"
}
}
: 모든 키가 시드라는 단일 마스터 키로부터 파생된다.
모든 파생된 키는 시드로 복구할 수 있다.
HD(hierarchical deterministic) 지갑은 트리 구조로 파생된 키를 가지고 있다.
장점
개인키를 인코딩하려면 단어 시퀀스를 사용하는 방법이 있다.
16진수 시퀀스를 기록할 때는 오류가 발생할 확률이 매우 높으나 단어 목록은 오류 업시 고쳐 쓰고, 종이에 기록하고, 읽고, 안전하게 내보내고, 개인키들을 다른 지갑으로 가져오는 가장 쉬운 방법이다.
mnemonic code 단어는 시드로 사용되는 난수를 인코딩하는 단어 시퀀스이다.
brainwallet은 사용자가 고른 단어로 구성되지만, 니모닉 단어는 무작위로 생성된다.
1. 128~256비트의 무작위 암호화 시퀀스 S를 생성한다.
2. S를 SHA-256으로 해싱한 값을 32비트로 나눈 처음 길이를 체크섬으로 생성한다.
3. 무작위 시퀀스 S의 끝에 체크섬을 추가한다.
4. 시퀀스와 체크섬을 연결한 것을 11비트 단위로 나눈다.
5. 각각의 11비트 값을 사전에 정의된 2,048 단어 사전과 매핑한다.
6. 단어의 시퀀스로부터 순서를 유지하면서 니모닉 코드를 생성한다.
엔트로피는 키 스트레칭 함수 PBKDF2를 사용하여 더 긴 시드를 파생하는 데 사용된다.
이 함수에는 니모닉과 솔트라는 2가지 파라미터가 있다.
솔트의 목적은 무차별 대입 공격을 가능하게 하는 조회 테이블 생성을 어렵게 하는 것이다.
7. PBKDF2 키 스트레칭 함수의 첫 번째 파라미터는 6단계에서 생성된 니모닉이다.
8. PBKDF2 키 스트레칭 함수의 2 번째 파라미터는 salt이다. salt는 문자열 상수 "mnemonic"과 선택적으로 사용자가 지정한 암호문을 연결하여 구성한다.
9. PBKDF2는 최종 출력으로 512비트 값을 만드는 HMAC-SHA512 알고리즘으로, 2048 해시 라운드를 사용하여 니모닉과 솔트 파라미터를 확장하며, 이 결과로 나온 512비트 값이 시드이다.
키를 확장하는 것은 키 자체를 가져와서 특수 chain code를 추가하는 것.
키가 개인키이면 접두어 xprv로 구분되는 확장된 개인키가 되고,
확장된 공개키의 경우에는 xpub이라는 접두어로 구분된다.
확장된 부모 키는 적절한 연산을 사용하여 자식 키를 파생시킬 수 있다.
HD 지갑은 child 공개키를 파생하는 방법이 2가지가 있는데, 하나는 자식 개인키로부터, 다른 하나는 부모 공개키로부터 파생하는 방법이다.
위 방법은 xpub이 chain code를 포함하므로 하위 개인키가 알려져 있거나 유출되었을 경우에 모든 child 개인키가 노출될 위험이 있고, 부모 chain code 와 자식 개인키로부터 부모 개인키를 추론할 수 있다는 문제점이 있다.
위 문제에 대응하기 위해 HD 지갑은 강화 파생이라고 하는 대체 가능 파생 함수를 사용한다.
이 함수는 자식 chain code를 파생하기 위해 부모 공개키 대신 개인키를 사용한다. 이는 부모 공개키와 자식 chain code 간의 연결을 끊는다.
관리를 위해 인덱스 번호를 이용.
0x0 ~ 0x7FFFFFFF(0 ~ 2^31 - 1)은 일반 파생,
0x80000000 ~ 0xFFFFFFFF(2^31 ~ 2^32 - 1)까지는 강화 파생을 위해 사용.
m: 마스터 키에서 파생된 개인키
M: 마스터 키에서 파생된 공개키
ex) m/1/0: 두번째 자식의 1번째 개인키
m / purppose' / coin_type' / account' / change / address_index
change에서 HD 지갑에는 2개의 하위 트리가 존재하는데,하나는 입금 주소 작성용이고, 다른 하나는 잔액 주소 작성용이다. 이더리움은 비트코인에 있는 잔액 주소가 필요하지 않지만 BIP-44는 원래 비트코인을 위해 제작된 것이다.