การคำนวณ CRC Checksum ง่ายแค่ไหน (CRC32 - CRC16 - CRC8)

สารบัญ:

การคำนวณ CRC Checksum ง่ายแค่ไหน (CRC32 - CRC16 - CRC8)
การคำนวณ CRC Checksum ง่ายแค่ไหน (CRC32 - CRC16 - CRC8)

วีดีโอ: การคำนวณ CRC Checksum ง่ายแค่ไหน (CRC32 - CRC16 - CRC8)

วีดีโอ: การคำนวณ CRC Checksum ง่ายแค่ไหน (CRC32 - CRC16 - CRC8)
วีดีโอ: Cyclic Redundancy Check(CRC) example 2024, เมษายน
Anonim

มีตัวเลือกมากมายสำหรับการคำนวณเช็คซัม CRC บนอินเทอร์เน็ต แต่เช็คซัมคืออะไรและทำไมจึงคำนวณด้วยวิธีนี้? ลองคิดออก

การคำนวณ CRC checksum ง่ายแค่ไหน (CRC32 - CRC16 - CRC8)
การคำนวณ CRC checksum ง่ายแค่ไหน (CRC32 - CRC16 - CRC8)

คำแนะนำ

ขั้นตอนที่ 1

ก่อนอื่น มาทำความเข้าใจทฤษฎีกันสักหน่อย แล้ว CRC คืออะไรกันแน่? กล่าวโดยสรุป นี่เป็นหนึ่งในความหลากหลายของการคำนวณเช็คซัม Checksum เป็นวิธีตรวจสอบความสมบูรณ์ของข้อมูลที่ได้รับจากฝั่งผู้รับเมื่อส่งผ่านช่องทางการสื่อสาร ตัวอย่างเช่น การตรวจสอบที่ง่ายที่สุดวิธีหนึ่งคือการใช้พาริตีบิต นี่คือเมื่อบิตทั้งหมดของข้อความที่ส่งถูกสรุป และถ้าผลรวมกลายเป็นคู่ ดังนั้น 0 จะถูกเพิ่มที่ส่วนท้ายของข้อความ หากเป็นเลขคี่ ให้เท่ากับ 1 เมื่อได้รับ ผลรวมของ บิตข้อความยังถูกนับและเปรียบเทียบกับบิตพาริตีที่ได้รับ หากต่างกัน แสดงว่าเกิดข้อผิดพลาดระหว่างการส่งและข้อมูลที่ส่งผิดเพี้ยน

แต่วิธีการตรวจหาข้อผิดพลาดนี้ไม่มีข้อมูลและไม่ได้ผลเสมอไปเพราะ หากข้อความบางส่วนบิดเบี้ยว ความเท่าเทียมกันของผลรวมอาจไม่เปลี่ยนแปลง ดังนั้นจึงมีการตรวจสอบ "ขั้นสูง" อีกมากมาย รวมทั้ง CRC

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

ขั้นตอนที่ 2

ก่อนที่เราจะเริ่มคำนวณ CRC จำเป็นต้องมีทฤษฎีเพิ่มเติมเล็กน้อย

ข้อความต้นฉบับคืออะไรควรมีความชัดเจน เป็นลำดับต่อเนื่องกันของบิตที่มีความยาวตามอำเภอใจ

อะไรคือค่าคงที่ที่เราควรแบ่งข้อความต้นฉบับ? ตัวเลขนี้มีความยาวเท่าใดก็ได้ แต่โดยปกติแล้วจะใช้ทวีคูณของ 1 ไบต์ - 8, 16 และ 32 บิต นับง่ายกว่าเพราะคอมพิวเตอร์ทำงานกับไบต์ไม่ใช่บิต

