비트코인 메르켈 루트 구성의 약점

이 기사는 기계로 번역되었습니다
원문 표시

저자: 수하스 다프투아르

출처: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/attachments/20190225/a27d8837/attachment-0001.pdf

원본 기사는 2019년 2월에 게재되었습니다.

요약

비트코인 블록 헤더에는 블록에 의해 확인된 일련의 거래에 대한 약속이 포함되어 있습니다. 이는 거래 ID(거래의 두 연속 SHA256 계산 해시 값)를 사용하여 머클 트리를 구성하는 것입니다. 블록 헤더의 트리 루트. 따라서 이를 사용하여 트리 루트에서 트랜잭션까지 Merkle 경로를 제공함으로써 특정 트랜잭션이 특정 블록에 의해 확인되었음을 비트코인 ​​라이트 클라이언트에게 증명할 수 있습니다. 그러나 Merkle 트리의 특수한 구성에는 비트코인 ​​코어의 합의 논리에 영향을 미치는 최소 2개의 블록 용해 취약점과 라이트 클라이언트(트랜잭션 유효하지 않은 트랜잭션이 블록에 나타난 것으로 "증명"될 수 있음)에 대한 공격을 포함하여 여러 가지 보안 약점이 있습니다. ) 두 개의 연속 SHA256 해시 작업의 충돌을 찾는 것보다 작업량이 훨씬 적습니다.

감사의 말

Sergio Lerner와 Peter Todd를 포함하여 많은 사람들이 비트코인 ​​개발자 메일링 리스트에 이 요약에 설명된 문제 중 일부를 보고했습니다. 이 요약은 저자가 Johnson Law 및 Greg Maxwell과 진행한 비공개 IRC 토론을 기반으로 합니다. 나는 3장에서 논의된 관찰 중 일부가 원래 Luke Dashjr로부터 나온 것이라고 믿습니다.

배경 1개

1.1 메르켈 뿌리의 구축

검토하자면, 비트코인에서 사용하는 Merkle 루트 구성은 각 트랜잭션에서 두 번의 연속 SHA256 작업(이중 SHA256)을 수행하여 [1] 트리의 리프로 해시 값 $H$를 얻는 것으로 시작됩니다. 연속된 리프의 각 쌍에 대해 리프를 연결하고 리프에 대해 두 번의 연속 SHA256 해시 작업을 수행하고 결과 해시 값을 리프 쌍의 부모노드 (Parent node) 로 사용합니다. 중요한 것은 트리의 특정 수준에 홀수 개의 노드가 있는 경우 마지막 요소가 먼저 복사되므로 부모노드 (Parent node) 요소 자체를 복사하고 서로 접합하는 해시 값이 된다는 것입니다. 예를 들어, 블록에 3개의 트랜잭션이 있는 경우 머클 트리는 다음과 같습니다.

머클-1

여기서 Node1은 H(H(Tx1)||H(Tx2)) 사용하여 계산되고, Node2는 H(H(Tx3)||H(Tx3)) 사용하여 계산됩니다. 마지막으로 Merkle 루트는 H(Node1||Node2) 사용하여 계산되며 이 Merkle 루트는 블록 헤더에 나타납니다.

블록에 트랜잭션이 하나만 있는 경우 Merkle 루트는 해당 트랜잭션의 해시가 됩니다. 모든 유효한 블록에는 최소한 하나의 거래가 포함되어야 합니다.

1.2 비트코인 ​​코어의 블록 유효성

Bitcoin Core의 합의 논리는 블록 유효성 검사를 여러 부분으로 나누고 이러한 모든 단계를 통해 블록의 유효성을 추적합니다. 예를 들어, 새로운 블록 헤더를 처리할 때(일반적으로 블록을 수신하기 전) 네트워크의 합의 규칙에 따라 블록 헤더의 유효성을 검사합니다. 나중에 블록이 도착하면 블록도 단계적으로 처리됩니다. 먼저 컨텍스트 없는 검사(다른 블록 및 블록 헤더에 의존하지 않음)를 실행한 다음 블록의 위치에 따라 검사합니다. 헤더 체인, 마지막으로 트랜잭션과 서명을 확인하고 해당 블록이 가장 많은 작업을 수행한 블록 헤더 체인에 속하는지 확인합니다.

