Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
title: "간단 직렬화"
description: "이더리움의 SSZ 형식에 대한 설명입니다."
lang: ko
sidebarDepth: 2
---

\*\*간단 직렬화(SSZ)\*\*는 비콘 체인에서 사용되는 직렬화 방법입니다. 피어 검색 프로토콜을 제외하고 합의 레이어 전반의 실행 레이어에서 사용되는 RLP 직렬화를 대체합니다. RLP 직렬화에 대해 자세히 알아보려면 [재귀 길이 접두사(RLP)](/developers/docs/data-structures-and-encoding/rlp/)를 참조하세요. SSZ는 결정론적이며 효율적으로 머클화되도록 설계되었습니다. SSZ는 직렬화 방식과 직렬화된 데이터 구조와 효율적으로 작동하도록 설계된 머클화 방식의 두 가지 구성 요소를 갖는 것으로 생각할 수 있습니다.

## SSZ는 어떻게 작동하나요? {#how-does-ssz-work}

### 직렬화 {#serialization}

SSZ는 자체 서술적이지 않은 직렬화 방식이며, 사전에 알려져야 하는 스키마에 의존합니다. SSZ 직렬화의 목표는 임의의 복잡성을 가진 객체를 바이트 문자열로 표현하는 것입니다. 이는 "기본 유형"에 대한 매우 간단한 프로세스입니다. 요소는 단순히 16진수 바이트로 변환됩니다. 기본 유형은 다음과 같습니다.

- 부호 없는 정수
- 불리언

복잡한 "복합" 유형의 경우, 복합 유형에 유형이나 크기가 다르거나 둘 다 다른 여러 요소가 포함되어 있으므로 직렬화가 더 복잡합니다. 이러한 객체가 모두 고정된 길이(즉, 요소의 크기가 실제 값에 관계없이 항상 일정함)를 갖는 경우 직렬화는 단순히 복합 유형의 각 요소를 리틀엔디언 바이트 문자열로 순서대로 변환하는 것입니다. 이러한 바이트 문자열은 함께 결합됩니다. 직렬화된 객체는 역직렬화된 객체에 나타나는 것과 동일한 순서로 고정 길이 요소의 바이트 목록 표현을 가집니다.

가변 길이 유형의 경우, 실제 데이터는 직렬화된 객체의 해당 요소 위치에 있는 "오프셋" 값으로 대체됩니다. 실제 데이터는 직렬화된 객체의 끝에 있는 힙에 추가됩니다. 오프셋 값은 힙에 있는 실제 데이터의 시작 인덱스로, 관련 바이트에 대한 포인터 역할을 합니다.

아래 예는 고정 및 가변 길이 요소를 모두 포함하는 컨테이너에 대한 오프셋 작동 방식을 보여줍니다.

```Rust

struct Dummy {

number1: u64,
number2: u64,
vector: Vec<u8>,
number3: u64
}

dummy = Dummy{

number1: 37,
number2: 55,
vector: vec![1,2,3,4],
number3: 22,
}

serialized = ssz.serialize(dummy)

```

`serialized`는 다음과 같은 구조를 가집니다(여기서는 4비트로만 패딩되었지만 실제로는 32비트로 패딩되었으며, 명확성을 위해 `int` 표현을 유지합니다):

```
[37, 0, 0, 0, 55, 0, 0, 0, 16, 0, 0, 0, 22, 0, 0, 0, 1, 2, 3, 4]
------------ ----------- ----------- ----------- ----------
| | | | |
number1 number2 vector의 number3 vector의
오프셋 값

```

명확성을 위해 여러 줄로 나눴습니다:

```
[
37, 0, 0, 0, # `number1`의 리틀엔디언 인코딩.
55, 0, 0, 0, # `number2`의 리틀엔디언 인코딩.
16, 0, 0, 0, # `vector` 값의 시작 위치를 나타내는 "오프셋"(리틀엔디언 16).
22, 0, 0, 0, # `number3`의 리틀엔디언 인코딩.
1, 2, 3, 4, # `vector`의 실제 값.
]
```

이것은 여전히 단순화된 것입니다. 위의 도식에 있는 정수와 0은 실제로는 다음과 같이 바이트 목록으로 저장됩니다.

