คอมพิวเตอร์จะคำนวณเลขชี้กำลังแบบเลขชี้กำลังโดยไม่มีข้อผิดพลาดมากเกินไปได้อย่างไร


32

จากการศึกษาวิธีการเข้ารหัส / ถอดรหัส RSA ฉันพบบทความนี้: ตัวอย่างของอัลกอริทึม RSA

มันต้องการสิ่งนี้เพื่อถอดรหัสข้อความนี้ ป้อนคำอธิบายรูปภาพที่นี่

ผลลัพธ์ทั้งหมดของป้อนคำอธิบายรูปภาพที่นี่มันใหญ่มากสำหรับเครื่อง 64- บิต / 32- บิตฉันไม่เชื่อว่ามันสามารถเก็บค่าที่ยิ่งใหญ่เช่นนี้ไว้ในการลงทะเบียนครั้งเดียว คอมพิวเตอร์ทำอย่างไรโดยไม่ล้น


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


6
ฉันสงสัยว่าคุณจะได้รับคำตอบที่ดีกว่าหรือไม่หากมีการย้ายข้อมูลไปยัง cs.stackexchange.com ดูเหมือนว่ามันจะเหมาะกับไซต์ CS / Math มากขึ้นซึ่งเน้นไปที่รายละเอียดที่แท้จริงของสิ่งต่ำลงในระดับต่ำมาก
Zoredache

1
สิ่งนี้ใช้ได้เพียงพอสำหรับผู้ใช้ขั้นสูง
James Mertz

คำตอบ:


40

เนื่องจากการดำเนินการโมดูลัสจำนวนเต็มเป็นวงแหวนโฮโมมอร์ฟิซึม ( Wikipedia ) จากℤ -> ℤ / nℤ,

(X * Y) mod N = (X mod N) * (Y mod N) mod N

คุณสามารถยืนยันตัวเองด้วยพีชคณิตแบบง่าย ๆ (โปรดทราบว่าสุดท้ายmodที่ด้านขวามือจะปรากฏขึ้นเนื่องจากคำจำกัดความของการคูณในวงแหวนแบบแยกส่วน)

คอมพิวเตอร์ใช้เคล็ดลับนี้เพื่อคำนวณเลขยกกำลังในวงแหวนแบบแยกส่วนโดยไม่ต้องคำนวณตัวเลขจำนวนมาก

               / 1 I = 0,
               |
(X ^ I) mod N = <(X * (X ^ (I-1) mod N)) mod NI คี่
               |
               \ (X ^ (I / 2) mod N) ^ 2 mod NI แม้ & I / = 0

ในรูปแบบอัลกอริทึม

-- compute X^I mod N
function expmod(X, I, N)
    if I is zero
        return 1
    elif I is odd
        return (expmod(X, I-1, N) * X) mod N
    else
        Y <- expmod(X, I/2, N)
        return (Y*Y) mod N
    end if
end function

คุณสามารถใช้สิ่งนี้เพื่อคำนวณ(855^2753) mod 3233ด้วยการลงทะเบียนแบบ 16 บิตเท่านั้นหากคุณต้องการ

อย่างไรก็ตามค่าของ X และ N ใน RSA นั้นใหญ่กว่ามากเกินกว่าที่จะพอดีกับรีจิสเตอร์ โดยทั่วไปโมดูลัสจะยาว 1024-4096 บิต! คุณสามารถให้คอมพิวเตอร์ทำการคูณด้วยวิธี "ยาว" เช่นเดียวกับที่เราคูณด้วยมือ เฉพาะการใช้ตัวเลข 0-9 เท่านั้นคอมพิวเตอร์จะใช้ "คำ" 0-2 16 -1 หรืออะไรทำนองนั้น (การใช้เพียง 16 บิตหมายความว่าเราสามารถคูณตัวเลข 16 บิตสองตัวและรับผลลัพธ์เต็ม 32 บิตโดยไม่ต้องใช้ภาษาแอสเซมบลีในภาษาแอสเซมบลีมักจะง่ายมากที่จะได้ผลลัพธ์เต็ม 64 บิตหรือสำหรับคอมพิวเตอร์ 64 บิต ผลลัพธ์เต็ม 128 บิต)