저장된 각 블록 헤더에는 관련 블록이 완료한 확인 횟수를 추적하는 관련 캐시 값이 있습니다. 블록이 유효하지 않은 것으로 확인되면 비트코인 ​​코어는 블록의 유효하지 않은 상태를 영구적으로 저장하고 블록 및 후속 블록의 재처리를 방지합니다.

다음 장에서는 공격자가 이 최적화를 사용하여 네트워크를 분할하는 것을 방지하기 위해 유효하지 않은 블록을 영구적 태그 관련된 우려 사항에 대해 논의합니다.

2 거래 복사, CVE-2012-2459

이것은 Bitcoin Core 소스 코드에 작성되었습니다.

警告!如果你是为学习密码学以及/或者设计一种将要使用默克尔树的新系统,请记住,下面的默克尔树算法有一个跟交易id 重合相关的严重错误,最终会产生漏洞(CVE-2012-2456)。原因在于,如果某个时刻,在列表中的哈希值的数量是奇数,则最后一个哈希值会被复制,以计算下一层(这在默克尔树中是不常见的设计)。这导致交易的特定排序会产生相同的默克尔根。举个例子,这两棵树: AA / \ / \ BCBC / \ | / \ / \ DEFDEEF/ \ / \ / \ / \ / \ / \ / \1 2 3 4 5 6 1 2 3 4 5 6 5 6交易列表[1, 2, 3, 4, 5, 6] 跟[1, 2, 3, 4, 5, 6, 5, 6](5 和6 被重复了)会得出相同的哈希值A(因为(F) 和(F, F) 的哈希值都是C)。漏洞在于,你可以发送一个带有重复交易列表的区块,它跟原版区块有相同的默克尔根值、相同的区块哈希值,但却无法通过验证。然而,如果接收节点将这个区块标记为永久无效的,就不再能接收同一区块没有篡改过(因此可能是有效)的版本。我们通过检测这种情形来防止这种误伤:检测会在列表末尾哈希两个完全相同的哈希值的行为,并跟具有无效默克尔根的区块采取相同的处理措施。假设没有double-SHA256 的碰撞,这将检查出所有已知的改变交易而不影响默克尔根的方法。

다음 섹션에서는 위의 내용이 작성된 당시 아직 발견되지 않은 새로운 유형의 블록 용해성에 대해 논의합니다.

머클 트리 모호성으로 인한 3가지 약점

Greg Maxwell은 IRC 비공개 통신에서 Merkle 트리의 "리프와 노드 사이의 도메인 분리 부족"에 한 가지 약점이 있다는 점을 지적했습니다. 머클 트리의 리프가 아닌 노드는 64바이트 입력의 해시(자식 연결)입니다. 동시에 리프 노드는 트랜잭션의 해시 값입니다(증인 없이 직렬화된 형식). 감시 데이터 없이 트랜잭션의 직렬화된 형식이 64바이트일 수 있는 경우 리프 노드와 리프가 아닌 노드를 구별하는 것이 불가능하므로 보안 취약점이 노출될 수 있습니다.

3.1 블록 용해성

2개의 거래가 있는 블록 $B$를 생각해 보세요. 블록 B의 머클 루트 값은 다음과 같습니다.

머클-2

이제 거래가 1개뿐인 블록을 상상해 보세요. 그러면 메르켈 루트는 H(Tx1) 이 됩니다.

피어가 $B$의 블록 헤더를 전달하고 $B$에 두 개가 아닌 하나의 트랜잭션만 있고 블록에 있는 트랜잭션 $T$의 직렬화된 형식이 정확히 H(Tx1)||H(Tx2) 라고 주장한다고 가정해 보겠습니다. . T가 트랜잭션 [2] 으로 성공적으로 역직렬화될 수 있는 경우(실제로 H(Tx1)||H(Tx2) )로 재직렬화됨) $T$의 해시 값은 블록 헤더의 해시 값과 동일합니다. 머클 루트 값이 일치합니다. T가 유효하지 않은 경우 이 버전의 $B$ 블록을 수신하는 노드는 해당 블록을 거부하고 유효하지 않은 블록으로 처리합니다. 그러나 수신 노드가 블록 해시를 유효하지 않은 것으로 영구적으로 태그 하면 정직한 노드가 두 개의 유효한 트랜잭션을 전송하더라도 더 이상 실제로 유효한 블록 $B$를 처리하고 수락할 수 없습니다. 이는 합의에서 노드를 제거하는 데 사용될 수 있습니다.