```
[
10100101000000000000000000000000 # `number1`의 리틀엔디언 인코딩
10110111000000000000000000000000 # `number2`의 리틀엔디언 인코딩.
10010000000000000000000000000000 # `vector` 값의 시작 위치를 나타내는 "오프셋"(리틀엔디언 16).
10010110000000000000000000000000 # `number3`의 리틀엔디언 인코딩.
10000001100000101000001110000100 # `bytes` 필드의 실제 값.
]
```

따라서 가변 길이 유형의 실제 값은 직렬화된 객체의 끝에 있는 힙에 저장되며, 오프셋은 정렬된 필드 목록의 올바른 위치에 저장됩니다.

`BitList` 유형과 같이 직렬화 중에 길이 상한을 추가하고 역직렬화 중에 제거해야 하는 특정 처리가 필요한 몇 가지 특수한 경우도 있습니다. 전체 세부 정보는 [SSZ 사양](https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md)에서 확인할 수 있습니다.

### 역직렬화 {#deserialization}

이 객체를 역직렬화하려면 <b>스키마</b>가 필요합니다. 스키마는 직렬화된 데이터의 정확한 레이아웃을 정의하여 각 특정 요소를 바이트 블롭에서 올바른 유형, 값, 크기 및 위치를 갖는 의미 있는 객체로 역직렬화할 수 있도록 합니다. 어떤 값이 실제 값이고 어떤 값이 오프셋인지를 역직렬화 프로그램에 알려주는 것이 바로 스키마입니다. 모든 필드 이름은 객체가 직렬화될 때 사라지지만, 스키마에 따라 역직렬화될 때 다시 인스턴스화됩니다.