-- Multiply two bigints by each other
function mul(uint16 X[N], uint16 Y[N]):
    Z <- new array uint16[N*2]
    for I in 1..N
        -- C is the "carry"
        C <- 0
        -- Add Y[1..N] * X[I] to Z
        for J in 1..N
            T <- X[I] * Y[J] + C + Z[I + J - 1]
            Z[I + J - 1] <- T & 0xffff
            C <- T >> 16
        end
        -- Keep adding the "carry"
        for J in (I+N)..(N*2)
            T <- C + Z[J]
            Z[J] <- T & 0xffff
            C <- T >> 16
        end
    end
    return Z
end
-- footnote: I wrote this off the top of my head
-- so, who knows what kind of errors it might have

สิ่งนี้จะทวีคูณ X ด้วย Y ในระยะเวลาเท่ากับจำนวนคำใน X คูณด้วยจำนวนคำใน Y ซึ่งเรียกว่าเวลา O (N 2 ) หากคุณดูอัลกอริทึมด้านบนแล้วแยกมันเป็น "การคูณแบบยาว" ที่พวกเขาสอนในโรงเรียน คุณไม่มีตารางเวลาที่จำได้ถึง 10 หลัก แต่คุณยังสามารถคูณ 1,926,348 x 8,192,004 ถ้าคุณนั่งลงและทำงานออกมา

การคูณยาว:

    1,234
  x 5,678
---------
    9,872
   86,38
  740,4
6,170
---------
7,006,652

จริงๆแล้วมีบางอัลกอริทึมที่เร็วกว่าสำหรับการคูณ ( Wikipedia ) เช่นวิธี Fourier ที่รวดเร็วของ Strassen และวิธีที่ง่ายกว่าที่จะทำการบวกและการลบเพิ่มเติม แต่การคูณน้อยลงและจบลงโดยรวมเร็วขึ้น ห้องสมุดเชิงตัวเลขเช่น GMP มีความสามารถในการเลือกอัลกอริทึมที่แตกต่างกันตามจำนวนที่มีขนาดใหญ่: การแปลงฟูริเยร์เป็นเพียงเร็วที่สุดสำหรับหมายเลขที่ใหญ่ที่สุด


+1 แต่คุณขาดส่วนเพิ่มเติมmod Nไปในตอนท้ายของทฤษฎีบทส่วนที่เหลือของจีน ( (16 mod 5)ไม่เท่ากับ(4 mod 5) * (4 mod 5): อดีตคือ 1 หลังคือ 16)
ruakh

@ruakh: แก้ไขแล้ว แม้ว่าฉันอยากจะบอกว่า R / kR isomorphic ถึง R / k1R x R / k2R x ... R / knR โดยที่ k1 .. kn เป็นคู่ตามลำดับ coprime ผลิตภัณฑ์ของพวกเขาคือ k และ R เป็นโดเมนในอุดมคติหลัก ฉันบรรทุกเกินพิกัดมานานจนยากที่จะมองว่าเป็นอะไรนอกจากเป็นโมดูล ในคำอื่น ๆ ภายใต้อนุสัญญาสัญกรณ์ปกติของฉันmodคือไม่จำเป็น
Dietrich Epp

1
@Synetech: แต่ฉันรักสี่คำเหล่านั้นมาก: "การออกกำลังกายสำหรับผู้อ่าน"
Dietrich Epp

1
(X * Y) mod N = (X mod N) * (Y mod N) mod Nเป็นความจริง แต่มันไม่มีอะไรเกี่ยวข้องกับทฤษฎีบทส่วนที่เหลือของจีน
Dennis

1
@Dennis: ฉันชี้แจงโครงสร้างของโคโดเมนในคำตอบทันที (ฉันไม่เคยคลุมเครือสำหรับฉันตั้งแต่ฉันเขียนมัน ... )
Dietrich Epp

9

คำตอบง่ายๆคือพวกเขาทำไม่ได้ไม่ใช่ด้วยตัวเอง แน่นอนถ้าคุณใช้แนวคิดของเครื่อง x-bit แล้วมีจำนวน จำกัด ซึ่งสามารถแสดงด้วยบิตจำนวน จำกัด เช่นเดียวกับที่มีจำนวน จำกัด จำนวนซึ่งสามารถแสดงด้วย 2 หลักใน ระบบทศนิยม

ที่ถูกกล่าวว่าคอมพิวเตอร์เป็นตัวแทนของตัวเลขที่มีขนาดใหญ่มากเป็นองค์ประกอบที่มีขนาดใหญ่ของด้านการเข้ารหัส มีหลายวิธีในการแสดงตัวเลขที่มีขนาดใหญ่มากในคอมพิวเตอร์แต่ละวิธีมีความหลากหลายเป็นแบบถัดไป