이 공격은 $N$ 트랜잭션이 있는 블록에서 실제로 N/ 2k 트랜잭션이 있다고 주장하며, 이 트랜잭션은 모두 64바이트 "트랜잭션"입니다. 해시 값은 k번째 행의 노드입니다. 원래 나무의. 이러한 64바이트 값이 모두 성공적으로 트랜잭션으로 역직렬화될 수 있고 이에 따라 통신이 가능하다면 블록을 수신하는 노드는 이러한 64바이트 값 섹션 트랜잭션이 유효하지 않은 경우에도 해시 값을 유효하지 않은 것으로 영구적으로 표시해서는 안 됩니다. .

**3.1.1 메르켈 루트의 사전 이미지를 트랜잭션으로 역직렬화할 수 있도록 이러한 2트랜잭션 블록을 생성하려면 얼마나 많은 작업이 필요합니까? **

트랜잭션은 다음과 같이 직렬화됩니다.

 [version][vin][vout][locktime]

버전 번호와 잠금 시간은 모두 4바이트 길이의 필드이며 역직렬화 요구 사항이 없습니다. 그리고 $vin$(트랜잭션 입력)과 $vout$(트랜잭션 출력)은 다음과 같이 직렬화됩니다.

 [|vin|][vin0]...[vinn][|vout|][vout0]...[voutn]

$vin$의 크기는 비트코인의 "밀도 볼륨"을 사용하여 인코딩됩니다. 각 $vin$에는 이전 트랜잭션의 32바이트 해시가 포함되어 있고 트랜잭션으로 성공적으로 역직렬화할 수 있는 64바이트 트랜잭션을 생성하려고 하므로 |vin| 을 1바이트( 0x01 로 제한할 수 있습니다. )을 인코딩할 수 있습니다. 각 $vin_i$는 다음 필드로 구성됩니다.

 [hash][index][scriptSig][sequence]

여기서 hash 는 32바이트 선주문 트랜잭션 해시 값이고 index hash 로 지정된 트랜잭션의 $vout$ 벡터에 색인이 지정된 4바이트 길이의 시퀀스 번호입니다. 유효한 코인베이스 거래에는 빈 이전 거래 해시 값과 Oxffffffff 로 설정된 인덱스 번호가 있어야 하지만 유효하지 않은 코인베이스 거래는 이러한 값으로 제한되지 않습니다.

scriptsig 스크립트 길이와 스크립트 내용을 인코딩하므로 제약 조건이 있습니다. 길이는 읽은 바이트 수와 일치해야 합니다. 지금은 길이가 1바이트이고 0x00 으로 인코딩된 빈 $scriptSig$를 가정할 수 있습니다.

sequence 제약이 없는 4바이트 길이의 필드입니다.

$vout$ 배열도 길이와 함께 인코딩됩니다. 직렬화가 효과적이려면 이 규칙도 따라야 합니다. 따라서 $vout$의 볼륨도 1로 제한하여 고정 바이트 0x01 이 하나 더 추가됩니다. 나머지 vout 벡터는 다음과 같이 직렬화됩니다.

 [amount][scriptPubKey]

amount 는 수량을 나타내는 8바이트 길이의 필드이고, scriptSig 와 마찬가지로 scriptPubKey 에도 길이 인코딩이 있으므로 최소 1바이트입니다.

요약하자면, 성공적으로 역직렬화할 수 있는 64바이트 트랜잭션은 다음과 같이 구성할 수 있습니다.

이미지-20240920150154129

A = 버전 번호(4바이트, 제한 없음)

B = Vin 수(1바이트, 제한됨)

C = 선주문 거래 ID(32바이트, 제약 없음)

D = 선주문 출력 인덱스 번호(4바이트, 제한 없음)

E = 스크립트 서명(1바이트, 제한됨)

F = 시퀀스(4바이트, 제한 없음)

G = vout 수(1바이트, 제한됨)

H = 양(8바이트, 제약 없음)

I = 스크립트 공개 키의 길이(1바이트, 제한됨)

J = 스크립트 공개 키의 나머지 부분(4바이트, 제한 없음)