이에 대한 대화형 설명은 [ssz.dev](https://www.ssz.dev/overview)를 참조하세요.

## 머클화 {#merkleization}

그런 다음 이 SSZ 직렬화된 객체를 머클화할 수 있습니다. 즉, 동일한 데이터의 머클 트리 표현으로 변환할 수 있습니다. 먼저, 직렬화된 객체에서 32바이트 청크의 수를 결정합니다. 이것이 트리의 "리프"입니다. 리프를 함께 해싱하여 최종적으로 단일 해시 트리 루트를 생성할 수 있도록 총 리프 수는 2의 거듭제곱이어야 합니다. 자연스럽게 그렇지 않은 경우, 32바이트의 0을 포함하는 추가 리프가 추가됩니다. 도식적으로:

```
해시 트리 루트
/ \
/ \
/ \
/ \
리프 1과 2의 해시 리프 3과 4의 해시
/ \ / \
/ \ / \
/ \ / \
리프1 리프2 리프3 리프4
```

위의 예에서와 같이 트리의 리프가 자연스럽게 고르게 분포되지 않는 경우도 있습니다. 예를 들어, 리프 4는 머클 트리에 추가적인 "깊이"를 추가해야 하는 여러 요소를 가진 컨테이너일 수 있으며, 이로 인해 불균일한 트리가 생성됩니다.

이러한 트리 요소를 리프 X, 노드 X 등으로 지칭하는 대신, 루트 = 1에서 시작하여 각 레벨을 따라 왼쪽에서 오른쪽으로 계산하는 일반화된 인덱스를 부여할 수 있습니다. 이것이 위에서 설명한 일반화된 인덱스입니다. 직렬화된 목록의 각 요소는 `2**depth + idx`와 같은 일반화된 인덱스를 가집니다. 여기서 idx는 직렬화된 객체에서 0부터 시작하는 위치이고, 깊이는 머클 트리의 레벨 수이며, 요소(리프) 수의 밑이 2인 로그로 결정될 수 있습니다.

## 일반화된 인덱스 {#generalized-indices}

일반화된 인덱스는 이진 머클 트리의 노드를 나타내는 정수이며, 각 노드는 `2 ** depth + 행의 인덱스`라는 일반화된 인덱스를 가집니다.

```
1 --깊이 = 0 2**0 + 0 = 1
2 3 --깊이 = 1 2**1 + 0 = 2, 2**1+1 = 3
4 5 6 7 --깊이 = 2 2**2 + 0 = 4, 2**2 + 1 = 5...

```

이 표현은 머클 트리의 각 데이터 조각에 대한 노드 인덱스를 산출합니다.

## 다중 증명 {#multiproofs}

특정 요소를 나타내는 일반화된 인덱스 목록을 제공하면 해시 트리 루트와 비교하여 이를 확인할 수 있습니다. 이 루트는 우리가 수용한 현실 버전입니다. 제공된 모든 데이터는 머클 트리의 올바른 위치(일반화된 인덱스에 의해 결정됨)에 삽입하고 루트가 일정하게 유지되는지 관찰함으로써 그 현실에 대해 검증될 수 있습니다. 사양에는 특정 일반화된 인덱스 세트의 내용을 확인하는 데 필요한 최소 노드 세트를 계산하는 방법을 보여주는 함수가 [여기](https://github.com/ethereum/consensus-specs/blob/dev/ssz/merkle-proofs.md#merkle-multiproofs)에 있습니다.

예를 들어, 아래 트리에서 인덱스 9의 데이터를 확인하려면 인덱스 8, 9, 5, 3, 1에 있는 데이터의 해시가 필요합니다.
(8,9)의 해시는 해시 (4)와 같아야 하며, 이는 5와 해싱되어 2를 생성하고, 이는 3과 해싱되어 트리 루트 1을 생성합니다. 9에 대해 잘못된 데이터가 제공되면 루트가 변경됩니다. 우리는 이를 감지하고 브랜치 확인에 실패할 것입니다.

```
* = 증명을 생성하는 데 필요한 데이터

1*
2 3*
4 5* 6 7
8* 9* 10 11 12 13 14 15

```

## 더 읽어보기 {#further-reading}

- [이더리움 업그레이드: SSZ](https://eth2book.info/altair/part2/building_blocks/ssz)
- [이더리움 업그레이드: 머클화](https://eth2book.info/altair/part2/building_blocks/merkleization)
- [SSZ 구현](https://github.com/ethereum/consensus-specs/issues/2138)
- [SSZ 계산기](https://simpleserialize.com/)
- [SSZ.dev](https://www.ssz.dev/)
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
---
title: "Web3 비밀 저장소 정의"
description: "웹3 비밀 저장 공간에 대한 공식적인 정의"
lang: ko
sidebarDepth: 2
---

앱이 이더리움에서 작동하도록 하려면 web3.js 라이브러리에서 제공하는 웹3 객체를 사용할 수 있습니다. 내부적으로 RPC 호출을 통해 로컬 노드와 통신합니다. [web3](https://github.com/ethereum/web3.js/)는 RPC 레이어를 노출하는 모든 이더리움 노드와 함께 작동합니다.

`web3`는 `eth` 객체(web3.eth)를 포함합니다.

```js
var fs = require("fs")
var recognizer = require("ethereum-keyfile-recognizer")

fs.readFile("keyfile.json", (err, data) => {
var json = JSON.parse(data)
var result = recognizer(json)
})

/** result
* [ 'web3', 3 ] 웹3(v3) 키 파일
* [ 'ethersale', undefined ] Ethersale 키 파일
* null 잘못된 키 파일
*/
```

이 문서는 웹3 비밀 저장 공간 정의의 **버전 3**에 대한 내용입니다.

## 정의 {#definition}

파일의 실제 인코딩 및 디코딩은 버전 1과 거의 동일하지만, 암호화 알고리즘이 더 이상 AES-128-CBC로 고정되지 않는다는 점이 다릅니다(현재는 AES-128-CTR이 최소 요구 사항임). 대부분의 의미/알고리즘은 버전 1과 유사하지만 `mac`은 예외입니다. `mac`은 파생된 키의 왼쪽에서 두 번째 16바이트와 전체 `ciphertext`를 연결한 것의 SHA3(keccak-256)으로 지정됩니다.

비밀 키 파일은 `~/.web3/keystore`(유닉스 계열 시스템의 경우) 및 `~/AppData/Web3/keystore`(윈도우의 경우)에 직접 저장됩니다. 이름은 무엇이든 될 수 있지만, `<uuid>.json`이 좋은 규칙입니다. 여기서 `<uuid>`는 비밀 키에 부여된 128비트 UUID(비밀 키 주소에 대한 개인정보 보호 프록시)입니다.

이러한 모든 파일에는 연결된 비밀번호가 있습니다. 주어진 `.json` 파일의 비밀 키를 파생시키려면 먼저 파일의 암호화 키를 파생시켜야 합니다. 이 작업은 파일의 비밀번호를 가져와 `kdf` 키에 설명된 대로 키 파생 함수를 통해 전달하여 수행됩니다. KDF 함수에 대한 KDF 종속 정적 및 동적 파라미터는 `kdfparams` 키에 설명되어 있습니다.

최소 준수 구현은 모두 PBKDF2를 지원해야 하며, 다음과 같이 표시됩니다.

- `kdf`: `pbkdf2`

PBKDF2의 경우, kdfparams는 다음을 포함합니다.

- `prf`: `hmac-sha256`이어야 합니다(향후 확장될 수 있음).
- `c`: 반복 횟수,
- `salt`: PBKDF에 전달된 솔트,
- `dklen`: 파생된 키의 길이. 32 이상이어야 합니다.

파일의 키가 파생되면 MAC 파생을 통해 확인해야 합니다. MAC은 파생된 키의 왼쪽에서 두 번째 16바이트와 `ciphertext` 키의 내용을 연결하여 형성된 바이트 배열의 SHA3(keccak-256) 해시로 계산되어야 합니다. 즉,

```js
KECCAK(DK[16..31] ++ <ciphertext>)
```

(여기서 `++`는 연결 연산자입니다)

이 값은 `mac` 키의 내용과 비교해야 합니다. 만약 값이 다르면 다른 비밀번호를 요청하거나 작업을 취소해야 합니다.

파일의 키가 확인된 후, `cipher` 키로 지정되고 `cipherparams` 키를 통해 매개변수화된 대칭 암호화 알고리즘을 사용하여 암호문(`ciphertext` 키)을 복호화할 수 있습니다. 파생된 키 크기와 알고리즘의 키 크기가 일치하지 않는 경우, 파생된 키의 0으로 채워진 가장 오른쪽 바이트가 알고리즘의 키로 사용되어야 합니다.

모든 최소 준수 구현은 AES-128-CTR 알고리즘을 지원해야 하며, 다음과 같이 표시됩니다.

- `cipher: aes-128-ctr`

이 암호는 cipherparams 키에 대한 키로 지정된 다음 매개변수를 사용합니다.

- `iv`: 암호에 대한 128비트 초기화 벡터.

암호의 키는 파생된 키의 가장 왼쪽 16바이트입니다(예: `DK[0..15]`)

비밀 키의 생성/암호화는 기본적으로 이러한 지침의 역순이어야 합니다. `uuid`, `salt` 및 `iv`가 실제로 무작위인지 확인하십시오.

버전의 "하드" 식별자 역할을 해야 하는 `version` 필드 외에도, 구현은 형식에 대한 더 작고 호환성을 깨뜨리지 않는 변경 사항을 추적하기 위해 `minorversion`을 사용할 수도 있습니다.

## 테스트 벡터 {#test-vectors}

세부 정보:

- `주소`: `008aeeda4d805471df9b2a5b0f38a0c3bcba786b`
- `ICAP`: `XE542A5PZHH8PYIZUBEJEO0MFWRAPPIL67`
- `UUID`: `3198bc9c-6672-5ab3-d9954942343ae5b6`
- `비밀번호`: `testpassword`
- `비밀`: `7a28b5ba57c53603b0b07b56bba752f7784bf506fa95edc395f5cf6c7514fe9d`

### PBKDF2-SHA-256 {#PBKDF2-SHA-256}

`AES-128-CTR` 및 `PBKDF2-SHA-256`을 사용한 테스트 벡터:

`~/.web3/keystore/3198bc9c-6672-5ab3-d9954942343ae5b6.json`의 파일 내용:

```json
{
"crypto": {
"cipher": "aes-128-ctr",
"cipherparams": {
"iv": "6087dab2f9fdbbfaddc31a909735c1e6"
},
"ciphertext": "5318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46",
"kdf": "pbkdf2",
"kdfparams": {
"c": 262144,
"dklen": 32,
"prf": "hmac-sha256",
"salt": "ae3cd4e7013836a3df6bd7241b12db061dbe2c6785853cce422d148a624ce0bd"
},
"mac": "517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2"
},
"id": "3198bc9c-6672-5ab3-d995-4942343ae5b6",
"version": 3
}
```

**중간값**:

`파생된 키`: `f06d69cdc7da0faffb1008270bca38f5e31891a3a773950e6d0fea48a7188551`
`MAC 본문`: `e31891a3a773950e6d0fea48a71885515318b4d5bcd28de64ee5559e671353e16f075ecae9f99c7a79a38af5f869aa46`
`MAC`: `517ead924a9d0dc3124507e3393d175ce3ff7c1e96529c6c555ce9e51205e9b2`
`암호 키`: `f06d69cdc7da0faffb1008270bca38f5`

### Scrypt {#scrypt}

AES-128-CTR 및 Scrypt를 사용한 테스트 벡터:

```json
{
"crypto": {
"cipher": "aes-128-ctr",
"cipherparams": {
"iv": "740770fce12ce862af21264dab25f1da"
},
"ciphertext": "dd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2",
"kdf": "scrypt",
"kdfparams": {
"dklen": 32,
"n": 262144,
"p": 1,
"r": 8,
"salt": "25710c2ccd7c610b24d068af83b959b7a0e5f40641f0c82daeb1345766191034"
},
"mac": "337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c"
},
"id": "3198bc9c-6672-5ab3-d995-4942343ae5b6",
"version": 3
}
```

**중간값**:

`파생된 키`: `7446f59ecc301d2d79bc3302650d8a5cedc185ccbb4bf3ca1ebd2c163eaa6c2d`
`MAC 본문`: `edc185ccbb4bf3ca1ebd2c163eaa6c2ddd8a1132cf57db67c038c6763afe2cbe6ea1949a86abc5843f8ca656ebbb1ea2`
`MAC`: `337aeb86505d2d0bb620effe57f18381377d67d76dac1090626aa5cd20886a7c`
`암호 키`: `7446f59ecc301d2d79bc3302650d8a5c`

## 버전 1의 변경 사항 {#alterations-from-v2}

이 버전은 [여기](https://github.com/ethereum/homestead-guide/blob/master/old-docs-for-reference/go-ethereum-wiki.rst/Passphrase-protected-key-store-spec.rst)에 게시된 버전 1의 몇 가지 불일치를 수정합니다. 간단히 말해 다음과 같습니다.

- 대소문자 사용이 부적절하고 일관성이 없습니다(scrypt는 소문자, Kdf는 혼합 대/소문자, MAC은 대문자).
- 주소는 불필요하며 개인 정보를 침해합니다.
- `Salt`는 본질적으로 키 파생 함수의 매개변수이므로 일반적인 암호화가 아닌 해당 함수와 연결되어야 합니다.
- _SaltLen_은 불필요합니다(Salt에서 파생하면 됨).
- 키 파생 함수는 주어지지만, 암호화 알고리즘은 하드코딩되어 있습니다.
- `Version`은 본질적으로 숫자이지만 문자열입니다(문자열로 구조화된 버전 관리가 가능하지만, 거의 변경되지 않는 구성 파일 형식의 범위를 벗어난 것으로 간주될 수 있습니다).
- `KDF`와 `cipher`는 개념적으로 형제 개념이지만 다르게 구성되어 있습니다.
- `MAC`은 공백에 영향을 받지 않는 데이터 조각을 통해 계산됩니다(!).

이전에 링크된 페이지의 예시와 기능적으로 동일한 다음 파일을 제공하기 위해 형식이 변경되었습니다.

```json
{
"crypto": {
"cipher": "aes-128-cbc",
"ciphertext": "07533e172414bfa50e99dba4a0ce603f654ebfa1ff46277c3e0c577fdc87f6bb4e4fe16c5a94ce6ce14cfa069821ef9b",
"cipherparams": {
"iv": "16d67ba0ce5a339ff2f07951253e6ba8"
},
"kdf": "scrypt",
"kdfparams": {
"dklen": 32,
"n": 262144,
"p": 1,
"r": 8,
"salt": "06870e5e6a24e183a5c807bd1c43afd86d573f7db303ff4853d135cd0fd3fe91"
},
"mac": "8ccded24da2e99a11d48cda146f9cc8213eb423e2ea0d8427f41c3be414424dd",
"version": 1
},
"id": "0498f19a-59db-4d54-ac95-33901b4f1870",
"version": 2
}
```

## 버전 2의 변경 사항 {#alterations-from-v2}

버전 2는 여러 버그가 있는 초기 C++ 구현이었습니다. 모든 필수 요소는 그대로 유지됩니다.
Loading
Loading