แต่ละวิธีเหล่านี้มีข้อดีและข้อเสียแตกต่างกันและในขณะที่ฉันไม่สามารถ / ไม่สามารถแสดงรายการวิธีการทั้งหมดที่นี่ฉันจะนำเสนอเพียงวิธีเดียว

สมมติว่าจำนวนเต็มสามารถเก็บค่าได้ตั้งแต่ 0-99 หนึ่งจะแสดงหมายเลข 100 ได้อย่างไร สิ่งนี้อาจดูเหมือนเป็นไปไม่ได้ในตอนแรก แต่นั่นเป็นเพราะเราพิจารณาเพียงตัวแปรเดียวเท่านั้น ถ้าผมเรียกว่าเป็นจำนวนเต็มunitsและเป็นหนึ่งเรียกว่าhundredsผมได้อย่างง่ายดายสามารถเป็นตัวแทนของ hundreds = 1; units = 0;100: ฉันได้อย่างง่ายดายจะเป็นตัวแทนเป็นจำนวนมากเช่น hundreds = 92; units = 239223:

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

ฉันหวังว่านี่จะตอบคำถามของคุณ!

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


3

วิธีที่สามารถทำได้ (มีวิธีที่เร็วกว่ามากเกี่ยวกับการยกกำลังสองซ้ำและสิ่งที่คล้ายกัน) คือการคูณและหลังจากการคูณทุกครั้งจะใช้มอดุลัส ตราบใดที่โมดูลัสกำลังสองน้อยกว่า 2 ^ 32 (หรือ 2 ^ 64) สิ่งนี้จะไม่มีวันล้น


3

แบบเดียวกับที่คุณทำได้

ฉันจะเดาว่าคุณไม่รู้อะไรเลยว่าอะไรคือ 342 * 189 แต่คุณรู้ข้อเท็จจริงต่อไปนี้:

9 * 2 = 18
9 * 4 = 36
9 * 3 = 27
8 * 2 = 16
8 * 4 = 32
8 * 3 = 24
1 * 2 = 2
1 * 4 = 4
1 * 3 = 3

18 + 360 + 2700 + 160 + 3200 + 24000 + 200 + 4000 + 30000 = 64638

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

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


0

เท่าที่มีการเพิ่มและการลบซีพียูจำนวนมากมี "บิตนำ" ที่ตั้งไว้หากการดำเนินการทางคณิตศาสตร์ได้โอเวอร์โฟลว์ ดังนั้นหากผลลัพธ์จะต้องมี 8 ไบต์ในการจัดเก็บและ CPU เป็น 32- บิต (ซึ่ง equls 4 8- บิตไบต์) ก็สามารถดำเนินการเพิ่มเติมสองครั้งแรกใน "คำต่ำ" และจาก "คำสูง" ด้วย carry bit ที่ดูแลการโอเวอร์โฟลว์ จำเป็นต้องล้างบิตนำออกก่อน นี่เป็นเหตุผลหนึ่งที่ทำให้ซีพียูบิตที่สูงกว่าเพิ่มประสิทธิภาพเนื่องจากไม่ต้องทำอะไรมาก

แน่นอนว่ามันมาจากประสบการณ์แอสเซมเบลอร์ที่ จำกัด ของฉันกับซีพียู 8 บิต ฉันไม่รู้ว่า carry bit ทำงานอย่างไรกับ CPU ที่ทันสมัยพร้อมคำแนะนำการคูณและการหาร ซีพียูที่ไม่ใช่ของ Intel RISC อาจมีพฤติกรรมที่แตกต่างออกไป

ฉันไม่รู้เกี่ยวกับคณิตศาสตร์จุดลอยตัวมากนัก แต่โดยทั่วไปแล้วไบต์เป็นตัวแทนของจำนวนสถานที่ที่แน่นอน แต่ไม่ใช่สถานที่ที่เฉพาะเจาะจง นั่นเป็นสาเหตุที่เรียกว่าจุด "ลอย" ตัวอย่างเช่นหมายเลข 34459234 จะใช้พื้นที่หน่วยความจำประมาณเท่ากับ 3.4459234 หรือ 3.4459234E + 20 (นั่นคือ 3.4459234 x 10 ^ 20)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.