Thread

Article header

สรุป Mastering Bitcoin: Programming the Open Blockchain บทที่ 5

หายไปนานไม่ใช่ low time แค่มันขี้เกียจจจจจ

Wallet Recovery: การกู้คืนกระเป๋าบิตคอยน์

การสร้างคู่กุญแจ private key และ public key เป็นส่วนสำคัญในการอนุญาตให้กระเป๋าเงินบิตคอยน์สามารถรับและใช้จ่ายบิตคอยน์ได้ แต่การสูญเสีย private key ไปนั้นจะทำให้ไม่สามารถนำบิตคอยน์ที่เกี่ยวข้องกับ public key ที่คู่กันออกมาใช้จ่ายได้อีกเลย ตลอดหลายปีที่ผ่านมา นักพัฒนากระเป๋าเงินและโปรโตคอลได้ทำงานเพื่อออกแบบระบบที่ช่วยให้ผู้ใช้สามารถกู้คืนการเข้าถึงบิตคอยน์ของตนหลังจากเกิดปัญหาโดยไม่ทำให้ความปลอดภัยนั้นลดน้อยถอยลง

ในบทนี้ เราจะสำรวจวิธีการกู้คืนและป้องกันการสูญหายของข้อมูลที่ใช้กันในกระเป๋าเงินสมัยใหม่ บางวิธีได้รับการยอมรับอย่างกว้างขวางเพราะแทบไม่มีข้อเสีย และจึงถือเป็นแนวปฏิบัติที่ดีที่สุด ส่วนวิธีอื่น ๆ แม้จะมีข้อดี แต่ก็มาพร้อมข้อจำกัดบางประการ ทำให้ผู้พัฒนากระเป๋าเงินเลือกใช้แตกต่างกันไป เราจะอธิบายทั้งข้อดี ข้อเสีย และทางเลือกเหล่านี้อย่างเป็นระบบ เพื่อให้ผู้อ่านเข้าใจภาพรวมทั้งหมด

กระเป๋าประเภทสร้างคู่กุญแจแบบอิสระ (Independent Key Generation)

ก่อนอื่นควรทำความเข้าใจก่อนว่า bitcoin wallet หรือ “กระเป๋าเก็บบิตคอยน์” แท้จริงแล้วไม่ได้เก็บบิตคอยน์ไว้ข้างใน แต่เก็บเพียงกุญแจ (keys) ไว้เท่านั้น กุญแจเหล่านี้เชื่อมโยงกับบิตคอยน์ที่ถูกบันทึกไว้บนบล็อกเชน และใช้การพิสูจน์ต่อเครือข่ายว่าคุณถือครอง private key เป็นหลักฐานว่าคุณสามารถใช้จ่ายบิตคอยน์ที่เกี่ยวข้องนั้นได้ ซึ่งต่างจากกระเป๋าสตางค์ทั่วไปที่เก็บเงินสดไว้ภายใน

โดยทั่วไป กระเป๋าเงินบิตคอยน์จะมีทั้ง public key สำหรับสร้าง address และ private key สำหรับสร้างลายเซ็นเพื่ออนุมัติการใช้จ่าย และอีกประเภทหนึ่งคือกระเป๋าที่เก็บเพียง public key ในแอปพลิเคชัน ส่วน private key จะถูกเก็บไว้ในอุปกรณ์ภายนอก เช่น ฮาร์ดแวร์วอลเล็ตหรือระบบหลายลายเซ็น (multisig)

ในยุคแรก แอปพลิเคชันกระเป๋าเงินมักสร้างคู่กุญแจใหม่แบบอิสระทุกครั้งที่ต้องการใช้งาน จากนั้นผู้ใช้จำเป็นต้องสำรองฐานข้อมูลกระเป๋าเงินนั้น ๆ อยู่เสมอ เพื่อป้องกันไม่ให้กุญแจที่สร้างใหม่สูญหาย การล้มเหลวในการสำรองทันเวลาอาจทำให้สูญเสียการเข้าถึงบิตคอยน์ที่เก็บไว้ในกุญแจเหล่านั้นโดยถาวร

กุญแจแต่ละชุดที่สร้างอย่างอิสระมีขนาดประมาณ 32 ไบต์ การสำรองกุญแจจำนวนมากจึงเป็นภาระสำหรับผู้ใช้ บางคนพยายามลดภาระนี้ด้วยการใช้เพียงกุญแจเดียวในการทำธุรกรรมหลายครั้ง แต่ถึงแม้ว่าจะช่วยให้ง่ายต่อการสำรองข้อมูล แต่มันกลับทำให้ความเป็นส่วนตัวลดลงอย่างมาก เนื่องจากทุกธุรกรรมสามารถโยงกลับไปยังผู้ใช้รายเดิมได้ ด้วยเหตุนี้ ผู้ที่ให้ความสำคัญกับความเป็นส่วนตัวมักเลือกสร้างกุญแจใหม่สำหรับแต่ละธุรกรรม ซึ่งทำให้การสำรองข้อมูลเป็นไปได้จริงเพียงบนสื่อดิจิทัลที่มีความจุเพียงพอเท่านั้น image

กระเป๋าเก็บบิตคอยน์ประเภทสร้างกุญแจแบบกำหนดได้ (Deterministic Key)

ฟังก์ชันแฮชจะสร้างเอาต์พุตเดิมเสมอเมื่อรับอินพุตเดิม แต่ถ้าอินพุตเปลี่ยนแปลงเพียงเล็กน้อย เอาต์พุตจะแตกต่างกัน หากฟังก์ชันมีความปลอดภัยทางการเข้ารหัส จะไม่มีใครสามารถคาดเดาเอาต์พุตใหม่ได้ เว้นเสียแต่ว่าพวกเขารู้อินพุตใหม่

เราสามารถใช้คุณสมบัตินี้เพื่อแปลงค่าใด ๆ (เช่น seed) ให้กลายเป็นชุดค่าที่ได้มาอย่างกำหนดได้ซ้ำ ๆ — นั่นคือ ถ้าใช้ seed เดิมกับขั้นตอนเดิม เราจะได้กุญแจอนุพันธ์ชุดเดียวกันทุกครั้ง ตัวอย่างเชิงปฏิบัติ:

# เก็บ entropy แบบสุ่ม แล้วแฮชเป็น seed
$ dd if=/dev/random count=1 status=none | sha256sum
f1cc3bc03ef51cb43ee7844460fa5049e779e7425a6349c8e89dfbb0fd97bb73  -
# กำหนด seed
$ seed=f1cc3bc03ef51cb43ee7844460fa5049e779e7425a6349c8e89dfbb0fd97bb73
# สร้างค่าที่ได้มาแบบกำหนดได้
$ for i in {0..2} ; do echo "$seed + $i" | sha256sum ; done
50b18e0bd9508310b8f699bad425efdf67d668cb2462b909fdb6b9bd2437beb3  -
a965dbcd901a9e3d66af11759e64a58d0ed5c6863e901dfda43adcd5f8c744f3  -
19580c97eb9048599f069472744e51ab2213f687d4720b0efc5bb344d624c3aa  -

ถ้าเรานำค่าที่ได้มาเหล่านี้ไปใช้เป็น private key ของ address ต่าง ๆ เราก็สามารถสร้างกุญแจทั้งหมดซ้ำได้โดยใช้เพียง seed และอัลกอริทึมเดียวกัน ดังนั้นการสำรองข้อมูลเพื่อกู้คืนกระเป๋าที่สร้างกุญแจแบบกำหนดได้จึงทำได้ง่าย — แทนที่จะสำรองกุญแจทุกดอก ผู้ใช้เพียงบันทึก seed และวิธีการ (algorithm/derivation) ที่ใช้เท่านั้น ตัวอย่างเช่น แม้อลิซจะมีบิตคอยน์ที่กระจายอยู่ในหนึ่งล้าน address ต่างกัน สิ่งที่ต้องสำรองเพื่อกู้คืนทั้งหมดอาจเป็นเพียง seed ชุดเดียว:

f1cc 3bc0 3ef5 1cb4 3ee7 8444 60fa 5049
e779 e742 5a63 49c8 e89d fbb0 fd97 bb73

โครงตรรกะของการสร้างกุญแจแบบกำหนดได้แบบเรียงลำดับจะแสดงให้เห็นว่าจาก seed เดียวสามารถแยกสาขา (derive) กุญแจได้หลายดอก แต่กระเป๋าเงินสมัยใหม่มีวิธีที่พัฒนาขึ้น (เช่น แนวคิดกระเป๋าแบบ hierarchical deterministic) ที่ช่วยแยกการสร้าง public key ออกจาก private key ได้ ทำให้สามารถเผยหรือใช้ public key ได้โดยไม่ต้องเก็บ private key ไว้ในที่เสี่ยง เหมาะกับการจัดการความปลอดภัยและความเป็นส่วนตัวมากขึ้น image

การดึงกุญแจลูกสาธารณะ (Public Child Key Derivation)

จากที่เราได้เรียนเรื่องของ public key กันไปในบทก่อนหน้า เราได้เรียนรู้วิธีการสร้าง public key จาก private key โดยใช้การเข้ารหัสแบบเส้นโค้งวงรี (ECC) แล้วมันจะเป็นอย่างไรหากเราใช้วิธีการเดิมแต่เปลี่ยนไปใช้ public key เป็นตัวตั้งแทน พิจารณาการดำเนินการที่เราใช้ในบทก่อนหน้าสำหรับการสร้าง public key (K) จาก private key (k) โดยใช้จุดกำเนิด (G): $$K = k * G $$

คำถามคือ หากเราใช้ public key ที่มีอยู่แทนการสร้างใหม่จาก private key จะสามารถสร้างกุญแจลูก (child key) ได้หรือไม่?

ลองพิจารณาสมการเดิม หากเราบวกค่าเพิ่มเติมเดียวกันทั้งสองฝั่ง เช่น ค่า “123” เราจะได้ว่า: $$K+(123×G)≡(k+123)×G$$

TIP: ในหนังสือเล่มนี้ สัญลักษณ์ “=” ใช้แสดงการคำนวณค่า ส่วน “==” ใช้เพื่อแสดงความสมมูลระหว่างสองด้านของสมการ หากทั้งสองด้านไม่สมมูล ค่าที่ได้จะเป็น “false”

สิ่งที่น่าสนใจคือ การเพิ่มค่า (tweak) เช่น 123 ลงใน public key สามารถทำได้ด้วยข้อมูลสาธารณะเพียงอย่างเดียว โดยไม่ต้องรู้ private key เลย

ตัวอย่างเช่น อลิซสร้าง public key (K) และส่งให้บ็อบ ถึงแม้บ็อบจะไม่รู้ค่า private key (k) แต่เขารู้จุดกำเนิด (G) ดังนั้นเขาสามารถสร้าง public child key ได้ด้วยการเพิ่มค่าใด ๆ ลงไป หากบ็อบแจ้งค่า tweak ที่ใช้กับอลิซ อลิซก็สามารถเพิ่มค่าดังกล่าวลงใน private key ของเธอ เพื่อให้ได้ private child key ที่สอดคล้องกับ public child key ที่บ็อบสร้างขึ้น

กล่าวอีกอย่างคือ แม้ผู้ที่ไม่รู้ private key ก็ยังสามารถสร้าง public child key ได้ไม่จำกัดจาก public key อันเดียว หากมีการกำหนดวิธีสร้าง key tweaks อย่างเป็นระบบ ผู้ที่ถือครอง private key สามารถใช้ key tweaks เดียวกันเพื่อสร้าง private child key ที่ตรงกันได้เสมอเช่นกัน

เทคนิคนี้ช่วยให้ข้อมูลสาธารณะ เช่น public key ของผู้ใช้ สามารถถูกแจกจ่ายไปยังบุคคลอื่น โดยไม่ต้องเปิดเผย private key เมื่อถึงเวลาที่ต้องใช้จ่ายเงิน อลิซสามารถส่งรายการ key tweaks ที่ใช้ไปยังอุปกรณ์ลงนามแบบฮาร์ดแวร์ (hardware wallet) ซึ่งเก็บ private key ไว้อย่างปลอดภัย อุปกรณ์นั้นจะใช้ key tweaks เพื่อสร้าง private child key ที่จำเป็นสำหรับการลงนามธุรกรรม จากนั้นส่งธุรกรรมที่ลงนามแล้วกลับไปยังส่วนติดต่อผู้ใช้ที่ปลอดภัยน้อยกว่าเพื่อเผยแพร่ไปยังเครือข่ายบิตคอยน์

การดึง public child key สามารถสร้างเป็นลำดับเชิงเส้นของกุญแจ คล้ายกับกระเป๋าเงินแบบกำหนดได้ (deterministic wallets) ที่สร้างกุญแจจาก seed อย่างไรก็ตาม กระเป๋าเงินสมัยใหม่ก้าวไปอีกขั้น โดยใช้เทคนิคเพิ่มเติมเพื่อสร้างชุดของ public child keys ที่ซับซ้อนกว่า และจะอธิบายในส่วนถัดไป