ค่าคงที่ตัวหารมักจะเขียนเป็นพหุนาม (พหุนาม) ดังนี้: x ^ 8 + x ^ 2 + x ^ 1 + x ^ 0 ในที่นี้ ระดับของตัวเลข "x" หมายถึงตำแหน่งของหนึ่งบิตในตัวเลข โดยเริ่มจากศูนย์ และบิตที่สำคัญที่สุดระบุระดับของพหุนามและจะถูกละทิ้งเมื่อตีความตัวเลข นั่นคือ จำนวนที่เขียนไว้ก่อนหน้านี้ไม่มีอะไรมากไปกว่า (1) 000000111 ในเลขฐานสองหรือ 7 ในหน่วยทศนิยม ในวงเล็บ ฉันระบุตัวเลขที่มีนัยสำคัญที่สุดโดยนัยของตัวเลข

นี่เป็นอีกตัวอย่างหนึ่ง: x ^ 16 + x ^ 15 + x ^ 2 + x ^ 0 = (1) 1000000000000101 = 0x8005 = 32773

โดยปกติพหุนามมาตรฐานบางตัวจะใช้สำหรับ CRC ประเภทต่างๆ

ขั้นตอนที่ 3

คุณจะคำนวณเช็คซัมอย่างไร? มีวิธีการพื้นฐาน - การแบ่งข้อความออกเป็นพหุนาม "แบบตรง" - และการปรับเปลี่ยนเพื่อลดจำนวนการคำนวณและด้วยเหตุนี้จึงทำให้การคำนวณ CRC เร็วขึ้น เราจะดูวิธีการพื้นฐาน

โดยทั่วไป การหารจำนวนด้วยพหุนามจะดำเนินการตามอัลกอริธึมต่อไปนี้:

1) สร้างอาร์เรย์ (รีจิสเตอร์) เติมด้วยศูนย์เท่ากับความยาวเท่ากับความกว้างของพหุนาม

2) ข้อความต้นฉบับถูกเสริมด้วยศูนย์ในบิตที่มีนัยสำคัญน้อยที่สุด ในจำนวนที่เท่ากับจำนวนบิตของพหุนาม

3) บิตที่สำคัญที่สุดของข้อความถูกป้อนลงในบิตที่มีความสำคัญน้อยที่สุดของรีจิสเตอร์และหนึ่งบิตจะถูกย้ายจากบิตที่สำคัญที่สุดของรีจิสเตอร์

4) ถ้าบิตขยายเท่ากับ "1" บิตจะกลับด้าน (การดำเนินการ XOR, OR แบบเอกสิทธิ์เฉพาะบุคคล) ในบิตรีจิสเตอร์ที่สอดคล้องกับบิตในพหุนาม

5) หากยังมีบิตอยู่ในข้อความ ให้ไปที่ขั้นตอนที่ 3);

6) เมื่อบิตของข้อความทั้งหมดเข้าสู่รีจิสเตอร์และประมวลผลโดยอัลกอริธึมนี้ ส่วนที่เหลือของการหารจะยังคงอยู่ในรีจิสเตอร์ ซึ่งก็คือการตรวจสอบ CRC

รูปแสดงการแบ่งลำดับบิตดั้งเดิมด้วยตัวเลข (1) 000000111 หรือพหุนาม x ^ 8 + x ^ 2 + x ^ 1 + x ^ 0

การแสดงแผนผังของการคำนวณ CRC
การแสดงแผนผังของการคำนวณ CRC

ขั้นตอนที่ 4

เหลืออีกสองสามสัมผัส ตามที่คุณอาจสังเกตเห็น ข้อความสามารถแบ่งได้ด้วยตัวเลขใดๆ วิธีการเลือกมัน? มีพหุนามมาตรฐานจำนวนหนึ่งที่ใช้คำนวณ CRC ตัวอย่างเช่น สำหรับ CRC32 อาจเป็น 0x04C11DB7 และสำหรับ CRC16 อาจเป็น 0x8005

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

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

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

ขั้นตอนที่ 5