K = 잠금 시간(4바이트, 제한 없음)

여기서는 $vout_0$의 $scriptPubKey$를 총 5바이트로 설정하므로 트랜잭션 길이는 64바이트이며 성공적인 역직렬화는 위에서 언급한 바이트(길이 인코딩)로만 제한됩니다. 하지만 전체적으로 살펴보면 $scriptPubKey$와 $scriptSig$의 길이를 합한 값이 4바이트만 필요하다는 것을 알 수 있습니다.

또한 64바이트 중 4바이트만 제한되어 있으며 모두 서로 다른 부분에 표시됩니다. 따라서 64바이트 트랜잭션 블록 헤더로 효과적으로 역직렬화할 수 있는 Merkle 루트의 사전 이미지를 만들려면 8비트만 검색하여 사용 가능한 코인베이스 트랜잭션(32바이트로 해시됨)을 찾으면 됩니다. 해시가 두 번째 32바이트 노드인 두 번째 트랜잭션을 찾기 위한 22비트 검색((1/5) * 2 24 , 따라서 22바이트보다 약간 작음) - 계산 노력이 거의 필요하지 않습니다.

(역자 주: 이것이 의미하는 바는 트랜잭션으로 역직렬화할 수 있는 64바이트 값을 찾아야 한다는 것입니다. 첫 번째 32바이트는 정확히 코인베이스 트랜잭션의 해시입니다. 값이고 다음 32바이트는 정확히 다른 트랜잭션의 해시 값. 코인베이스 트랜잭션 + 일반 트랜잭션의 조합을 찾아야 하며 해당 해시 값의 연결을 트랜잭션에 대해 역직렬화할 수도 있습니다.

3.1.2 머클 트리의 특정 행의 모든 ​​노드를 유효한 트랜잭션으로 역직렬화할 수 있는 블록을 만드는 데 얼마나 많은 작업이 필요합니까?

블록의 첫 번째 트랜잭션은 코인베이스 트랜잭션이어야 하며 앞서 언급한 것처럼 이는 첫 번째 트랜잭션을 나타내는 처음 32바이트를 크게 제한합니다. 4바이트 버전 번호만 제한되지 않습니다. 따라서 코인베이스 거래와 일치할 트리의 특정 행의 첫 번째 노드의 전반부를 찾으려면 최소 28*8 = 224비트를 검색해야 하며, 그런 다음 계속해서 검색을 수행하여 다음과 일치하는 후반부를 찾아야 합니다. 코인베이스 트랜잭션은 어느 정도 의미가 있는 트랜잭션과 일치합니다(이것은 훨씬 쉽습니다. 약 16바이트만 제한되므로 충돌을 찾는 데 128비트 검색만 필요합니다). 물론 Merkle 트리의 모든 행을 사용할 수 있지만 분명히 이는 계산상 실행 가능하지 않아야 합니다.

3.2 SPV(라이트) 클라이언트에 대한 공격

SPV 클라이언트는 거래가 블록에 나타난다는 증거를 받게 됩니다. 이 증거의 본질은 클라이언트에게 머클 트리를 통해 트리 루트부터 트랜잭션까지의 경로를 제공하는 것입니다.

Merkle Tree 아래에서 그러나 (유효한) 64바이트 트랜잭션 $T$가 블록에 포함되어 있고 다음 32바이트(이전 32바이트보다 덜 제한됨)가 다른 가짜 및 유효하지 않은 트랜잭션과 충돌하지 않도록 신중하게 구성되었다고 가정합니다. 거래 F. $R$를 Merkel 루트 값으로 설정하면 다음과 같은 결과를 얻을 수 있습니다.

 R = H(H(H(...H(T)||H(...)...)T = [32bytes]||[H(F)]

그러한 트랜잭션을 구성할 수 있는 경우 노드는 $F$가 이 블록에 있다고 믿도록 SPV 클라이언트를 속일 수 있습니다. 왜냐하면 머클 루트에서 $T$ el 경로로 머클을 제공한 다음 $T$를 해석할 수 있기 때문입니다. (리프 노드가 아닌) 내부 노드로. 블록의 트랜잭션 수는 블록 헤더에서 볼 수 없기 때문에 SPV 클라이언트는 이 숫자를 먼저 알 수 없으므로 올바른 트리 깊이를 알 수 없습니다.

3.2.1 다음 32바이트가 다른 트랜잭션의 해시 값과 충돌하도록 유효한 64바이트 트랜잭션을 만드는 데 얼마나 많은 작업이 필요합니까?

Sergio Lerner 72비트 검색으로 구현될 수 있다는 전문 분석을 발표했으며 Peter Todd도 60비트 검색으로 구현 가능하다고 주장하는 분석을 발표했습니다.

위 다이어그램에서 우리는 거래의 처음 32바이트가 더 많은 선주문 출력을 포함하고 있기 때문에 더 제한적이라는 것을 알 수 있습니다. 이는 유효해야 합니다(그렇지 않으면 거래가 유효하지 않습니다). 따라서 마지막 32바이트에 중점을 둡니다.

이미지-20240920161441713

C = 사전 시퀀스 트랜잭션 ID(사전 시퀀스 트랜잭션 ID의 나머지 5바이트, 제한 없음)

D = 프리앰블 출력 인덱스 번호(4바이트, 21비트 제한)

E = scriptSig(1바이트, 제한됨)

F = 시퀀스(4바이트, 트랜잭션 버전 번호가 1이면 제약 없음)

G = 트랜잭션 출력 수(1바이트, 제한됨)

H = 양(8바이트, 약 33바이트로 제한됨, 아래 참조)

I = scriptPubKey의 길이(1바이트, 제한됨)

J = scriptPubKey의 나머지 부분(4바이트, 제한 없음)

K = 잠금 시간(4바이트, ~29비트 비제약, 아래 참조)

이전 트랜잭션 ID의 나머지 비트는 제한이 없다고 가정할 수 있습니다. 왜냐하면 후보 트랜잭션을 찾으면 전용 40비트 검색을 수행하여 이전 트랜잭션 ID의 마지막 5비트가 일치하는 트랜잭션을 찾을 수 있기 때문입니다. . 마찬가지로, 선주문 출력 인덱스 번호를 부분적으로 제한하여 단순히 2048보다 크지 않도록 요구할 수 있습니다(가정). 2048개의 출력으로 트랜잭션을 생성할 수 있고 적절한 출력 위치가 적절한 거래 금액.

이 필드는 버전 1 트랜잭션에 대한 합의 의미가 없으므로 $sequence$는 제약이 없다고 가정할 수 있습니다. 트랜잭션의 처음 32바이트가 고정되어 있다고 가정하므로 버전 번호를 1로 가정합니다.

그리고 $amount$는 8바이트 필드입니다. 공격자가 많은 돈을 얻을 수 있는 경우 합의 제약 조건은 출력 값이 입력 값보다 작거나 같기 때문에 더 많은 비트가 제한되지 않은 상태로 남습니다. 그러나 이러한 거래에 투입된 자금은 누구나 소비할 수 있기 때문에(혹은 누구도 소비할 수 없기 때문에) 이러한 공격에 사용된 자금은 회수되지 않을 수도 있다(공격자가 채굴자일 경우 복구가 불가능할 수도 있다). 동일한 블록을 다시 지출하여 자금을 회수하려는 시도가 이루어지지만, 다른 채굴자가 해당 블록을 고아화하여 누구나 사용할 수 있는 공격자의 수수료와 출력을 훔칠 수 있습니다. 그리고 자금을 잃을 수 있는 한, 소수의 유효하지 않은 블록을 채굴하고 이러한 블록을 사용하여 라이트 클라이언트를 공격하는 등 동일한 비용으로 실행할 수 있는 다른 공격을 고려해야 합니다(이러한 공격의 특성은 공격은 동일하지 않습니다. 이 공격은 라이트 클라이언트를 속여 가짜 거래가 여러 블록에 의해 확인되었다고 믿게 만들 수 있기 때문에 가짜 블록에는 그러한 양보가 없기 때문에 소수의 가짜 블록을 채굴하는 것보다 더 가치 있을 수 있습니다. 대상 거래가 원하는 수의 블록에서 확인을 받을 수 있는 기능입니다.

논의를 위해 공격자가 부담할 비용을 대략 25 BTC로 설정해 보겠습니다. 이는 현재 2블록 보상의 가치가 있습니다. 이때 제한되는 비트 수는 33이다. (공격자가 687 BTC를 리스크 에 빠뜨릴 의향이 있다고 가정하면 필요한 검색 수가 5비트 감소합니다.)

$locktime$은 4바이트 정수입니다. 5 0000 0000을 초과하면 Unix 시간으로 해석되고, 이 값보다 작으면 블록 높이로 해석됩니다. 현재 시간은 에포크 이후 약 14억 초이므로 유효한 잠금 시간 값은 9억 개로 추정되며 이는 약 29비트의 자유도입니다.

요약하자면, 제한된 81비트가 있습니다. 이는 공격자가 81비트 검색을 실행할 수 있음을 의미합니다(누구나 사용할 수 있는 자금을 제공하는 자금 거래를 구성하기 위한 추가 40비트 추가). 이 방법을 사용할 수 있습니다. SPV 라이트 노드를 속이기 위해. (참고: 이는 동일한 해시를 가진 두 개의 트랜잭션을 찾기 위해 검색할 것으로 예상한 128비트보다 훨씬 작습니다.)

4 취약점 및 완화

4.1 블록 용해성

블록 용해성으로 인한 합의 분할 리스크 유효하지 않은 블록을 둘러싼 처리 논리에 뿌리를 두고 있습니다. 위의 비트코인 ​​코어 코드 설명에서 언급했듯이, 처리 중인 블록이 녹을 수 있는 한 합의 논리는 어떤 블록 헤더도 유효하지 않은 것으로 영구적으로 태그 안 된다는 점을 깨달았습니다. 특정 블록 헤더가 동일한 블록에 해당하는 한 헤더 블록은 유효할 수 있으며 블록 헤더를 영구적으로 비활성화하면 합의 분할이 발생할 수 있습니다.

거래 복사 거래 복사 문제는 Bitcoin-Qt 버전 0.6.1부터 수정되었습니다. 그 당시(그리고 현재)에는 블록 입력에 대한 일련의 검사가 있었고( CheckBlock() )이라는 함수에서 수행됨) 검사가 실패하면 블록이 저장되지 않았으며 검사 오류가 영구적으로 감지되지 않았습니다. 복사된 거래에 대한 새로운 검사도 이 검사 세트에 추가되어 문제가 해결되었습니다.

CheckBlock() 에서도 수행되는 Merkle 트리의 또 다른 확인은 코인베이스 거래와 관련이 있습니다. 블록의 첫 번째 거래가 거래소 구조를 가지고 있지 않은 경우 - 입력, 이전 거래 해시 값은 다음과 같습니다. 모두 0이고 인덱스 번호가 모두 1입니다. 그러면 이 블록도 검증에 실패합니다. 이 검사의 부작용은 섹션 3.1에서 논의된 블록 용해성에 대해 알기도 전에 본질적으로 문제를 방지한다는 것입니다. 앞에서 언급한 것처럼 공격자가 가능한 용융 블록을 생성하려면 최소 224비트 양을 검색해야 합니다. 코인베이스 거래 확인을 통과합니다.

비트코인 코어 0.13.0부터 블록 용해성 처리에 대한 구현이 변경되었으므로 CheckBlock() 에서 머클 트리 용해 가능성을 확인할 수 있으며 태그가 블록이 녹았는지 추적합니다. 이 태그는 이 블록을 영구적으로 비활성화해야 하는지 여부를 결정하는 논리에 포함됩니다. 그러나 CheckBlock() 여전히 ​​두 번 호출됩니다. 한 번은 위에서 언급한 대로 실패 시 조기 반환 기능을 사용하고 다른 한 번은 블록을 저장하기 전에(검사 통과 필요) 호출됩니다. 따라서 CheckBlock() 에서 블록이 실패하고 블록이 유효하지 않다고 생각하게 만드는 이유(용해로 인한 가능성 없음)가 있더라도 함수의 논리는 블록을 영구적으로 비활성화하지 않습니다.

따라서 두 번 호출하는 것은 중복되는 것 같습니다. 비트코인 코어 코드 커밋 dbb89dc 에서는 중복 호출이 제거된 것으로 나타나므로 알 수 없는 용해 가능성으로 인해 CheckBlock() 오류가 발생하면 이 오류로 인해 해당 블록이 영구적으로 비활성화됩니다. 따라서 Bitcoin Core 0.13.0, 0.13.1 및 0.13.2는 모두 섹션 3.1에 설명된 공격에 취약합니다.

문제가 비공개적으로 발견된 후 0.14.0 릴리스에 앞서 비트코인 ​​코어 코드 커밋 ba803ef 에서 변경 사항이 취소되었습니다. 버전 0.13은 이 공격에 취약한 것으로 알려진 유일한 버전입니다.

예를 들어, 블록이 완전히 64바이트 트랜잭션으로 구성된 경우 해당 블록은 영구적으로 유효하지 않은 블록으로 태그 되지 않습니다 [3] . 또는 합의에서 64바이트 트랜잭션이 비활성화될 수 있습니다. . 거래. 보다 즉각적인 수정에 대한 제안은 라이트 클라이언트가 직면한 문제를 발견하고 완화할 때까지 연기되었습니다(섹션 3.2에 설명됨).

4.2 라이트 클라이언트

3.2장에 설명된 공격으로부터 라이트 클라이언트를 보호하기 위해 다양한 완화 조치를 사용할 수 있습니다. Bitcoin Core 0.16.1부터 64바이트 트랜잭션은 더 이상 트랜잭션 풀에 들어갈 수 없습니다. 채굴자들도 이 규칙을 채택한다면 64바이트 트랜잭션을 무효화하는 합의 변경을 제안하는 것이 합리적일 것입니다. 이를 채택하면 Merkle 트리의 리프와 내부 노드 사이의 모호성이 영구적으로 제거되고 기존 라이트 클라이언트도 보호됩니다(그들은 어떠한 변경도 필요하지 않습니다.) [4] .

비트코인 블록체인 온체인 소수의 64바이트 트랜잭션이 있었습니다.

라이트 클라이언트가 사용할 수 있는 또 다른 완화 방법은 증명에 코인베이스 거래뿐만 아니라 코인베이스 거래 자체에 대한 증거도 포함하도록 요구하는 것입니다(동일한 블록의 모든 거래에 필요한 머클 트리의 깊이를 결정하는 데 사용됨). 이를 위해서는 라이트 클라이언트 소프트웨어를 변경해야 합니다. 특히 들어오는 코인베이스 거래가 사전 정의된 형식인지 확인하려면 합의가 변경되지 않아야 합니다.

Sergio Lerner는 또한 그의 보고서에서 추가 완화 조치에 대해 논의했습니다.

참고자료

Sergio Lerner, " 비트코인 머클 트리 디자인의 리프 노드 취약점 ", 2017년 8월 4일. https://bitslog.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/

Peter Todd, “ 소프트 포크 없이 안전한 tx 포함 증명을 위한 신뢰할 수 있는 머클 트리 깊이 ”, 2018년 6월 7일. https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-June/016091.html

각주

1. 이 기사에서는 블록 헤더의 Merkle 루트 값만 논의하므로 트랜잭션은 증인 없이 직렬화된 다음 해싱됩니다.

2. 녹았는지 여부에 관계없이 모든 블록은 통신이 가능한 경우에만 노드에 의해 블록으로 간주됩니다. 즉, 메시지는 네트워크의 메시지 처리 규칙에 따라 역직렬화될 수 있습니다. 이해할 수 없는 메시지는 간단히 폐기됩니다.

3. 이 문서의 "64바이트"는 감시자 없이 직렬화 후 트랜잭션의 길이를 나타냅니다.

4. 우리는 Merkle 트리를 올라가서 내부 노드가 관심 있는 거래라고 주장함으로써 SPV 노드에 대한 공격을 생략합니다. 합리적인 가정 하에서 116비트 작업을 사용하면 라이트 클라이언트가 출력 중 하나가 소비되었다고 생각하도록 속일 수 있습니다. 합의 변경으로 인해 64바이트 트랜잭션이 무효화되고 라이트 클라이언트가 64바이트 트랜잭션을 거부하도록 수정된 경우 이 문제에 대해 전혀 걱정할 필요가 없습니다.

출처
면책조항: 상기 내용은 작자의 개인적인 의견입니다. 따라서 이는 Followin의 입장과 무관하며 Followin과 관련된 어떠한 투자 제안도 구성하지 않습니다.
라이크
즐겨찾기에 추가
코멘트