การสร้างกุญแจแบบลำดับชั้นเชิงกำหนด (HD) ตามมาตรฐาน BIP32

วอลเล็ตบิตคอยน์สมัยใหม่ทั้งหมดที่เรารู้จัก ใช้การสร้างกุญแจแบบลำดับชั้นเชิงกำหนด (HD) เป็นค่าเริ่มต้น มาตรฐานนี้ถูกกำหนดไว้ใน BIP32 โดยใช้หลักการสร้างกุญแจแบบกำหนดค่าได้ร่วมกับการดึง public child key แบบเลือกได้ผ่านอัลกอริทึมที่สร้างโครงสร้างเป็น tree ของกุญแจ

ใน tree นี้ กุญแจใด ๆ สามารถทำหน้าที่เป็นพ่อแม่ของชุด child key ได้ และ child key แต่ละดอกก็สามารถกลายเป็นพ่อแม่ของชุด child key ใหม่ได้เช่นกัน ไม่มีข้อจำกัดตายตัวในเรื่องความลึกของ tree โครงสร้างแบบนี้ช่วยให้วอลเล็ต HD สามารถสร้างกุญแจจำนวนมากจาก seed เดียว โดยผู้ใช้เพียงสำรอง seed ก็สามารถกู้คืนกุญแจทั้งหมดใน tree ได้อย่างปลอดภัยและสะดวก ดูตัวอย่างได้ในภาพประกอบข้างล่างนี้ image

โครงสร้างแบบ tree ของกุญแจยังสามารถสะท้อนการจัดการและการแบ่งหมวดหมู่ได้อย่างชัดเจน ตัวอย่างเช่น กิ่งหนึ่งของ child key อาจใช้สำหรับรับการชำระเงินขาเข้า อีกกิ่งหนึ่งอาจใช้สำหรับรับเงินทอนจากการชำระเงินขาออก นอกจากนี้ กิ่งของกุญแจยังสามารถประยุกต์ใช้ในบริบทขององค์กร เช่น แยกกิ่งต่าง ๆ ให้กับแผนก บริษัทในเครือ หน้าที่เฉพาะ หรือหมวดหมู่การบัญชี

บทต่อไปเราจะเจาะลึกเรื่องวอลเล็ต HD และอธิบายวิธีการสร้างวอลเล็ตจาก seed ในหัวข้อ "การสร้างวอลเล็ต HD จาก seed"

Seeds and Recovery Codes

วอลเล็ต HD เป็นกลไกที่ทรงพลังสำหรับจัดการกุญแจจำนวนมากที่สกัดมาจาก seed เดียวกัน หากฐานข้อมูลวอลเล็ตของคุณเสียหายหรือสูญหาย คุณสามารถสร้าง private key ทั้งหมดกลับคืนมาได้โดยใช้ seed ชุดเดิม แต่ข้อเสียสำคัญคือ หากผู้อื่นได้ seed ของคุณไป พวกเขาจะสามารถสร้างกุญแจส่วนตัวทั้งหมดได้เช่นกัน ซึ่งอาจทำให้บิตคอยน์ถูกขโมยจากวอลเล็ตแบบลงนามเดี่ยว หรือทำให้ความปลอดภัยของวอลเล็ตแบบหลายลายเซ็นลดลง

ในส่วนนี้เราจะอธิบายรูปแบบของ โค้ดกู้คืน (recovery code) หลายแบบ โดยมุ่งหมายเพื่อทำให้การสำรองข้อมูลทั้งสะดวกและปลอดภัยมากขึ้น

แม้ว่า seed โดยพื้นฐานเป็นตัวเลขสุ่มขนาดใหญ่ — โดยทั่วไปมีขนาดตั้งแต่ 128 ถึง 256 บิต — โค้ดกู้คืนส่วนใหญ่ถูกออกแบบให้เป็น คำในภาษามนุษย์ เพื่อให้จดจำและเขียนเก็บได้ง่ายกว่ารหัสไบนารีหรือเลขฐานสิบหก ตัวอย่างแรงจูงใจในการใช้คำคือผู้ใช้สามารถจดหรือพูดได้โดยไม่ต้องคัดลอกตัวอักษรยาว ๆ และลดความเสี่ยงจากความผิดพลาดเมื่อสำรองด้วยมือ

ตัวอย่างการเก็บ seed สองรูปแบบ (เลขฐานสิบหก กับ คำศัพท์ภาษาอังกฤษ):

Hex-encoded:
0C1E 24E5 9177 79D2 97E1 4D45 F14E 1A1A

Word-encoded:
army van defense carry jealous true
garbage claim echo media make crunch

การจดจำโค้ดกู้คืนเพียงอย่างเดียวอาจเป็นคุณสมบัติที่มีประโยชน์ในบางสถานการณ์ เช่น เมื่อคุณไม่สามารถขนย้ายสิ่งของทางกายภาพ เช่น กระดาษที่เขียนโค้ดกู้คืน โดยไม่เสี่ยงต่อการถูกยึดหรือถูกตรวจค้นโดยบุคคลภายนอกที่อาจขโมยบิตคอยน์ของคุณได้

อย่างไรก็ตาม การพึ่งพาความทรงจำเพียงอย่างเดียวถือเป็นเรื่องอันตราย เพราะมีความเสี่ยงหลายประการ:

  • หากคุณลืมโค้ดกู้คืนและไม่สามารถเข้าถึงฐานข้อมูลวอลเล็ตเดิม บิตคอยน์ของคุณจะสูญหายตลอดกาล

  • หากคุณเสียชีวิตหรือได้รับบาดเจ็บรุนแรง และทายาทไม่สามารถเข้าถึงฐานข้อมูลวอลเล็ตเดิม พวกเขาจะไม่สามารถรับมรดกบิตคอยน์ของคุณได้

  • หากมีคนเชื่อว่าคุณจำโค้ดกู้คืนได้ พวกเขาอาจพยายามบังคับให้คุณเปิดเผยรหัสนั้น ในเวลาที่เขียนหนังสือเล่มนี้ เจมสัน ล็อปป์ ผู้มีส่วนร่วมในการพัฒนาบิตคอยน์ ได้บันทึกเหตุโจมตีทางกายภาพต่อผู้ที่สงสัยว่าเป็นเจ้าของบิตคอยน์และสินทรัพย์ดิจิทัลอื่น ๆ มากกว่า 100 ครั้ง รวมถึงมีการเสียชีวิตอย่างน้อย 3 ราย และหลายกรณีที่เกี่ยวข้องกับการทรมาน จับเป็นตัวประกัน หรือคุกคามครอบครัว

TIP: แม้ว่าคุณจะใช้โค้ดกู้คืนที่ออกแบบมาให้จดจำง่าย เราขอแนะนำอย่างยิ่งให้คุณพิจารณาจดบันทึกไว้

ปัจจุบันมีรหัสกู้คืนหลายประเภทที่มีการใช้งานอย่างแพร่หลาย:

  • BIP39: เป็นวิธีที่ได้รับความนิยมมากที่สุดในการสร้างรหัสกู้คืนในช่วงทศวรรษที่ผ่านมา BIP39 เกี่ยวข้องกับการสร้างลำดับไบต์แบบสุ่ม เพิ่มเช็คซัมเข้าไป และเข้ารหัสข้อมูลเป็นชุดคำศัพท์ 12 ถึง 24 คำ (ซึ่งอาจแปลเป็นภาษาท้องถิ่นของผู้ใช้) คำเหล่านี้ (บวกกับ passphrase ) จะถูกประมวลผ่านฟังก์ชัน key-stretching และนำผลลัพธ์มาใช้เป็น seed BIP39 มีข้อบกพร่องหลายประการซึ่งระบบอื่น ๆ ที่พัฒนาขึ้นภายหลังพยายามแก้ไข

  • Electrum v2: ถูกใช้ในกระเป๋าเงิน Electrum (เวอร์ชัน 2.0 ขึ้นไป) รหัสกู้คืนที่ใช้คำนี้มีข้อดีหลายประการเหนือ BIP39 มันไม่ได้พึ่งพารายการคำศัพท์สากลที่ต้องนำไปใช้ในทุกเวอร์ชันของทุกโปรแกรมที่เข้ากันได้ อีกทั้งรหัสกู้คืนยังมีหมายเลขเวอร์ชันที่ช่วยเพิ่มความน่าเชื่อถือและประสิทธิภาพ เช่นเดียวกับ BIP39 มันรองรับ passphrase (ซึ่ง Electrum เรียกว่า seed extension ) และใช้ฟังก์ชัน key-stretching แบบเดียวกัน

  • Aezeed: ถูกใช้ในกระเป๋าเงิน LND นี่เป็นอีกรหัสกู้คืนที่ใช้คำซึ่งมีการปรับปรุงจาก BIP39 มันรวมหมายเลขเวอร์ชันสองตัว: ตัวแรกเป็นภายในและช่วยกำจัดปัญหาหลายอย่างในการอัปเกรดแอปพลิเคชันกระเป๋าเงิน (เหมือนหมายเลขเวอร์ชันของ Electrum v2); อีกหมายเลขเวอร์ชันเป็นภายนอก ซึ่งสามารถเพิ่มเข้ามาเพื่อเปลี่ยนคุณสมบัติทางการเข้ารหัสพื้นฐานของรหัสกู้คืน นอกจากนี้ยังรวม วันเกิดของกระเป๋าเงิน ในรหัสกู้คืน ซึ่งอ้างอิงถึงวันที่ผู้ใช้สร้างฐานข้อมูลกระเป๋าเงิน โดยสิ่งนี้ช่วยให้กระบวนการกู้คืนสามารถค้นหาเงินทั้งหมดที่เกี่ยวข้องกับกระเป๋าเงินโดยไม่ต้องสแกนบล็อกเชนทั้งหมด ซึ่งมีประโยชน์อย่างยิ่งสำหรับซอฟแวร์ที่เน้นความเป็นส่วนตัว มันรองรับการเปลี่ยนรหัสผ่านหรือเปลี่ยนแปลงรูปแบบอื่น ๆ ของรหัสกู้คืนโดยไม่จำเป็นต้องย้ายเงินไปยัง seed ใหม่—ผู้ใช้เพียงแค่ต้องสำรองรหัสกู้คืนใหม่เท่านั้น ข้อเสียเปรียบเมื่อเทียบกับ Electrum v2 คือ เช่นเดียวกับ BIP39 มันต้องพึ่งพาทั้งซอฟต์แวร์สำรองและกู้คืนที่รองรับรายการคำศัพท์เดียวกัน

  • Muun: ถูกใช้ในกระเป๋าเงิน Muun โดยค่าเริ่มต้นกำหนดให้ธุรกรรมการใช้จ่ายต้องถูกลงนามด้วยกุญแจหลายดอก นี่เป็นรหัสที่ไม่ใช่คำซึ่งต้องมาพร้อมกับข้อมูลเพิ่มเติม (ปัจจุบัน Muun ให้มาในรูปแบบ PDF) รหัสกู้คืนนี้ไม่เกี่ยวข้องกับ seed และถูกใช้เพื่อถอดรหัส private key ที่อยู่ใน PDF แทน แม้ว่าวิธีนี้จะยุ่งยากเมื่อเทียบกับรหัสกู้คืน BIP39, Electrum v2 และ Aezeed แต่มันรองรับเทคโนโลยีและมาตรฐานใหม่ที่กำลังกลายเป็นที่นิยมมากขึ้นในกระเป๋าเงินใหม่ ๆ เช่น การสนับสนุน Lightning Network (LN), ตัวอธิบายสคริปต์เอาต์พุต และ miniscript

  • SLIP39: เป็นวิธีที่พัฒนามาต่อจาก BIP39 โดยนักพัฒนาบางคนที่มีส่วนร่วมใน BIP39 ซึ่ง SLIP39 อนุญาตให้ seed เดียวกระจายโดยใช้รหัสกู้คืนหลายชุดที่สามารถเก็บไว้ในสถานที่ต่างกัน (หรือโดยคนต่างกัน) เมื่อคุณสร้างรหัสกู้คืน คุณสามารถระบุจำนวนที่จะต้องใช้เพื่อกู้คืน seed ได้ ตัวอย่างเช่น คุณสร้างรหัสกู้คืนห้าชุดแต่ต้องการเพียงสามชุดเพื่อกู้คืนซีด SLIP39 ให้การสนับสนุน passphrase ขึ้นอยู่กับรายการคำศัพท์สากล และไม่ได้ให้การกำหนดเวอร์ชันโดยตรง