จากทั้งหมดข้างต้น เรามาเขียนฟังก์ชัน Basic. NET ที่คำนวณเช็คซัม CRC โดยใช้พารามิเตอร์จำนวนหนึ่งที่ฉันอธิบายไว้ข้างต้นและส่งคืนค่า CRC เป็นตัวเลขที่ไม่มีเครื่องหมาย 32 บิต

ฟังก์ชั่นที่ใช้ร่วมกันสาธารณะ GetCrc (ByVal ไบต์เป็นไบต์ (), ByVal poly As UInteger, ความกว้าง ByVal ที่เป็นตัวเลือก As Integer = 32, ByVal initReg ทางเลือก As UInteger = & HFFFFFFFFUI, ByVal ที่เป็นตัวเลือก FinalXor As UInteger = & HFFFFFFFFUI, ByVal ที่เป็นตัวเลือก Boo reverseBytes, ByVal ที่เป็นตัวเลือก reverseCrc As Boolean = True) เป็น UInteger

หรี่ widthInBytes As Integer = width / 8

'เสริมความกว้างของข้อความด้วยศูนย์ (การคำนวณเป็นไบต์):

ReDim Preserve ไบต์ (bytes. Length - 1 + widthInBytes)

'สร้างคิวบิตจากข้อความ:

Dim msgFifo เป็นคิวใหม่ (ของบูลีน) (bytes. Count * 8 - 1)

สำหรับแต่ละ b As Byte In bytes

Dim ba เป็น BitArray ใหม่ ({b})

ถ้า reverseBytes แล้ว

สำหรับ i As Integer = 0 ถึง 7

msgFifo. Enqueue (ba (i))

ถัดไป

อื่น

สำหรับ i As Integer = 7 ถึง 0 ขั้นตอน -1

msgFifo. Enqueue (ba (i))

ถัดไป

จบถ้า

ถัดไป

'สร้างคิวจากบิตเติมเริ่มต้นของการลงทะเบียน:

Dim initBytes เป็น Byte () = BitConverter. GetBytes (initReg)

Dim initBytesReversed As IEnumerable (ของ Byte) = (จาก b As Byte ใน initBytes ใช้ widthInBytes). Reverse

Dim initFifo เป็นคิวใหม่ (ของบูลีน) (ความกว้าง - 1)

สำหรับแต่ละ b เป็นไบต์ใน initBytesReversed

Dim ba เป็น BitArray ใหม่ ({b})

หากไม่ย้อนกลับ Bytes แล้ว

สำหรับ i As Integer = 0 ถึง 7

initFifo. Enqueue (ba (i))

ถัดไป

อื่น

สำหรับ i As Integer = 7 ถึง 0 ขั้นตอน -1

initFifo. Enqueue (ba (i))

ถัดไป

จบถ้า

ถัดไป

'Shift และ XOR:

Dim register As UInteger = 0 'เติม width-bit register ด้วยศูนย์

ทำในขณะที่ msgFifo. Count> 0

Dim poppedBit As Integer = CInt (register >> (width - 1)) และ 1 'define before shift register

Dim shiftedBit As Byte = Convert. ToByte (msgFifo. Dequeue)

ถ้า initFifo. Count> 0 แล้ว

Dim b As Byte = Convert. ToByte (initFifo. Dequeue)

shiftedBit = shiftedBit Xor b

จบถ้า

ลงทะเบียน = ลงทะเบียน << 1

register = register หรือ shiftedBit

ถ้า poppedBit = 1 แล้ว

register = register Xor poly

จบถ้า

ห่วง

'การแปลงครั้งสุดท้าย:

Dim crc As UInteger = register 'การลงทะเบียนมีส่วนที่เหลือของแผนก == checksum

ถ้า reverseCrc แล้ว

crc = สะท้อน (crc, ความกว้าง)

จบถ้า

crc = crc Xor สุดท้ายXor

crc = crc And (& HFFFFFFFFUI >> (32 - width)) 'ปิดบังบิตที่มีนัยสำคัญน้อยที่สุด

ส่งคืน crc

ฟังก์ชั่นสิ้นสุด

แนะนำ: