Hash Function คืออะไร?

hash-function-cover-photo
01-hash function

Hash Function (ฟังก์ชั่น Hash) คืออะไร?

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

เรื่องเจ๋งๆ ของฟังก์ชั่น Hash ก็คือ 

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

ในทางกลับกัน ฟังก์ชั่น Hash จะให้คุณสร้างรอยนิ้วมือดิจิทัล (Digital Fingerprint) สำหรับข้อมูลใดๆ ก็ตามที่คุณใส่เข้าไป 

คุณสมบัติของ Hash Function

ข้อดีของฟังก์ชั่น Hash ก็คือคุณสมบัติ 3 ประการที่ทำให้มันมีประโยชน์อย่างมาก 

หมายเหตุ ฟังก์ชั่น Hash SHA256 เป็นตัวหลักที่ใช้บนเครือข่าย Bitcoin เพราะฉะนั้นฉันจะใช้มันในตัวอย่างต่อไป

1. คุณไม่สามารถหาข้อมูลดั้งเดิมได้จากผลลัพธ์

Hash Function ของวิทยาการเข้ารหัส (Cryptography) สร้างผลลัพธ์แบบสุ่มขึ้นมา (โดยที่ไม่มีรูปแบบตายตัว) เพราะฉะนั้นคุณจึงไม่สามารถ “ย้อนกลับข้อมูล” ผ่านฟังก์ชั่น Hash เพื่อที่จะค้นหาว่าข้อมูลดั้งเดิมคืออะไร

02-random
2. ข้อมูลเดิมมักจะกลับมาเป็นผลลัพธ์เดิมเสมอ

ฟังก์ชั่น Hash จะรวบรวมข้อมูลอย่างเป็นระบบ เพราะฉะนั้นหากมีการป้อนข้อมูลเดียวกันเข้าไป ผลลัพธ์ก็จะออกมาเหมือนเดิมเสมอ

03-hash-function-cogs

ตัวอย่าง:

data                sha256(data)
---------------     ----------------------------------------------------------------
bitcointhailand     8f437fdf2ab2b29d97bfc5a96b1fa675e3c09e66024e7c7eb1f1325a56f95f2e
bitcointhailand     8f437fdf2ab2b29d97bfc5a96b1fa675e3c09e66024e7c7eb1f1325a56f95f2e
bitcointhailand     8f437fdf2ab2b29d97bfc5a96b1fa675e3c09e66024e7c7eb1f1325a56f95f2e
3. ข้อมูลที่แตกต่างกันจะสร้างผลลัพธ์ที่ไม่เหมือนกัน

หากคุณใส่ข้อมูลที่แตกต่างกันเข้าไปในฟังก์ชั่น Hash ทางฟังก์ชั่น Hash จะมอบผลลัพธ์ที่แตกต่างกันเช่นกัน 

ไม่ว่าความแตกต่างนั้นจะเล็กน้อยแค่ไหน ข้อมูลที่กลับมาก็จะมีผลลัพธ์ที่แตกต่างกันไปอยู่ดี

ตัวอย่าง:

data                sha256(data)
---------------     ----------------------------------------------------------------
bitcointhailand     8f437fdf2ab2b29d97bfc5a96b1fa675e3c09e66024e7c7eb1f1325a56f95f2e
bitcointhailand1    406c96725d2442b04e1c479d16974724e3ec6192cca5f3e10c3e542c940e953e
bitcointhailand2    b769dc2058a86352f3701e3f0fab3a641a671b01a8e2b058f4ce8c406e74c92f
bitcointhailand2 5737aed925b9d05ea62153bf402119e63729d9b8dea77038096afac8eb02a0e1

Bitcoin ใช้ฟังก์ชั่น Hash ที่ไหน?

1. เลข Hash ของรายการธุรกรรม (Transaction Hashes)

คุณสามารถ Hash ข้อมูลรายการธุรกรรมเพื่อที่จะได้รับ TXID (เลข ID ของรายการธุรกรรม Hash รายการธุรกรรม)

  • ความสามารถในการ Hash สายรายการธุรกรรมที่มีความยาวให้สั้นลงได้ สายข้อมูลที่ไม่เหมือนกันจะทำให้คุณสามารถสร้างเครื่องมือระบุตัวตนของรายการธุรกรรมแต่ละรายการได้

2. เลข Hash ของบล็อก (และการขุด) (Block Hashes)

คุณสามารถ Hash หัวบล็อก (Block Header) เพื่อที่จะได้รับ Hash บล็อก

  • เพราะฉะนั้น คุณจึงสามารถสร้าง ID ที่มีความแตกต่างกันสำหรับแต่ละบล็อกได้ 
  • ผลลัพธ์เลข Hash จะเป็นแบบสุ่มเพราะฉะนั้นจึงสามารถใช้กลไกการขุดในการทำงานได้

3. บัญชีผู้ใช้งาน (Address)

Public Key ถูก Hash (ใช้ทั้ง SHA256 และ RIPEMD160) ในการดำเนินการสร้างบัญชีผู้ใช้งาน Bitcoin ( bitcoin address )

  • ด้วยความที่คุณไม่อาจจะถอยกลับกระบวนการโดยใช้ผลลัพธ์ที่ได้จากการ Hash ได้ จึงทำให้ public key ที่ถูกวางเอาไว้ข้างในสคริปต์ล็อก (Locking scripts) มีความปลอดภัยสูง 
  •  RIPEMD-160 ทำการย่อยข้อมูลที่สั้นกว่าความยาวของ public key ซึ่งจะลดความยาวของผลลัพธ์ของบัญชีผู้ใช้งาน

คุณจะ Hash ข้อมูลบนเครือข่าย Bitcoin ได้อย่างไร?

มีวิธีหลักอยู่ 2 วิธีในการ Hash ข้อมูลบนเครือข่าย Bitcoin และแต่ละวิธีก็มีชื่อเรียกดังต่อไปนี้:

  1. Hash256 – SHA-256 สองครั้ง
  2. Hash160  – SHA-256 และตามด้วย by RIPEMD-160

1. Hash256

นี้เป็นการใส่ข้อมูลผ่านฟังก์ชั่น Hash SHA-256 จากนั้นก็เอาผลลัพธ์ใส่เข้าไปใน  SHA-256 อีกครั้ง หรือจะเรียกว่า SHA-256 สองครั้ง แต่เราจะเรียกสั้นๆ ว่า Hash256

นี้คือวิธีที่ได้รับความนิยมที่สุดสำหรับการ Hash ข้อมูลบนเครือข่าย Bitcoin มักจะถูกใช้งานในการ Hash ข้อมูลรายการธุรกรรมเพื่อที่จะสร้าง TXIDS และจากนั้นก็ Hash หัวบล็อก (Block Header) ระหว่างการขุด

Ruby

require 'digest'

def hash256(hex)
  # convert hexadecimal string to byte sequence first
  binary = [hex].pack("H*") # H = hex string (highest byte first), * = multiple bytes
  
  # SHA-256 (first round)
  hash1 = Digest::SHA256.digest(binary)
  
  # SHA-256 (second round)
  hash2 = Digest::SHA256.digest(hash1)
  
  # convert from byte sequence back to hexadecimal
  hash256 = hash2.unpack("H*")[0]
  
  return hash256
end

puts hash256("aa") #=> e51600d48d2f72eb428e78733e01fbd6081b349528335bf21269362edfae185d

2. Hash160

นี้เป็นการใส่ข้อมูลผ่านฟังก์ชั่น Hash SHA-256 จากนั้นก็เอาผลลัพธ์ใส่เข้าไปในฟังก์ชั่น Hash RIPEMD-160 เราจะเรียกสั้นๆ ว่า Hash160

RIPEMD-160 ทำการย่อยเลข Hash ให้สั้นกว่า (160 บิต/ 20 ไบต์) เมื่อเปรียบเทียบกับ SHA-256 (256 บิต/ 32 ไบต์) เพราะฉะนั้นจึงมักถูกใช้งานเมื่อคุณต้องการจะสร้างเลข Hash ที่สั้นกว่าที่คุณจะได้รับหากใช้ Hash256

มักจะถูกใช้เมื่อต้องการทำให้ Public Keys และสคริปต์ให้สั้นลงในการดำเนินการสร้างบัญชีผู้ใช้งานทรัพย์สิน  addresses  (ยกตัวอย่างเช่น บัญชีผู้ใช้งานที่เริ่มต้นด้วย  1 หรือ 3 ) มันจะไม่ถูกใช้ในการพัฒนาเร็วๆ นี้ที่ต้องการการ Hash ข้อมูลบนเครือข่าย Bitcoin

Ruby

require 'digest'

def hash160(data)
  # convert hexadecimal string to byte sequence first
  binary = [data].pack("H*") # H = hex string (highest byte first), * = multiple bytes
  
  # SHA-256
  sha256 = Digest::SHA256.digest(binary)
  
  # RIPEMD-160
  ripemd160 = Digest::RMD160.digest(sha256)
  
  # convert from byte sequence back to hexadecimal
  hash160 = ripemd160.unpack("H*").join
  
  return hash160
end

puts hash160("aa") #=> 58d179ca6112752d00dc9b89ea4f55a585195e26

ข้อผิดพลาดที่มักจะเกิดขึ้นเมื่อทำการ Hash

ข้อผิดพลาดที่มักจะเกิดขึ้นเมื่อทำการ Hash บนเครือข่าย Bitcoin ก็คือการใส่เส้นข้อมูล (String) เข้าไปในฟังก์ชั่น Hash และไม่มีการอ้างอิงลำดับไบต์ (byte sequences) ที่เส้นข้อมูลเหล่านั้นแสดงถึง 

ยกตัวอย่างเช่น หากเรามีเส้นข้อมูลเลขฐานสิบหก

ถ้าเราใส่เส้นข้อมูลนี้เข้าไปตรงๆ ในฟังก์ชั่น Hash ภาษาโปรแกรมคอมพิวเตอร์ของคุณจะส่ง ASCII encoding ของตัวอักษรแต่ละตัวเข้าไปในฟังก์ชั่น Hash ซึ่งจะดูเหมือนเลขระบบฐานสองนี้

แต่สิ่งที่เราต้องการจะส่งเข้าไปในฟังก์ชั่น Hash จริงๆ ก็คือไบต์ที่เส้นข้อมูลเลขฐานสิบหกนี้อ้างถึง ซึ่งจะดูเหมือนเลขระบบฐานสองนี้

นี้คือสาเหตุว่าทำไมเราจึงจำเป็นต้องใส่เส้นข้อมูลเลขฐานสิบหกเข้าไปในไบต์ก่อนที่จะทำการ Hash 

ภาษาโปรแกรมคอมพิวเตอร์ส่วนใหญ่จะมีฟังก์ชั่นที่ให้คุณทำสิ่งนี้:

Ruby

hex = "ab"
binary = [hex].pack("H*") # H = hex string (highest byte first), * = multiple bytes

PHP

$hex = "ab"
$binary = pack("H*", $hex);

จำไว้ว่าฟังก์ชั่น Hash นั้นจะใช้ข้อมูลเลขฐานสองเป็นข้อมูลที่จะทำการป้อนเข้าไปในระบบ เพราะฉะนั้นเราจึงจะต้องจำกัดข้อมูลเลขฐานสองที่เราต้องการจะใส่เข้าไป

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

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

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

Source: learnmeabitcoin.com/technical/hash-function