NOTE: ระบบใหม่สำหรับการกระจายรหัสกู้คืนที่มีความคล้ายคลึงกับ SLIP39 ได้ถูกนำเสนอระหว่างการเขียนหนังสือเล่มนี้ โดยมันมีชื่อ Codex32 ช่วยให้สามารถสร้างและตรวจสอบรหัสกู้คืนได้โดยใช้เพียงคำแนะนำที่พิมพ์ไว้ กรรไกร มีดคัตเตอร์แบบละเอียด ตัวยึดทองเหลือง และปากกา—บวกกับความเป็นส่วนตัวและเวลาว่างสักสองสามชั่วโมง ผู้ที่ไว้วางใจคอมพิวเตอร์สามารถสร้างรหัสกู้คืนได้ทันทีโดยใช้ซอฟต์แวร์บนอุปกรณ์ดิจิทัล คุณสามารถสร้างรหัสกู้คืนได้สูงสุด 31 ชุดเพื่อเก็บไว้ในสถานที่ต่าง ๆ โดยระบุจำนวนที่จะต้องใช้เพื่อกู้คืน seed เนื่องจากเป็นข้อเสนอใหม่ รายละเอียดเกี่ยวกับ Codex32 อาจเปลี่ยนแปลงอย่างมีนัยสำคัญก่อนที่หนังสือเล่มนี้จะตีพิมพ์ ดังนั้นเราจึงแนะนำให้ผู้อ่านที่สนใจรหัสกู้คืนแบบกระจายศูนย์ตรวจสอบสถานะปัจจุบันของมัน https://secretcodex32.com/

passphrase

รูปแบบ BIP39, Electrum v2, Aezeed, และ SLIP39 ทั้งหมดสามารถรองรับการใช้ passphrase ได้ หากคุณเก็บ passphrase ไว้ในความทรงจำ (ไม่จด) มันก็จะมีข้อดีข้อเสียแบบเดียวกับการจดจำ seed เช่นกัน

สามระบบ (BIP39, Electrum v2, และ SLIP39) ไม่ได้รวม passphrase เข้าไปในเช็คซัมที่ใช้ตรวจจับความผิดพลาดในการป้อนข้อมูล ทุก passphrase (รวมถึงการไม่ใช้เลย) จะให้ผลลัพธ์เป็น seed สำหรับโครงสร้างกุญแจ BIP32 แต่จะเป็นโครงสร้างที่ต่างกัน passphrase ที่ต่างกันจะได้กุญแจคนละชุด ซึ่งจุดนี้อาจเป็นทั้งข้อดีหรือข้อเสีย ขึ้นกับมุมมองของคุณ

  • ในด้านบวก หากมีคนได้รหัสกู้คืน (คำศัพท์ 12–24 คำ) ของคุณไป แต่ไม่มี passphrase พวกเขาจะได้โครงสร้างกุญแจ BIP32 หนึ่งชุดที่ใช้งานได้ หากคุณวางแผนรับมือไว้ล่วงหน้า (เช่น โอนบิตคอยน์บางส่วนไปยังโครงสร้างที่ไม่มี passphrase) การถูกขโมยบางส่วนอาจเป็นสัญญาณเตือนว่ารหัสกู้คืนถูกบุกรุก ทำให้คุณมีโอกาสตอบโต้ได้ การที่รหัสกู้คืนเดียวสามารถมี passphrase หลายค่าแล้วให้ผลลัพธ์ที่ดูถูกต้องทั้งหมด ก็เป็นรูปแบบของ plausible deniability (การปฏิเสธที่เป็นไปได้)

  • ในด้านลบ หากคุณถูกบังคับให้มอบรหัสกู้คืน ผู้โจมตีอาจยังคงบีบบังคับให้คุณเปิดเผย passphrase เพิ่มเติมหากยอดที่เห็นไม่ตรงกับที่คาดหวัง การออกแบบเพื่อรองรับการปฏิเสธที่เป็นไปได้จึงไม่มีวิธีพิสูจน์ต่อผู้โจมตีได้ว่าคุณได้เปิดเผยข้อมูลทั้งหมดแล้ว ดังนั้นความเสี่ยงคือพวกเขาอาจยังคงบังคับต่อแม้คุณจะให้รหัสทั้งหมดแล้วก็ตาม

  • ข้อเสียอีกประการคือการลดทอนการตรวจจับข้อผิดพลาด หากคุณพิมพ์ passphrase ผิดเพียงเล็กน้อยเมื่อกู้คืนจากการสำรอง กระเป๋าเงินจะไม่แจ้งเตือนความผิดพลาดได้ชัดเจน — แอปจะแสดงโครงสร้างกุญแจใหม่ที่ใช้งานได้แต่ยอดเป็นศูนย์ ซึ่งผู้ใช้มือใหม่อาจคิดว่าเงินหายไปจริง ๆ และทำการตัดสินใจผิดพลาด เช่น ทิ้งรหัสกู้คืนหรือยอมแพ้ ในทางกลับกัน หากคุณคาดหวังยอดคงเหลือเป็นศูนย์จริง ๆ คุณอาจไม่รู้ตัวถึงความผิดพลาดนั้นเป็นเวลาหลายปีจนกว่าจะลองกู้คืนด้วย passphrase ที่ถูกต้อง

มีเพียง Aezeed เท่านั้นที่รับรองการตรวจสอบความถูกต้องของ passphrase และจะแจ้งข้อผิดพลาดเมื่อใส่ค่าไม่ถูกต้อง ข้อนี้ช่วยลดปัญหาการปฏิเสธที่เป็นไปได้โดยเพิ่มการตรวจจับข้อผิดพลาด และทำให้เป็นไปได้ที่จะพิสูจน์แก่ผู้โจมตีได้ว่าคุณได้เปิดเผย passphrase แล้ว

ผู้ใช้และนักพัฒนามีมุมมองแตกต่างกันเกี่ยวกับวิธีที่ดีกว่า บางคนสนับสนุนการปฏิเสธที่เป็นไปได้อย่างเต็มที่ ขณะที่บางคนชอบความปลอดภัยจากการตรวจจับข้อผิดพลาดสำหรับผู้ใช้มือใหม่และผู้ที่ตกอยู่ภายใต้ความกดดัน เราคาดว่าการถกเถียงนี้จะยังคงอยู่ตราบเท่าที่รหัสกู้คืนยังใช้กันแพร่หลาย

การสำรองข้อมูลอื่น ๆ

แน่นอนว่าข้อมูลที่สำคัญที่สุดนั้นคือ private key เพราะหากคุณสูญเสีย private key คุณจะสูญเสียความสามารถในการใช้จ่ายบิตคอยน์ของคุณ การสร้างกุญแจแบบกำหนดได้และรหัสกู้คืน (คำศัพท์ 12-24 คำ) ให้วิธีแก้ปัญหาที่ค่อนข้างแข็งแกร่งสำหรับการสำรองและกู้คืนกุญแจของคุณและบิตคอยน์ที่พวกมันควบคุม แต่อย่างไรก็ตาม สิ่งสำคัญที่ต้องพิจารณาคือฐานข้อมูลกระเป๋าเงินหลายแห่งเก็บข้อมูลมากกว่าแค่กุญแจ

ตัวอย่างเช่น เมื่อบ๊อบสร้าง address ใหม่เพื่อส่ง invoice ให้อลิซ เขาจะเพิ่ม ป้ายกำกับ (label) ให้กับ address นั้น เพื่อให้สามารถแยกการชำระเงินของอลิซออกจากการชำระเงินอื่น ๆ ที่เขาได้รับได้ เมื่ออลิซจ่ายเงินตาม address ดังกล่าว เธอก็ติดป้ายกำกับกับธุรกรรมด้วยเหตุผลเดียวกัน

กระเป๋าเงินบางแห่งยังสามารถบันทึกข้อมูลเพิ่มเติมที่เป็นประโยชน์กับผู้ใช้ เช่น อัตราแลกเปลี่ยนปัจจุบัน ซึ่งช่วยให้คำนวณภาษีหรือรายงานทางบัญชีได้สะดวกยิ่งขึ้น

ป้ายกำกับและข้อมูลเสริมทั้งหมดนี้จะถูกเก็บไว้ ภายในกระเป๋าเงินของผู้ใช้ เท่านั้น ไม่ได้แชร์กับเครือข่ายบิตคอยน์ ซึ่งช่วยปกป้องความเป็นส่วนตัวและลดการเปิดเผยข้อมูลส่วนบุคคลที่ไม่จำเป็นบนบล็อกเชน

สำหรับตัวอย่างข้อมูล สามารถดูได้จากตารางด้านล่างนี้:

| DATE | LABEL | BTC | | :---- | :---- | :---- | | 2023-01-01 | Bought bitcoins from Joe | +0.00100 | | 2023-01-02 | Paid Bob for podcast | −0.00075 |

ข้อความจากหลาม: ในบางกระเป๋าจะเก็บพวกข้อมูลธุรกรรมของเราด้วย เช่นที่เราส่งหรือที่เรารับ ยกตัวอย่างเช่น sparrow จะเก็บพวก transaction ที่เราเคยรับมา เพื่อให้ไม่ต้องเรียกจาก blockchain หลาย ๆ รอบ

อย่างไรก็ตาม เนื่องจาก ป้ายกำกับของ address และธุรกรรม ถูกเก็บไว้เฉพาะในฐานข้อมูลกระเป๋าเงินของผู้ใช้แต่ละคน และไม่ได้ถูกกำหนดไว้ล่วงหน้า จึงไม่สามารถกู้คืนได้เพียงแค่ใช้รหัสกู้คืนหรือ seed เมื่อกู้คืนจาก seed ผู้ใช้จะเห็นเพียงรายการเวลาธุรกรรมโดยประมาณและจำนวนบิตคอยน์เท่านั้น ซึ่งอาจทำให้ยากต่อการติดตามว่าเงินถูกใช้ไปอย่างไร ลองนึกภาพการตรวจสอบรายการธนาคารหรือบัตรเครดิตจากปีที่แล้วที่มีวันที่และจำนวนเงินครบ แต่ช่อง “คำอธิบาย” กลับว่างเปล่า

ดังนั้น กระเป๋าเงินควรมีวิธีที่สะดวกสำหรับผู้ใช้ในการ สำรองข้อมูลป้ายกำกับ แม้ว่าจะดูเหมือนเป็นเรื่องชัดเจน แต่หลายแอปพลิเคชันที่ได้รับความนิยมทำให้การสร้างและใช้รหัสกู้คืนเป็นเรื่องง่าย กลับไม่มีวิธีสำรองหรือกู้คืนป้ายกำกับ

นอกจากนี้ อาจเป็นประโยชน์หากกระเป๋าเงินรองรับ รูปแบบมาตรฐานในการส่งออกป้ายกำกับ เพื่อให้สามารถนำไปใช้กับแอปพลิเคชันอื่นได้ เช่น ซอฟต์แวร์บัญชี มาตรฐานสำหรับการส่งออกนี้ถูกเสนอไว้ใน BIP329

สำหรับกระเป๋าเงินที่สนับสนุนโปรโตคอลเพิ่มเติม นอกจากการทำงานพื้นฐานของบิตคอยน์ อาจจำเป็นต้องเก็บข้อมูลอื่น ๆ ด้วย ตัวอย่างเช่น ในปี 2023 แอปพลิเคชันหลายตัวได้เพิ่มการสนับสนุนการส่งและรับธุรกรรมผ่าน Lightning Network (LN) แม้ว่าโปรโตคอล LN จะมีวิธีการกู้คืนเงินในกรณีข้อมูลสูญหายที่เรียกว่า static channel backups แต่ก็ไม่สามารถรับประกันผลลัพธ์ได้ หากโหนดที่กระเป๋าเงินของคุณเชื่อมต่อรู้ว่าคุณสูญเสียข้อมูล โหนดนั้นอาจสามารถขโมยบิตคอยน์จากคุณได้ หากฐานข้อมูลของโหนดสูญหายพร้อมกับฐานข้อมูลของคุณ และไม่มีใครมีสำเนาสำรองเพียงพอ ทั้งคุณและโหนดนั้นก็อาจสูญเสียเงินทั้งหมด

การสำรองเส้นทางการสร้างกุญแจ (Backing Up Key Derivation Paths)

ในโครงสร้างกุญแจ BIP32 มีกุญแจระดับแรกประมาณสี่พันล้านคู่ แต่ละคู่สามารถมีลูกของตัวเองอีกสี่พันล้านคู่ และลูกแต่ละตัวก็สามารถมีลูกต่อได้อีกสี่พันล้านคู่ต่อไปเรื่อย ๆ เป็นไปไม่ได้ที่แอปพลิเคชันกระเป๋าเงินจะสร้างแม้แต่เศษเล็กน้อยของคู่กุญแจทั้งหมดในโครงสร้าง BIP32 ซึ่งหมายความว่าการกู้คืนจากการสูญเสียข้อมูลจำเป็นต้องใช้มากกว่ารหัสกู้คืนเพียงอย่างเดียว ต้องอาศัย อัลกอริทึมสำหรับรับ seed (เช่น BIP39) และ อัลกอริทึมการสร้างคู่กุญแจแบบกำหนดได้ (เช่น BIP32) ร่วมด้วย

มีสองวิธีที่ถูกนำเสนอเพื่อแก้ปัญหานี้ วิธีแรกคือ การกำหนดมาตรฐานเส้นทางการสร้างกุญแจ ทุกครั้งที่มีการสร้างหรือเปลี่ยนแปลง address แอปพลิเคชันกระเป๋าบิตคอยน์จะคำนวณ address ใหม่จากเส้นทางมาตรฐานที่กำหนดไว้ ตัวอย่างเช่น BIP44 กำหนดเส้นทางมาตรฐานเป็น m/44'/0'/0' สำหรับ legacy address แอปพลิเคชันกระเป๋าเงินจะใช้เส้นทางนี้ในการคำนวณกุญแจต่าง ๆ ทั้งเมื่อเริ่มใช้งานครั้งแรกและหลังจากกู้คืนจากรหัสกู้คืน

วิธีแก้ปัญหานี้เรียกว่า เส้นทางโดยนัย (Implicit Path) เส้นทางโดยนัยที่เป็นที่นิยมหลายแบบซึ่งกำหนดโดย BIP ต่าง ๆ แสดงอยู่ในตารางด้านล่างนี้: | Standard | Script | BIP32 Path | | ----- | ----------------------- | ----- | | BIP 44 | P2PKH | m/44'/0'/0' | | BIP 49 | Nested P2WPKH | m/49'/1'/0' | | BIP 84 | P2WPKH | m/84'/0'/0' | | BIP 86 | P2TR Single-key | m/86'/0'/0' |

วิธีที่สองคือ การสำรองเส้นทาง (path) ร่วมกับรหัสกู้คืน (recovery code) โดยระบุอย่างชัดเจนว่าเส้นทางใดใช้กับสคริปต์ใด เราเรียกวิธีนี้ว่า การระบุเส้นทางอย่างชัดเจน (explicit paths)

ข้อดีของ เส้นทางโดยปริยาย (implicit paths) คือผู้ใช้ไม่จำเป็นต้องจดจำหรือบันทึกข้อมูลเส้นทางใด ๆ หากป้อนรหัสกู้คืนเข้าไปในแอปพลิเคชันกระเป๋าเงินเดียวกับที่เคยใช้ก่อนหน้านี้ (เวอร์ชันเดียวกันหรือล่าสุดกว่า) ระบบจะสร้างกุญแจสำหรับเส้นทางเดิมโดยอัตโนมัติ

ข้อเสียของ implicit paths คือความไม่ยืดหยุ่น เมื่อใช้รหัสกู้คืน แอปพลิเคชันจะต้องสร้างกุญแจสำหรับทุกเส้นทางที่รองรับ และต้องสแกนบล็อกเชนเพื่อค้นหาธุรกรรมที่เกี่ยวข้อง หากไม่ทำเช่นนั้น อาจทำให้ไม่พบธุรกรรมทั้งหมดของผู้ใช้ วิธีนี้จึงสิ้นเปลืองทรัพยากร โดยเฉพาะในกระเป๋าที่รองรับฟีเจอร์หลายอย่างแต่ผู้ใช้อาจใช้เพียงบางฟีเจอร์เท่านั้น

สำหรับ implicit path recovery codes ที่ไม่มีหมายเลขเวอร์ชัน เช่น BIP39 และ SLIP39 เวอร์ชันใหม่ของแอปกระเป๋าที่เลิกสนับสนุนเส้นทางเก่า ๆ จะไม่สามารถเตือนผู้ใช้ระหว่างกู้คืนได้ว่าเงินบางส่วนอาจไม่ถูกค้นพบ เช่นเดียวกัน หากผู้ใช้ป้อนรหัสกู้คืนลงในซอฟต์แวร์รุ่นเก่า ซอฟต์แวร์ก็จะไม่สามารถค้นหาเส้นทางใหม่ ๆ ที่ผู้ใช้อาจเคยได้รับเงินเข้ามาได้

รหัสกู้คืนที่มีข้อมูลเวอร์ชัน เช่น Electrum v2 และ Aezeed สามารถตรวจจับได้ว่าผู้ใช้กำลังป้อนรหัสกู้คืนที่ใหม่กว่าหรือเก่ากว่า และสามารถแนะนำผู้ใช้ไปยังแหล่งข้อมูลที่เหมาะสมได้

ผลลัพธ์ของ implicit paths คือมันสามารถรวมเฉพาะข้อมูลที่เป็นสากล (เช่น เส้นทางที่กำหนดเป็นมาตรฐาน) หรือข้อมูลที่ได้จาก seed (เช่น keys) เท่านั้น ข้อมูลที่ไม่เป็นเชิงกำหนดและเฉพาะตัวผู้ใช้ไม่สามารถกู้คืนได้

ตัวอย่างเช่น Alice, Bob และ Carol มีบิตคอยน์ที่สามารถใช้ลายเซ็นของสองในสามคนได้ แม้ Alice ต้องการเพียงลายเซ็นของ Bob หรือ Carol เพื่อใช้จ่าย เธอก็ยังต้องมี public keys ของทั้งสองคนเพื่อค้นหาทรัพย์สินร่วมบนบล็อกเชน ซึ่งหมายความว่าทุกคนต้องสำรอง public keys ของทั้งสามคน เมื่อ multisignature และสคริปต์ขั้นสูงอื่น ๆ ถูกใช้งานมากขึ้น ความไม่ยืดหยุ่นของ implicit paths ก็ชัดเจนขึ้น

ข้อดีของ explicit paths คือสามารถระบุได้ชัดเจนว่า key ใดใช้กับ script ใด ทำให้ไม่จำเป็นต้องรองรับสคริปต์ล้าสมัย ไม่มีปัญหาความเข้ากันได้ย้อนหลังหรือไปข้างหน้า และข้อมูลเพิ่มเติม เช่น public keys ของผู้ใช้อื่น สามารถรวมเข้าไปได้โดยตรง

ข้อเสียคือผู้ใช้ต้องสำรองข้อมูลเพิ่มเติมควบคู่กับรหัสกู้คืน ข้อมูลเหล่านี้โดยทั่วไปไม่กระทบต่อความปลอดภัย จึงไม่ต้องการการป้องกันเท่ารหัสกู้คืน แต่ยังคงลดความเป็นส่วนตัวและต้องมีการปกป้องบางส่วน

กระเป๋าเงินเกือบทั้งหมดที่ใช้ explicit paths ปัจจุบันใช้ output script descriptors (เรียกสั้น ๆ ว่า descriptors) ตามที่กำหนดใน BIPs 380, 381, 382, 383, 384, 385, 386 และ 389 โดย descriptors ใช้อธิบาย script และ keys (หรือ key paths) ที่ควรใช้งานร่วมกับมัน | Descriptor | Explanation | | --------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | pkh(02c6…​9ee5) | P2PKH script สำหรับ public key ที่ให้มา | | sh(multi(2,022f…​2a01,03ac…​ccbe)) | P2SH multisignature script ที่ต้องการลายเซ็นสองอันที่สอดคล้องกับ public key ทั้งสองนี้ | | pkh([d34db33f/44'/0'/0']xpub6ERA…​RcEL/1/*) | P2PKH scripts สำหรับ BIP32 path d34db33f โดยใช้ extended public key (xpub) ที่ path M/44'/0'/0' ซึ่งคือ xpub6ERA…​RcEL และใช้ keys ที่ path M/1/* ของ xpub นั้น |

เป็นเวลานานแล้วที่กระเป๋าเงิน (wallet applications) ที่ออกแบบมาเพื่อใช้งานกับ single signature scripts เพียงอย่างเดียว มักใช้ implicit paths ส่วนกระเป๋าเงินที่ออกแบบมาสำหรับ multisignature หรือสคริปต์ขั้นสูงอื่น ๆ นั้น กำลังหันมาใช้ explicit paths โดยใช้ descriptors มากขึ้นเรื่อย ๆ สำหรับแอปพลิเคชันที่รองรับทั้งสองแบบ มักจะปฏิบัติตามมาตรฐานของ implicit paths และในขณะเดียวกันก็ให้การรองรับ descriptors ด้วย

เทคโนโลยีของกระเป๋าเงิน (A Wallet Technology Stack in Detail)

นักพัฒนากระเป๋าเงินสมัยใหม่สามารถเลือกใช้เทคโนโลยีหลายรูปแบบเพื่อช่วยผู้ใช้ในการสร้างและจัดการการสำรองข้อมูล โดยทุกปีจะมีโซลูชันใหม่ ๆ เกิดขึ้น แทนที่จะลงลึกในรายละเอียดของแต่ละตัวเลือกที่อธิบายไปก่อนหน้านี้ในบทนี้ เราจะเน้นที่ชุดเทคโนโลยี (technology stack) ที่นิยมใช้อย่างแพร่หลายในกระเป๋าเงิน ณ ต้นปี 2023 ได้แก่:

  • BIP39 recovery codes
  • BIP32 HD key derivation
  • BIP44-style implicit paths

มาตรฐานเหล่านี้มีมาตั้งแต่ปี 2014 หรือก่อนหน้านั้น และสามารถหาข้อมูลเพิ่มเติมเพื่อนำมาใช้งานได้ไม่ยาก อย่างไรก็ตาม หากคุณสนใจทดลองสิ่งใหม่ ๆ เราแนะนำให้ศึกษามาตรฐานสมัยใหม่ที่อาจเพิ่มฟีเจอร์หรือความปลอดภัยให้มากขึ้นได้

BIP39 Recovery Codes

BIP39 recovery codes คือ ลำดับคำ (word sequences) ที่ใช้แทนตัวเลขสุ่ม เพื่อทำหน้าที่เป็น seed สำหรับการสร้างกระเป๋าเงินแบบกำหนดค่าได้ล่วงหน้า (deterministic wallet) ลำดับคำชุดเดียวก็เพียงพอที่จะสร้าง seed ใหม่ และสามารถสร้างกุญแจทั้งหมดที่เกี่ยวข้อง (derived keys) ได้

แอปกระเป๋าเงินที่รองรับ deterministic wallets ด้วย BIP39 recovery codes จะให้ผู้ใช้บันทึกลำดับคำจำนวน 12–24 คำ เมื่อสร้างกระเป๋าเงินครั้งแรก ลำดับคำเหล่านี้ทำหน้าที่เป็น การสำรองข้อมูลของกระเป๋าเงิน (wallet backup) และสามารถใช้กู้คืนหรือสร้างกุญแจทั้งหมดใหม่ได้ ไม่ว่าจะใช้แอปเดียวกันหรือแอปกระเป๋าเงินอื่นที่รองรับมาตรฐานเดียวกัน

รหัสกู้คืน (recovery codes) ทำให้การสำรองข้อมูลสะดวกขึ้น เพราะอ่านง่าย และสามารถถ่ายทอดหรือจดบันทึกได้อย่างถูกต้อง

Tip:รหัสกู้คืน (recovery codes) มักถูกเข้าใจผิดว่าเหมือนกับ “brainwallets” แต่จริง ๆ แล้วไม่เหมือนกัน ความแตกต่างหลักคือ

  • Brainwallet → เป็นคำที่ผู้ใช้เลือกขึ้นมาเอง
  • Recovery code → เป็นคำที่ถูกสุ่มสร้างขึ้นโดยกระเป๋าเงิน แล้วแสดงให้ผู้ใช้บันทึก

ความแตกต่างนี้สำคัญมาก เพราะทำให้ recovery codes มีความปลอดภัยกว่ามาก เนื่องจากมนุษย์มักจะไม่สามารถสร้างความสุ่มที่แท้จริงได้ดีนัก

โปรดทราบว่า BIP39 เป็นหนึ่งในการนำมาตรฐานรหัสกู้คืน (recovery code standard) มาประยุกต์ใช้ โดย BIP39 ถูกเสนอโดยบริษัทผู้อยู่เบื้องหลัง Trezor hardware wallet และสามารถใช้งานร่วมกับแอปกระเป๋าเงินอื่น ๆ ได้มากมาย แม้ว่าจะไม่ใช่ทุกแอปที่จะรองรับก็ตาม

การสร้างรหัสสำรอง (Generating a Recovery Code)

รหัสกู้คืน (Recovery codes) ถูกสร้างขึ้นโดยอัตโนมัติจากแอปกระเป๋าเงิน โดยใช้กระบวนการมาตรฐานที่กำหนดไว้ใน BIP39 ขั้นตอนการสร้างมีดังนี้:

  1. สร้างลำดับสุ่ม (entropy) ความยาวระหว่าง 128 ถึง 256 บิต
  2. สร้างค่า checksum ของลำดับสุ่ม โดยการนำบิตแรกจำนวน (ความยาว entropy ÷ 32) ของค่า SHA256 hash มาใช้
  3. เติมค่า checksum ต่อท้ายลำดับ entropy
  4. แบ่งผลลัพธ์ออกเป็นกลุ่มย่อย ความยาว 11 บิตต่อกลุ่ม
  5. นำค่า 11 บิตแต่ละกลุ่มไปแมปกับคำหนึ่งคำจาก พจนานุกรมมาตรฐานที่มี 2,048 คำ
  6. ผลลัพธ์สุดท้ายก็คือ รหัสกู้คืน (recovery code) ซึ่งอยู่ในรูปแบบลำดับคำ (word sequence) image
BIP39:Entropy และความยาวของคำ

| Entropy (bits) | Checksum (bits) | Entropy + checksum (bits) | Recovery code words | | :---: | :---: | :---: | :---: | | 128 | 4 | 132 | 12 | | 160 | 5 | 165 | 15 | | 192 | 6 | 198 | 18 | | 224 | 7 | 231 | 21 | | 256 | 8 | 264 | 24 |

จากรหัสกู้คืนสู่seed (From recovery code to seed)

รหัสกู้คืน (recovery code) แทนค่า entropy ที่มีความยาวระหว่าง 128 ถึง 256 บิต จากนั้น entropy จะถูกใช้สร้าง seed ที่ยาวกว่า (512 บิต) ผ่านฟังก์ชัน key-stretching ชื่อ PBKDF2 ซึ่ง seed ที่ได้จะถูกนำไปสร้างกระเป๋าเงินแบบกำหนดค่าได้ล่วงหน้า (deterministic wallet) และสร้างกุญแจอนุพันธ์ (derived keys) ต่อไป

ฟังก์ชัน key-stretching จะรับพารามิเตอร์สองค่า ได้แก่ entropy และ salt ปกติ salt มีหน้าที่ป้องกันการโจมตีแบบ brute-force โดยทำให้การสร้างตารางค้นหาทำได้ยากขึ้น แต่ในมาตรฐาน BIP39 salt ยังใช้อนุญาตให้ผู้ใช้เพิ่ม passphrase ซึ่งเป็นปัจจัยด้านความปลอดภัยเพิ่มเติมสำหรับการป้องกัน seed (จะอธิบายรายละเอียดในหัวข้อ Optional passphrase in BIP39)

Tip: ฟังก์ชัน key-stretching ของ BIP39 ใช้การแฮช 2,048 รอบ ทำให้การโจมตีแบบ brute-force ด้วยซอฟต์แวร์ทำได้ยากขึ้นเล็กน้อย แต่ฮาร์ดแวร์เฉพาะทาง (special-purpose hardware) จะไม่ได้รับผลกระทบมากนัก สำหรับผู้โจมตีที่ต้องเดา recovery code ทั้งหมด ความยาวขั้นต่ำ 128 บิตของรหัสก็เพียงพอที่จะมอบความปลอดภัยสูงแล้ว อย่างไรก็ตาม หากผู้โจมตีรู้บางส่วนของรหัส ฟังก์ชัน key-stretching จะช่วยเพิ่มความปลอดภัยโดยทำให้การตรวจสอบความเป็นไปได้ของรหัสแต่ละแบบช้าลง

อย่างไรก็ดี พารามิเตอร์ของ BIP39 ถูกมองว่าค่อนข้างอ่อนแอเมื่อเทียบกับมาตรฐานสมัยใหม่ แม้ในช่วงที่เผยแพร่เมื่อเกือบสิบปีก่อน ก็เพื่อรองรับอุปกรณ์ hardware signing devices ที่มี CPU กำลังต่ำ มาตรฐานทางเลือกบางตัว เช่น Aezeed ใช้การแฮช 32,768 รอบผ่านอัลกอริทึม Scrypt ที่ซับซ้อนกว่า แม้ว่าจะไม่สะดวกในการใช้งานบนอุปกรณ์ฮาร์ดแวร์

กระบวนการดังกล่าวในขั้นตอนที่ 7 ถึง 10 เป็นการต่อเนื่องจากหัวข้อ Generating a recovery code ที่อธิบายไปก่อนหน้านี้:

  1. พารามิเตอร์แรก ของฟังก์ชัน key-stretching PBKDF2 คือ entropy ที่ได้มาจาก ขั้นตอนที่ 6
  2. พารามิเตอร์ที่สอง ของ PBKDF2 คือ salt โดย salt นี้ถูกสร้างขึ้นจากสตริงคงที่ "mnemonic" ต่อเข้ากับสตริง passphrase ที่ผู้ใช้จะใส่เพิ่ม (ซึ่งเป็นทางเลือก ไม่จำเป็นต้องใส่)
  3. PBKDF2 จะทำการขยาย (stretch) recovery code และ salt ด้วยการแฮชจำนวน 2,048 รอบ โดยใช้อัลกอริทึม HMAC-SHA512 และสร้างค่าผลลัพธ์สุดท้ายเป็นค่า 512 บิต
  4. ค่าที่ได้ซึ่งเป็น 512 บิต นี้ก็คือ seed image
128-bit entropy BIP39 recovery code, no passphrase, resulting seed

image

128-bit entropy BIP39 recovery code, with passphrase, resulting seed

image

256-bit entropy BIP39 recovery code, no passphrase, resulting seed

image

คุณต้องการ Entropy มากแค่ไหน?

BIP32 อนุญาตให้ seed มีค่าได้ตั้งแต่ 128 ถึง 512 บิต BIP39 รับค่าได้ตั้งแต่ 128 ถึง 256 บิต; Electrum v2 รับค่าได้ 132 บิต; Aezeed รับค่าได้ 128 บิต; SLIP39 รับค่าได้ 128 หรือ 256 บิต ความแตกต่างของตัวเลขเหล่านี้ทำให้ไม่ชัดเจนว่าต้องใช้ entropy เท่าไรถึงจะปลอดภัย เราจะพยายามอธิบายให้กระจ่าง

extended private key ของ BIP32 ประกอบด้วยคีย์ขนาด 256 บิตและ chain code ขนาด 256 บิต รวมทั้งหมด 512 บิต นั่นหมายความว่ามีคีย์ส่วนตัวแบบขยายได้สูงสุด 2^512 แบบ หากคุณเริ่มต้นด้วย entropy ที่มากกว่า 512 บิต คุณก็ยังจะได้ extended private key ที่มี entropy เพียง 512 บิตอยู่ดี—ดังนั้นจึงไม่มีประโยชน์ที่จะใช้มากกว่า 512 บิต แม้ว่าในบรรดามาตรฐานที่กล่าวมาจะอนุญาตให้ทำก็ตาม

อย่างไรก็ตาม แม้ว่าจะสามารถสร้างคีย์ส่วนตัวแบบขยาย (extended private key) ได้มากถึง 2^512 แบบ แต่คีย์ส่วนตัวจริง ๆ (regular private key) ที่ใช้งานได้มีเพียงประมาณ 2^256 แบบเท่านั้น—และคีย์เหล่านี้เองที่เป็นตัวปกป้องบิตคอยน์ของคุณ ซึ่งหมายความว่า ถึงคุณจะใช้ entropy เกิน 256 บิตในการสร้าง seed สุดท้ายแล้วคีย์ส่วนตัวที่ได้ก็ยังมี entropy เพียง 256 บิตอยู่ดี แม้ว่าในอนาคตอาจมีโปรโตคอลบิตคอยน์บางชนิดที่สามารถนำ entropy ส่วนเกินใน extended key มาใช้เพื่อเพิ่มความปลอดภัย แต่ในปัจจุบันยังไม่มีการใช้งานจริง

ระดับความปลอดภัยของ public key บิตคอยน์อยู่ที่ 128 บิต หมายความว่าผู้โจมตีต้องคำนวณราว 2^128 ครั้งบน elliptic curve จึงจะหาคีย์ส่วนตัวได้ ดังนั้นการใช้ entropy เกิน 128 บิตไม่ได้เพิ่มประโยชน์ด้านความปลอดภัย ตราบใดที่คีย์ส่วนตัวถูกสุ่มอย่างทั่วถึงในช่วง 2^256 ทั้งหมด

มีประโยชน์เพิ่มเติมอย่างหนึ่งจาก entropy ที่มากขึ้น: ถ้าผู้โจมตีเห็น recovery code ของคุณบางส่วน (แต่ไม่ใช่ทั้งหมด) ยิ่ง entropy มาก การที่เขาจะเดาส่วนที่เหลือก็จะยากขึ้น ยกตัวอย่างเช่น ถ้าผู้โจมตีเห็นครึ่งหนึ่งของโค้ด 128 บิต (64 บิต) ก็มีความเป็นไปได้ที่เขาจะ brute force อีก 64 บิตที่เหลือได้ แต่ถ้าเขาเห็นครึ่งหนึ่งของโค้ด 256 บิต (128 บิต) ก็ไม่เป็นไปได้ที่เขาจะ brute force ส่วนที่เหลือได้ เราไม่แนะนำให้พึ่งพาการป้องกันแบบนี้—ควรเก็บ recovery code ของคุณให้ปลอดภัย หรือใช้วิธีอย่าง SLIP39 ที่ให้คุณสามารถกระจาย recovery code ไว้หลายที่ โดยไม่ต้องอาศัยความปลอดภัยจากโค้ดใดโค้ดหนึ่งเพียงอย่างเดียว

ณ ปี 2023 กระเป๋าสตางค์สมัยใหม่ส่วนใหญ่สร้าง entropy ขนาด 128 บิตสำหรับ recovery code ของพวกเขา (หรือค่าที่ใกล้เคียง 128 เช่น Electrum v2 ที่ใช้ 132 บิต)

passphrase ใน BIP39

มาตรฐาน BIP39 อนุญาตให้ใส่ passphrase เสริมเพื่อสร้าง seed หากไม่ใส่ จะใช้ salt เป็นสตริงคงที่ "mnemonic" ทำให้ recovery code ใด ๆ ให้ผลเป็น seed เดียวตามมาตรฐาน แต่เมื่อมี passphrase ใด ๆ เข้ามา จะได้ seed ที่ต่างจากเดิม: ทุก passphrase ที่เป็นไปได้จะให้ seed คนละค่า ไม่มีค่าใดที่ถือว่า “ผิด” ดังนั้นรหัสกู้คืนชุดเดียวสามารถจับคู่กับ passphrase หลายค่าได้ ผลคือมีชุดกระเป๋า (wallets) ขนาดมหาศาล ขยายได้ถึงระดับประมาณ 2^512 ทำให้การเดาแบบ brute-force เพื่อไปพบกระเป๋าที่มีการใช้งานจริงเป็นสิ่งที่เป็นไปไม่ได้ในทางปฏิบัติ.

Tip: ใน BIP39 ไม่มี passphrase ที่ “ผิด” ทุก passphrase จะนำไปสู่กระเป๋าสตางค์บางใบ ซึ่งหากไม่เคยถูกใช้งานมาก่อน กระเป๋าสตางค์นั้นก็จะว่างเปล่า

Passphrase แบบเลือกใช้จะสร้างคุณสมบัติที่สำคัญสองประการ:

  • มีสิ่งที่จดจำได้ ที่ทำให้ recovery code ใช้งานไม่ได้ด้วยตัวมันเอง ปกป้อง recovery code จากการถูกขโมยโดยโจรทั่วไป สำหรับการป้องกันจากโจรที่มีความรู้ด้านเทคนิค คุณจำเป็นต้องใช้ passphrase ที่แข็งแกร่งมาก
  • รูปแบบหนึ่งของ plausible deniability หรือ “กระเป๋าลับ” (duress wallet) ซึ่ง passphrase ที่เลือกจะนำไปยังกระเป๋าที่มีเงินจำนวนน้อย ใช้เพื่อเบี่ยงเบนความสนใจของผู้โจมตีจาก “กระเป๋าจริง” ที่เก็บเงินส่วนใหญ่

สิ่งสำคัญที่ควรทราบคือ การใช้ passphrase ยังนำมาซึ่งความเสี่ยงของการสูญเสีย:

  • หากเจ้าของกระเป๋าไม่สามารถใช้งานได้หรือเสียชีวิตไป และไม่มีใครรู้ passphrase ค่า seed จะไร้ประโยชน์ และเงินทั้งหมดที่เก็บในกระเป๋าจะสูญหายไปตลอดกาล
  • ในทางกลับกัน หากเจ้าของทำการสำรอง passphrase ไว้ในที่เดียวกับ seed มันก็จะทำลายวัตถุประสงค์ของการมีปัจจัยที่สอง

แม้ว่า passphrase จะมีประโยชน์มาก แต่ควรใช้งานร่วมกับกระบวนการที่วางแผนอย่างรอบคอบสำหรับการสำรองและการกู้คืน โดยคำนึงถึงความเป็นไปได้ในการมีชีวิตต่อจากเจ้าของ และเปิดโอกาสให้ครอบครัวสามารถกู้คืนได้

การสร้าง HD Wallet จาก Seed

กระเป๋าเงินแบบ HD ถูกสร้างจาก root seed เดียว ซึ่งเป็นตัวเลขสุ่มขนาด 128, 256 หรือ 512 บิต โดยทั่วไป seed นี้จะถูกสร้างขึ้นโดยแอปหรือถอดรหัสมาจาก recovery code ตามที่อธิบายไว้ก่อนหน้านี้

กุญแจทุกดอกในกระเป๋าเงิน HD จะถูกอนุพันธ์อย่างกำหนดได้จาก root seed เดียวกัน ส่งผลให้สามารถสร้างกระเป๋าเงิน HD ทั้งหมดใหม่ได้จาก seed ชุดเดียว ในระบบที่เข้ากันได้ วิธีนี้ทำให้การ สำรอง, กู้คืน, ส่งออก และ นำเข้ากระเป๋าเงิน ซึ่งอาจมีจำนวนกุญแจเป็นพันหรือเป็นล้าน ดำเนินการได้สะดวกเพียงแค่เก็บรักษา recovery code ที่มาจาก root seed เท่านั้น

image

root seed จะถูกป้อนเข้าไปในอัลกอริทึม HMAC-SHA512 และค่าแฮชที่ได้จะถูกนำมาใช้สร้าง master private key (m) และ master chain code (c)

จากนั้น master private key (m) จะสร้าง master public key (M) ที่สอดคล้องกัน โดยใช้กระบวนการ elliptic curve multiplication แบบปกติ คือ m × G ตามที่เราเห็นไปแล้วใน public_key_derivation

ส่วน master chain code (c) จะถูกใช้เพื่อเพิ่ม entropy ในฟังก์ชันที่สร้าง child keys จาก parent keys ซึ่งเราจะได้เห็นในหัวข้อถัดไป

Private child key derivation

กระเป๋าเงิน HD ใช้ฟังก์ชัน child key derivation (CKD) เพื่อสร้าง child keys จาก parent keys

ฟังก์ชัน CKD จะอิงกับ one-way hash function ที่รวมข้อมูลดังนี้:

  • กุญแจ private หรือ public ของ parent (uncompressed key)
  • chain code (256 บิต)
  • หมายเลขดัชนี (index number) (32 บิต)

chain code ถูกใช้เพื่อเพิ่มข้อมูลสุ่มเชิงกำหนด (deterministic random data) ลงในกระบวนการ เพื่อให้การรู้แค่ index และ child key ไม่เพียงพอที่จะสร้าง child keys อื่น ๆ ได้ การรู้เพียง child key ไม่สามารถหาพี่น้อง (siblings) ของมันได้ เว้นแต่จะมี chain code ด้วย โดย chain code เริ่มต้น (ที่ root ของ tree) จะมาจาก seed ในขณะที่ chain codes ถัดไปจะถูกอนุพันธ์มาจาก chain code ของ parent แต่ละตัว

สามองค์ประกอบนี้ (parent key, chain code, index) จะถูกนำมารวมกันและทำการ hash เพื่อสร้าง child keys ดังนี้:

  • parent public key, chain code และ index number จะถูกนำมารวมกันแล้วทำการ hash ด้วยอัลกอริทึม HMAC-SHA512 เพื่อสร้างค่าแฮช 512 บิต
  • ค่าแฮช 512 บิตนี้จะถูกแบ่งออกเป็นสองส่วน ส่วนละ 256 บิต
    • ครึ่งขวา (256 บิต) จะกลายเป็น chain code สำหรับ child
    • ครึ่งซ้าย (256 บิต) จะถูกนำไปบวกกับ parent private key เพื่อสร้าง child private key

จากรูปข้างล่างเราจะเห็นตัวอย่างที่ใช้ index = 0 เพื่อสร้าง child ตัวแรก (zero child) ของ parent image

การเปลี่ยนค่า index ช่วยให้สามารถขยายจากกุญแจแม่ (parent key) เพื่อสร้างกุญแจลูก (child keys) ในลำดับได้ เช่น Child 0, Child 1, Child 2 และต่อไปเรื่อย ๆ โดยกุญแจแม่แต่ละดอกสามารถมีลูกได้สูงสุด 2,147,483,647 ดอก (2³¹) ซึ่งคิดเป็นครึ่งหนึ่งของช่วงค่า 2³² ทั้งหมด อีกครึ่งหนึ่งถูกสงวนไว้สำหรับรูปแบบการอนุพันธ์พิเศษที่จะอธิบายในบทถัดไป

เมื่อกระบวนการนี้ถูกทำซ้ำในระดับถัดไป แต่ละกุญแจลูกก็สามารถกลายเป็นกุญแจแม่และสร้างกุญแจลูกของมันเองต่อไปได้เช่นกัน ทำให้เกิดการขยายแบบลำดับชั้นได้อย่างไม่จำกัด (infinite generations)

Using derived child keys

child private keys ไม่สามารถแยกความแตกต่างได้จากกุญแจแบบไม่กำหนดล่วงหน้า (nondeterministic หรือกุญแจสุ่ม) เนื่องจากฟังก์ชัน derivation เป็น one-way function ดังนั้น child key ไม่สามารถถูกใช้เพื่อหากุญแจ parent ได้ และ child key ก็ไม่สามารถถูกใช้เพื่อหาพี่น้อง (siblings) ได้เช่นกัน หากคุณมีกุญแจลูกลำดับที่ n คุณจะไม่สามารถหาพี่น้องของมัน เช่น กุญแจ n–1 หรือ n+1 หรือกุญแจอื่น ๆ ที่อยู่ในลำดับได้ มีเพียง parent key และ chain code เท่านั้น ที่สามารถอนุพันธ์ลูกทั้งหมดออกมาได้ หากไม่มี child chain code กุญแจลูกก็ไม่สามารถถูกใช้เพื่อสร้างกุญแจหลาน (grandchildren) ได้เช่นกัน คุณจำเป็นต้องมีทั้ง child private key และ child chain code เพื่อเริ่มต้นสาขาใหม่และสร้าง grandchildren

แล้ว child private key สามารถใช้ทำอะไรได้บ้าง? มันสามารถถูกใช้เพื่อสร้าง public key และ Bitcoin address และสามารถใช้เพื่อ เซ็นธุรกรรม (sign transactions) เพื่อใช้จ่าย Bitcoin ที่ถูกส่งเข้ามายัง address นั้นได้

Tip: child private key, public key ที่สอดคล้องกัน และ Bitcoin address ทั้งหมดนี้ไม่สามารถแยกความแตกต่างได้จากกุญแจและ address ที่ถูกสร้างขึ้นแบบสุ่ม ความจริงที่ว่ามันเป็นส่วนหนึ่งของลำดับจะไม่สามารถมองเห็นได้จากภายนอกฟังก์ชันของ HD wallet ที่สร้างมันขึ้นมา และเมื่อมันถูกสร้างขึ้นแล้ว มันก็ทำงานเหมือนกับกุญแจ “ปกติ” ทุกประการ

Extended keys

ตามที่เราได้เห็นไปก่อนหน้านี้ ฟังก์ชัน key derivation สามารถถูกใช้เพื่อสร้าง children ได้ในทุกระดับของ tree โดยอ้างอิงจากข้อมูลนำเข้าสามส่วน: key, chain code และ index ของ child ที่ต้องการ โดยองค์ประกอบที่สำคัญที่สุดสองอย่างคือ key และ chain code ซึ่งเมื่อรวมกันแล้วจะถูกเรียกว่า extended key คำว่า extended key อาจถูกมองว่าเป็น extensible key ก็ได้ เพราะกุญแจลักษณะนี้สามารถถูกใช้เพื่อสร้าง children ได้

Extended keys จะถูกเก็บและแสดงผลในรูปแบบง่าย ๆ คือการนำ key มาต่อกับ chain code ซึ่งมีอยู่สองประเภทหลัก ได้แก่:

  • Extended private key คือการรวมกันของ private key และ chain code ที่สามารถใช้สร้าง child private keys ได้ (และจากนั้นก็สร้าง child public keys ได้อีกต่อหนึ่ง)

  • Extended public key คือการรวมกันของ public key และ chain code ที่สามารถใช้สร้างได้เฉพาะ child public keys เท่านั้น ตามที่อธิบายไว้ใน public_key_derivation

ลองนึกภาพ extended key เป็นเสมือนรากของกิ่งก้าน (branch) ในโครงสร้างต้นไม้ของ HD wallet เมื่อคุณมีรากนี้แล้ว ก็สามารถแตกกิ่งก้านที่เหลือต่อไปได้ โดย extended private key จะสร้างกิ่งก้านที่สมบูรณ์ได้ทั้งหมด ขณะที่ extended public key จะสร้างได้เพียงกิ่งก้านที่ประกอบด้วยเฉพาะ public keys เท่านั้น

Extended keys ยังถูกเข้ารหัสด้วย base58check เพื่อให้ง่ายต่อการส่งออกและนำเข้าไปยังกระเป๋าเงินอื่น ๆ ที่รองรับ BIP32 โดยการเข้ารหัส base58check สำหรับ extended keys จะใช้หมายเลขเวอร์ชันพิเศษ ทำให้เมื่อถูกเข้ารหัสออกมาเป็นอักขระ base58 จะขึ้นต้นด้วย prefix ที่จดจำง่ายอย่าง "xprv" และ "xpub" ทั้งนี้ เนื่องจาก extended key บรรจุข้อมูลมากกว่าที่อยู่ (address) ปกติหลายเท่า มันจึงมีความยาวมากกว่าสตริงที่เข้ารหัสด้วย base58check แบบอื่น ๆ ที่เราเคยเห็นมาก่อนหน้านี้

นี่คือตัวอย่างของ extended private key ที่เข้ารหัสด้วย base58check:

xprv9tyUQV64JT5qs3RSTJkXCWKMyUgoQp7F3hA1xzG6ZGu6u6Q9VMNjGr67Lctvy5P8oyaYAL9CAWrUE9i6GoNMKUga5biW6Hx4tws2six3b9c

นี่คือตัวอย่างของ extended public key ที่เข้ารหัสด้วย base58check ซึ่งตรงกับ private key ข้างต้น:

xpub67xpozcx8pe95XVuZLHXZeG6XWXHpGq6Qv5cmNfi7cS5mtjJ2tgypeQbBs2UAR6KECeeMVKZBPLrtJunSDMstweyLXhRgPxdp14sk9tJPW9

การสร้าง Public child key derivation

ดังที่กล่าวไว้ก่อนหน้านี้ คุณสมบัติที่มีประโยชน์อย่างมากของ HD wallet คือความสามารถในการสร้างกุญแจสาธารณะลูกได้จากกุญแจสาธารณะหลักโดยไม่ต้องมี private key อยู่ด้วย วิธีนี้ทำให้มีสองแนวทางในการได้มาซึ่งกุญแจสาธารณะลูก: สร้างจาก private child key หรือสร้างโดยตรงจาก extended public key ของกุญแจหลัก

Extended public key สามารถใช้สร้างกุญแจสาธารณะทั้งหมด (แต่เฉพาะกุญแจสาธารณะเท่านั้น) ในสาขาหนึ่งของโครงสร้าง HD wallet ได้ ทางลัดนี้เปิดทางให้สร้างระบบที่ทำงานบนข้อมูลสาธารณะเพียงอย่างเดียว — เซิร์ฟเวอร์หรือแอปพลิเคชันสามารถมีสำเนา extended public key แต่ไม่ได้เก็บ private key ใด ๆ ไว้ การติดตั้งแบบนี้อนุญาตให้เซิร์ฟเวอร์สร้างกุญแจสาธารณะและที่อยู่บิตคอยน์ได้ไม่จำกัด ขณะเดียวกันก็ไม่สามารถใช้จ่ายเงินจากที่อยู่เหล่านั้นได้

เมื่อต้องการใช้เงินจริง ให้ย้ายกระบวนการลงนามไปยังเครื่องที่ปลอดภัยกว่า ซึ่งเก็บ extended private key หรือ private keys ไว้ เสียง่ายคือ เซิร์ฟเวอร์สาธารณะทำหน้าที่ “สร้างที่อยู่” และมอบข้อมูลให้ลูกค้า/ผู้ใช้ ส่วนการลงนามธุรกรรมทำบนอุปกรณ์ที่มีความปลอดภัยสูงกว่า

การประยุกต์ใช้งานทั่วไปของแนวทางนี้คือการติดตั้ง extended public key บนเว็บเซิร์ฟเวอร์ของระบบอีคอมเมิร์ซ เว็บเซิร์ฟเวอร์สามารถสร้างที่อยู่บิตคอยน์ใหม่สำหรับแต่ละคำสั่งซื้อหรือแต่ละตะกร้าสินค้าได้ทันที โดยไม่ต้องเก็บ private key ไว้บนเซิร์ฟเวอร์ที่เสี่ยงต่อการถูกโจมตี หากไม่มี HD wallet ตัวเลือกเดียวที่มีจะเป็นการสร้างที่อยู่จำนวนมากล่วงหน้าในเซิร์ฟเวอร์แยกที่ปลอดภัย แล้วคอยโหลดเข้ามาใช้งาน ซึ่งยุ่งยากและต้องดูแลสต็อกที่อยู่ให้เพียงพออยู่ตลอดเวลา

ระวังช่องว่าง (Mind the Gap)

Extended public key สามารถสร้างกุญแจลูกได้โดยตรงมากถึงประมาณ 4 พันล้านกุญแจ ซึ่งถือว่าเกินพอสำหรับการใช้งานในร้านค้าหรือแอปพลิเคชันใด ๆ อยู่แล้ว อย่างไรก็ตาม การให้ wallet สร้างกุญแจทั้ง 4 พันล้านดอกและสแกนบล็อกเชนทั้งหมดเพื่อหาธุรกรรมที่เกี่ยวข้องนั้นแทบจะเป็นไปไม่ได้ในทางปฏิบัติ เนื่องจากจะใช้เวลามหาศาล ด้วยเหตุนี้ wallet ส่วนใหญ่จึงเลือกสร้างกุญแจเพียงไม่กี่ดอกในแต่ละครั้ง สแกนหาธุรกรรมที่ตรงกับกุญแจเหล่านั้น และเมื่อกุญแจที่สร้างไปก่อนหน้านี้ถูกใช้งานแล้ว จึงสร้างกุญแจใหม่ต่อไปตามลำดับ

ตัวอย่างเช่น wallet ของ Alice อาจสร้างกุญแจขึ้นมา 100 ดอก เมื่อพบว่ามีการชำระเงินไปยังกุญแจแรก มันก็จะสร้างกุญแจดอกที่ 101 ต่อทันที

บางครั้งอาจมีกรณีที่ wallet แจกกุญแจให้กับใครบางคน แต่ภายหลังคู่สัญญากลับไม่ทำการชำระเงิน ทำให้เกิด “ช่องว่าง” (gap) ในสายกุญแจ ซึ่งโดยทั่วไปไม่ถือว่าเป็นปัญหา ตราบใดที่ wallet ยังคงสร้างกุญแจถัดไปหลังช่องว่างนั้นต่อไป กระบวนการสแกนก็จะยังคงค้นพบธุรกรรมได้ในอนาคต การกำหนดจำนวนกุญแจที่สามารถสร้างไว้ล่วงหน้าโดยยังไม่ถูกใช้งาน และต่อเนื่องกันได้สูงสุดโดยไม่ก่อให้เกิดปัญหา เรียกว่า gap limit

เมื่อ wallet สร้างกุญแจจนถึงขีดจำกัด gap limit แล้ว แต่ไม่มีธุรกรรมเข้ามาที่กุญแจเหล่านั้น มันจะต้องเลือกวิธีรับมือเมื่อมีการขอกุญแจใหม่ในอนาคต ซึ่งมีอยู่ 3 แนวทางหลักคือ:

  • ปฏิเสธการสร้างกุญแจใหม่ – ทำให้ไม่สามารถรับการชำระเงินได้อีก วิธีนี้แม้ง่ายที่สุด แต่ก็เป็นตัวเลือกที่ไม่เหมาะสมที่สุด
  • สร้างกุญแจใหม่เกินกว่า gap limit – วิธีนี้รับประกันว่าทุกการชำระเงินจะได้ที่อยู่ใหม่ ไม่เกิดการใช้ที่อยู่ซ้ำ และเพิ่มความเป็นส่วนตัว อย่างไรก็ตาม หากต้องกู้ wallet จาก recovery code หรือหากนำ extended public key เดียวกันไปใช้กับซอฟต์แวร์อื่น ซอฟต์แวร์เหล่านั้นจะไม่สามารถเห็นการชำระเงินที่เกิดขึ้นหลังจากเกิน gap limit ได้
  • แจกจ่ายกุญแจเก่าซ้ำ – ช่วยให้การกู้คืน wallet เป็นไปอย่างราบรื่น แต่แลกมาด้วยการลดทอนความเป็นส่วนตัวของเจ้าของกระเป๋าและคู่ธุรกรรม

ระบบโอเพ่นซอร์สสำหรับร้านค้าออนไลน์ เช่น BTCPay Server แก้ปัญหานี้โดยการใช้ gap limit ที่มีค่ามหาศาล และจำกัดอัตราการสร้างใบแจ้งหนี้ (invoice) ขณะเดียวกันก็มีวิธีแก้ปัญหาเชิงแนวคิดอื่น ๆ ถูกเสนอขึ้นมา เช่น ให้ wallet ของผู้จ่ายสร้างธุรกรรมชั่วคราว (แต่ยังไม่กระจายสู่เครือข่าย) ไปยังที่อยู่ซ้ำก่อนที่จะได้รับที่อยู่ใหม่สำหรับธุรกรรมจริง อย่างไรก็ตาม วิธีเหล่านี้ยังไม่ถูกนำมาใช้จริงในระบบการผลิต ณ เวลาที่เขียนนี้

การใช้งานที่พบบ่อยอีกแบบหนึ่งคือ cold storage หรือ hardware signing device โดยในสถานการณ์นี้ extended private key จะถูกเก็บไว้อย่างปลอดภัยแบบออฟไลน์ เช่น บนกระดาษหรือบนอุปกรณ์ฮาร์ดแวร์ ในขณะที่ extended public key ถูกเก็บไว้ในระบบออนไลน์ ผู้ใช้จึงสามารถสร้างที่อยู่สำหรับการ “รับเงิน” ได้เรื่อย ๆ โดยไม่ต้องเสี่ยงเปิดเผย private key และเมื่อถึงเวลาที่ต้องใช้จ่ายเงิน ก็สามารถนำ extended private key มาสร้างและลงนามธุรกรรมบนซอฟต์แวร์ออฟไลน์หรืออุปกรณ์ฮาร์ดแวร์ได้โดยตรง

แผนภาพ “Extending a parent public key to create a child public key” จะแสดงให้เห็นกลไกการขยายกุญแจสาธารณะหลักเพื่อสร้างกุญแจสาธารณะลูกตามแนวคิดที่กล่าวมานี้ image

การใช้ Extended Public Key บนร้านค้าออนไลน์

มาดูกันว่า HD wallet ถูกนำไปใช้งานจริงอย่างไร ผ่านตัวอย่างร้านค้าออนไลน์ของ Gabriel

Gabriel เริ่มต้นทำร้านค้าออนไลน์เล็ก ๆ ของเขาเป็นงานอดิเรก โดยใช้ WordPress โฮสต์เองแบบง่าย ๆ ร้านค้ามีเพียงไม่กี่หน้าและฟอร์มสั่งซื้อที่ระบุที่อยู่บิตคอยน์เพียงหนึ่งเดียวสำหรับการชำระเงิน เขาใช้ที่อยู่บิตคอยน์แรกที่สร้างขึ้นจากกระเป๋าเงินส่วนตัวเป็นที่อยู่หลัก ลูกค้าส่งคำสั่งซื้อและโอนเงินไปยังที่อยู่นี้ ระบบจะส่งอีเมลแจ้งคำสั่งซื้อเพื่อให้ Gabriel ดำเนินการต่อ สำหรับคำสั่งซื้อเพียงไม่กี่ครั้งต่อสัปดาห์ วิธีนี้ก็ถือว่าเพียงพอ แม้ว่าจะมีข้อเสียด้านความเป็นส่วนตัวทั้งสำหรับ Gabriel เอง ลูกค้า และผู้ที่เขาส่งเงินต่อให้ก็ตาม

แต่เมื่อเวลาผ่านไป ร้านค้าเล็ก ๆ ของ Gabriel กลับได้รับความนิยมมากขึ้น คำสั่งซื้อหลั่งไหลเข้ามาจากลูกค้าในชุมชนท้องถิ่นจนเขาเริ่มจัดการไม่ทัน ปัญหาหลักคือคำสั่งซื้อทั้งหมดถูกส่งไปยังที่อยู่เดียวกัน ทำให้ยากต่อการจับคู่ธุรกรรมกับคำสั่งซื้อได้อย่างถูกต้อง โดยเฉพาะเมื่อมีหลายคำสั่งที่มียอดเงินเท่ากันเข้ามาในช่วงเวลาใกล้กัน อีกทั้งในธุรกรรมบิตคอยน์เอง ผู้รับสามารถระบุได้เพียงจำนวนเงินและที่อยู่ปลายทางเท่านั้น ไม่มีช่องสำหรับบันทึกหมายเลขใบแจ้งหนี้หรือข้อความอธิบายเพิ่มเติม

ทางออกของปัญหานี้มาจากการใช้ HD wallet ซึ่งสามารถสร้างกุญแจสาธารณะลูกจาก extended public key (xpub) โดยไม่ต้องใช้ private key Gabriel จึงสามารถนำ xpub ไปติดตั้งไว้บนเว็บไซต์ของร้านค้า และใช้สร้างที่อยู่ใหม่ที่ไม่ซ้ำสำหรับคำสั่งซื้อแต่ละรายการ วิธีนี้ไม่เพียงช่วยให้การจับคู่ธุรกรรมกับคำสั่งซื้อเป็นไปอย่างแม่นยำ แต่ยังช่วยเพิ่มความเป็นส่วนตัวและความปลอดภัย เนื่องจากแต่ละคำสั่งซื้อจะมีที่อยู่เฉพาะของตัวเอง

ข้อดีอีกอย่างคือ HD wallet ทำให้ Gabriel ยังคงควบคุมการใช้จ่ายเงินได้จากกระเป๋าส่วนตัวของเขา ขณะที่เว็บไซต์มีเพียง xpub ที่ใช้สร้างที่อยู่รับเงินได้เท่านั้น เว็บไซต์ไม่เก็บ private key ใด ๆ เลย หากวันหนึ่งถูกเจาะระบบ สิ่งที่คนร้ายอาจได้ไปก็มีเพียงที่อยู่ที่จะใช้รับเงินในอนาคต ไม่ใช่กุญแจที่สามารถเข้าถึงเงินที่ Gabriel ได้รับไปแล้ว

เพื่อส่งออก xpub จากอุปกรณ์เซ็นธุรกรรม Trezor ของเขา Gabriel ใช้แอปกระเป๋าเงิน Trezor เวอร์ชันเว็บ ซึ่งต้องเชื่อมต่อกับอุปกรณ์ก่อนจึงจะสามารถส่งออกกุญแจสาธารณะได้ ที่สำคัญ อุปกรณ์เซ็นธุรกรรมส่วนใหญ่จะไม่ส่งออก private key เลย Private key จะถูกเก็บอยู่บนอุปกรณ์เท่านั้น Gabriel จึงมั่นใจได้ว่าเงินของเขายังคงปลอดภัย

หลังจากนั้น เขาคัดลอก xpub ไปยังซอฟต์แวร์สำหรับจัดการการชำระเงินบิตคอยน์ของร้านค้า เช่น BTCPay Server ซึ่งเป็นโอเพ่นซอร์สที่ได้รับความนิยมอย่างมาก และสามารถสร้างระบบชำระเงินที่ยืดหยุ่นและปลอดภัยสำหรับธุรกิจของเขาได้ทันที

การสร้างอนุพันธ์กุญแจลูกแบบเสริมความแข็งแกร่ง

ความสามารถในการสร้างกิ่งกุญแจสาธารณะจาก xpub นั้นมีประโยชน์อย่างมาก แต่ก็แฝงไปด้วยความเสี่ยงบางประการ การเข้าถึง xpub โดยตรงไม่สามารถทำให้ได้ private key ตัวลูก แต่อย่างไรก็ตาม เนื่องจาก xpub มี chain code อยู่ด้วย หาก private key ตัวใดตัวหนึ่งรั่วไหลหรือถูกเปิดเผยขึ้นมา มันสามารถถูกนำมาใช้ร่วมกับ chain code เพื่อสร้าง private key ลูกตัวอื่น ๆ ได้ทั้งหมด กล่าวคือ เพียงแค่ private key ตัวลูกที่รั่วไหลหนึ่งตัว บวกกับ chain code ของตัวแม่ ก็เพียงพอที่จะเปิดเผย private key ตัวลูกทั้งหมด ยิ่งไปกว่านั้น เมื่อ private key ตัวลูก รวมกับ chain code ของแม่ ยังสามารถถูกใช้เพื่อคำนวณหา private key ตัวแม่ได้อีกด้วย

เพื่อป้องกันความเสี่ยงนี้ HD wallet จึงมีอีกหนึ่งกลไกที่เรียกว่า hardened derivation ซึ่งทำหน้าที่ตัดความสัมพันธ์ระหว่าง public key ตัวแม่กับ chain code ของลูกออกไป ฟังก์ชัน hardened derivation จะใช้ private key ตัวแม่ในการสร้าง chaincode ของตัวลูกแทนการใช้ public key ของตัวแม่ วิธีนี้เปรียบเสมือนการสร้าง “ไฟร์วอลล์” ในสายลำดับแม่/ลูก ทำให้ chain code ที่ได้ไม่สามารถนำไปใช้เพื่อเจาะหา private key อื่น ๆ ได้อีกต่อไป

ฟังก์ชัน hardened derivation ดูคล้ายกับฟังก์ชันการสร้างกุญแจลูกแบบปกติ เพียงแต่มันใช้ private key แม่เป็น input ของ hash function แทน public key ดังที่แสดงในแผนภาพข้างล่าง

image

เมื่อใช้ฟังก์ชัน hardened derivation ผลลัพธ์ที่เกิดทั้ง private key และ chain code ของตัวลูกจะต่างไปโดยสิ้นเชิงจากสิ่งที่จะได้จากการอนุพันธ์แบบปกติ กิ่งที่ได้ด้วยวิธีนี้สามารถนำไปสร้างเป็น extended public keys ได้โดยที่ความปลอดภัยไม่ถูกทำลาย เพราะ chain code ของกิ่งเหล่านั้นไม่สามารถนำไปใช้เปิดเผย private key ใด ๆ ในกิ่งอื่น ๆ ได้ การอนุพันธ์แบบ hardened จึงทำหน้าที่สร้าง “ช่องกั้น” (firewall) ในโครงสร้างต้นไม้ เหนือระดับที่มีการเผยแพร่ extended public keys

สรุปง่าย ๆ คือ หากคุณต้องการใช้ความสะดวกของ xpub เพื่อสร้าง public key หลาย ๆ ดอก โดยไม่เสี่ยงให้ตัวเองถูกเจาะจากการรั่วของ chain code ควรแยกสาขานั้นมาจากกุญแจพ่อแม่ที่สร้างด้วย hardened derivation แทนการใช้กุญแจพ่อแม่แบบปกติ โดยเป็นแนวปฏิบัติที่ดีที่สุดที่ลูกระดับแรก (level 1) ของกุญแจมาสเตอร์จะถูกสร้างด้วย hardened derivation เสมอ เพื่อป้องกันการถูกเจาะของกุญแจมาสเตอร์

หมายเลขดัชนีสำหรับการแตกกุญแจแบบปกติและแบบ hardened

หมายเลขดัชนีที่ใช้ในการอนุพันธ์กุญแจเป็นจำนวนเต็มขนาด 32 บิต เพื่อแยกความแตกต่างระหว่างการอนุพันธ์แบบปกติกับแบบ hardened หมายเลขดัชนีช่วง 0 ถึง 2³¹−1 (0x00000000 ถึง 0x7FFFFFFF) จะใช้สำหรับการอนุพันธ์แบบปกติ ส่วนหมายเลขดัชนีช่วง 2³¹ ถึง 2³²−1 (0x80000000 ถึง 0xFFFFFFFF) จะใช้สำหรับการอนุพันธ์แบบ hardened ดังนั้น หากค่าดัชนีต่ำกว่า 2³¹ กุญแจลูกจะเป็นแบบปกติ แต่ถ้าค่าเท่าหรือมากกว่า 2³¹ กุญแจลูกจะเป็นแบบ hardened

เพื่อให้อ่านและแสดงดัชนีได้สะดวกกว่า ค่าดัชนีของกุญแจ hardened มักจะแสดงด้วยตัวเลขเริ่มจากศูนย์ผนวกเครื่องหมาย prime (′) แทนค่าแบบไบนารี่ ตัวอย่างเช่น กุญแจลูกปกติแรกจะแสดงเป็น 0 ในขณะที่กุญแจลูก hardened แรก (ดัชนี 0x80000000) จะแสดงเป็น 0′ กุญแจ hardened ตัวถัดมาจะเป็น 1′ ซึ่งตามนิยาม i′ หมายถึงค่า 2³¹ + i ในการเขียนแบบ ASCII ปกติ เครื่องหมาย prime มักใช้เป็นอัปอสโทรฟเดี่ยว (') หรือในบริบทที่อัปอสโทรฟมีความหมายพิเศษ อาจใช้ตัวอักษร h แทน (เช่น 0h, 1h) ซึ่งเป็นรูปแบบที่มักแนะนำสำหรับการนำไปใช้ใน shell หรือใน output script descriptors.

ตัวระบุคีย์ใน HD wallet (path)

คีย์ใน HD wallet จะถูกระบุด้วยรูปแบบ path ซึ่งแยกระดับชั้นของต้นไม้ด้วยเครื่องหมายทับ (/) แต่ละระดับระบุการอนุพันธ์หนึ่งขั้น private key ที่อนุพันธ์มาจาก master private key จะขึ้นต้นด้วย m ในขณะที่ public key ที่อนุพันธ์มาจาก master public key จะขึ้นต้นด้วย M ตัวอย่างเช่น private key ลูกดอกแรกของ master private key จะเป็น m/0 และ public key ลูกดอกแรก จะเป็น M/0 และหลานลำดับที่สองของ Master private key ก็จะเป็น m/0/1 ไปเรื่อย ๆ

การอ่าน “ลำดับชั้น” ของ path ทำได้โดยอ่านจากซ้ายไปขวาโดยเริ่มจาก master key ไปยังกิ่งที่ลึกขึ้น เช่น ตัวระบุ m/x/y/z หมายความว่ากุญแจนี้เป็นกุญแจลูกลำดับที่ z ของกุญแจ m/x/y ซึ่งเป็นลูกลำดับที่ y ของกุญแจ m/x ซึ่งเป็นลูกลำดับที่ x ของ m — กล่าวคือ path แต่ละระดับบอกขั้นตอนการอนุพันธ์ที่ต่อเนื่องจาก master ลงไปยังกุญแจปัจจุบัน

| HD path | คีย์ที่อธิบาย | | ----- | ----- | | m/0 | กุญแจส่วนตัวลูกตัวแรก (0) จาก master private key (m) | | m/0/0 | กุญแจส่วนตัวหลานตัวแรกจากลูกตัวแรก (m/0) | | m/0'/0 | กุญแจส่วนตัวหลานปกติ (normal grandchild) ตัวแรกจากลูกแบบ hardened ตัวแรก (m/0') | | m/1/0 | กุญแจส่วนตัวหลานตัวแรกจากลูกตัวที่สอง (m/1) | | M/23/17/0/0 | กุญแจสาธารณะเหลนเหลน (great-great-grandchild) ตัวแรกจากเหลนตัวแรก (first great-grandchild) จากหลานตัวที่ 18 (18th grandchild) จากลูกตัวที่ 24 (24th child) |

การใช้งานเส้นทางในโครงสร้างต้นไม้ของกระเป๋าเงินแบบ HD

โครงสร้างต้นไม้ของ HD wallet มอบความยืดหยุ่นอย่างมาก แต่ละกุญแจขยายที่เป็นพ่อแม่สามารถมีลูกได้ 4 พันล้านกุญแจ: 2 พันล้านกุญแจปกติ และ 2 พันล้านกุญแจ hardened ลูกแต่ละกุญแจเหล่านั้นสามารถมีลูกอีก 4 พันล้านกุญแจ และต่อไปได้เรื่อย ๆ ต้นไม้สามารถลึกได้เท่าที่คุณต้องการ โดยมีจำนวนรุ่นไม่สิ้นสุด อย่างไรก็ตาม ด้วยความยืดหยุ่นทั้งหมดนั้น มันจึงกลายเป็นเรื่องที่ค่อนข้างยากที่จะใช้งานเส้นทางในต้นไม้ที่ไม่สิ้นสุดนี้ โดยเฉพาะอย่างยิ่งเมื่อมีการถ่ายโอน HD wallet ระหว่างการนำไปใช้งานต่าง ๆ เนื่องจากความเป็นไปได้สำหรับการจัดระเบียบภายในไปสู่กิ่งและกิ่งย่อยนั้นมีอยู่อย่างไม่จำกัด

สอง BIP นำเสนอโซลูชันสำหรับความซับซ้อนนี้ โดยการสร้างมาตรฐานที่เสนอไว้บางอย่างสำหรับโครงสร้างของต้นไม้ HD wallet BIP43 เสนอการใช้ hardened child index ตัวแรกเป็นตัวระบุพิเศษที่บ่งบอกถึง “วัตถุประสงค์” ของโครงสร้างต้นไม้ ตามที่ BIP43 กล่าวไว้ HD wallet ควรใช้เพียงกิ่งระดับ 1 ของต้นไม้ โดยหมายเลข index จะบ่งบอกถึงโครงสร้างและ namespace ของต้นไม้ที่เหลือโดยการกำหนดวัตถุประสงค์ ตัวอย่างเช่น HD wallet ที่ใช้เพียงกิ่ง m/i' มีเจตนาที่จะบ่งบอกถึงวัตถุประสงค์เฉพาะ และวัตถุประสงค์นั้นถูกระบุด้วยหมายเลข index “i”

โดยการขยายข้อกำหนดนั้น BIP44 เสนอ multiaccount structure เป็น “วัตถุประสงค์” หมายเลข 44' ภายใต้ BIP43 HD wallet ทั้งหมดที่ปฏิบัติตามโครงสร้าง BIP44 จะถูกระบุโดยข้อเท็จจริงที่ว่าพวกมันใช้เพียงกิ่งเดียวของต้นไม้: m/44'

BIP44 กำหนดโครงสร้างว่า ประกอบด้วยห้าระดับของต้นไม้ที่ถูกกำหนดไว้ล่วงหน้า:

m / purpose' / coin_type' / account' / change / address_index

ระดับแรก “purpose” จะถูกตั้งค่าเป็น 44’ เสมอ ระดับที่สอง “coin_type” ระบุชนิดของเหรียญ cryptocurrency โดยอนุญาตให้มี multicurrency HD wallets ที่แต่ละสกุลเงินมี subtree ของตัวเองภายใต้ระดับที่สอง Bitcoin คือ m/44’/0’ และ Bitcoin Testnet คือ m/44’/1’

ระดับที่สามของต้นไม้คือ “account” ซึ่งอนุญาตให้ผู้ใช้แบ่งย่อยกระเป๋าของพวกเขาออกเป็น subaccount เชิงตรรกะแยกกันเพื่อการบัญชีหรือวัตถุประสงค์ด้านการจัดการ ตัวอย่างเช่น HD wallet อาจมีสอง “account” ของ Bitcoin: m/44’/0’/0’ และ m/44’/0’/1’ แต่ละ account เป็นรากของ subtree ของมันเอง

ในระดับที่สี่ “change” HD wallet มีสอง subtree หนึ่งสำหรับการสร้าง receiving address และอีกหนึ่งสำหรับการสร้าง change address โปรดทราบว่าในขณะที่ระดับก่อนหน้านี้ใช้ hardened derivation แต่ระดับนี้ใช้ normal derivation นี่เป็นการอนุญาตให้ระดับนี้ของต้นไม้สามารถส่งออก extended public keys เพื่อใช้ในสภาพแวดล้อมที่ไม่ปลอดภัยได้ ที่อยู่ที่สามารถใช้งานได้ถูกสร้างขึ้นโดย HD wallet ในฐานะลูกของระดับที่สี่ ทำให้ระดับที่ห้าของต้นไม้คือ “address_index” ตัวอย่างเช่น receiving address ที่สามสำหรับการชำระเงินใน account หลักจะเป็น M/44’/0’/0’/0/2 ตารางข้างล่างจะแสดงตัวอย่างเพิ่มเติมอีกเล็กน้อย

| HD path | คำอธิบายคีย์ | | ----- | ----- | | M/44'/0'/0'/0/2 | กุญแจสาธารณะสำหรับรับเงินตัวที่สามของบัญชี Bitcoin หลัก | | M/44'/0'/3'/1/14 | กุญแจสาธารณะสำหรับที่อยู่ทอน (change-address) ตัวที่สิบห้าของบัญชี Bitcoin ที่สี่ | | m/44'/2'/0'/0/1 | กุญแจส่วนตัวที่สองในบัญชีหลักของ Litecoin สำหรับใช้ลงลายเซ็นธุรกรรม |

หลายคนมุ่งเน้นไปที่การปกป้องบิตคอยน์ของตนจากการขโมยและการโจมตีรูปแบบต่าง ๆ แต่หนึ่งในสาเหตุสำคัญของการสูญเสียบิตคอยน์—ซึ่งอาจเป็นสาเหตุหลักเลยก็ว่าได้—ก็คือการสูญหายของข้อมูล หากกุญแจและข้อมูลสำคัญอื่น ๆ ที่จำเป็นต่อการใช้จ่ายบิตคอยน์ของคุณสูญหายไป บิตคอยน์เหล่านั้นก็จะไม่สามารถถูกใช้จ่ายได้อีกต่อไป และไม่มีใครสามารถกู้คืนให้คุณได้ ในบทนี้ เราได้พิจารณาระบบที่กระเป๋าเงินสมัยใหม่ใช้เพื่อช่วยป้องกันไม่ให้คุณสูญเสียข้อมูลนั้น แต่อย่าลืมว่า การใช้งานระบบที่มีอยู่เพื่อสร้างการสำรองข้อมูลที่ดีและทดสอบอย่างสม่ำเสมอนั้น ขึ้นอยู่กับคุณเอง

Replies (0)

No replies yet. Be the first to leave a comment!