กลับไปหน้าบทความ

อ่าน 12 นาที

โปรโตคอลรหัสผ่านระยะไกลที่ปลอดภัย

โปรโตคอลรหัสผ่านระยะไกลที่ปลอดภัย ( SRP ) เป็น โปรโตคอล การแลกเปลี่ยนคีย์ที่ตรวจสอบความถูกต้องด้วยรหัสผ่าน (PAKE) ที่ได้รับการปรับปรุง...

โปรโตคอลรหัสผ่านระยะไกลที่ปลอดภัย

โปรโตคอลรหัสผ่านระยะไกลที่ปลอดภัย ( SRP ) เป็น โปรโตคอล การแลกเปลี่ยนคีย์ที่ตรวจสอบความถูกต้องด้วยรหัสผ่าน (PAKE) ที่ได้รับการปรับปรุง ซึ่งออกแบบมาโดยเฉพาะเพื่อแก้ไขปัญหาสิทธิบัตรที่มีอยู่[ 1 ]

เช่นเดียวกับโปรโตคอล PAKE ทั้งหมด ผู้ดักฟังหรือผู้แทรกแซงไม่สามารถได้รับข้อมูลเพียงพอที่จะสามารถ เดา รหัสผ่านแบบ brute-force หรือใช้ การโจมตีแบบพจนานุกรมได้โดยไม่ต้องมีการโต้ตอบเพิ่มเติมกับฝ่ายต่างๆ สำหรับการเดาแต่ละครั้ง ยิ่งไปกว่านั้น เนื่องจากเป็นโปรโตคอล PAKE ที่ได้รับการปรับปรุง เซิร์ฟเวอร์จึงไม่เก็บข้อมูลที่เทียบเท่ากับรหัสผ่าน[ 2 ]ซึ่งหมายความว่าผู้โจมตีที่ขโมยข้อมูลเซิร์ฟเวอร์ไม่สามารถปลอมตัวเป็นไคลเอนต์ได้ เว้นแต่พวกเขาจะทำการค้นหารหัสผ่านแบบ brute-force ก่อน

กล่าวโดยง่าย ในระหว่างการตรวจสอบสิทธิ์แบบ SRP (หรือโปรโตคอล PAKE อื่นๆ) ฝ่ายหนึ่ง ("ไคลเอ็นต์" หรือ "ผู้ใช้") แสดงให้ฝ่ายอื่น ("เซิร์ฟเวอร์") เห็นว่าตนเองรู้รหัสผ่าน โดยไม่ต้องส่งรหัสผ่านหรือข้อมูลอื่นใดที่สามารถนำมาคำนวณหารหัสผ่านได้ รหัสผ่านจะไม่เคยออกจากไคลเอ็นต์และเซิร์ฟเวอร์จะไม่ทราบ

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

คุณสมบัติความปลอดภัยที่ได้รับการพิสูจน์ทางคณิตศาสตร์เพียงอย่างเดียวของ SRP คือเทียบเท่ากับ Diffie-Hellman เมื่อเผชิญกับผู้โจมตีแบบพาสซีฟ[ 3 ]แม้ว่า SRP จะมีความสมบูรณ์และใช้งานอย่างแพร่หลาย แต่ก็เป็นการออกแบบที่เก่ากว่าและมีบางรูปแบบที่แสดงจุดอ่อนเล็กน้อย คือไม่ปลอดภัยแบบ UCขาดความต้านทานต่อ การโจมตี แบบ precomputation ทั้งหมด มีการพิสูจน์อย่างเป็นทางการที่อ่อนแอกว่า และไม่มีการป้องกันต่อรูปแบบการโจมตีสมัยใหม่บางแบบ ด้วยเหตุผลเหล่านี้ ปัจจุบัน SRP จึงถือว่าล้าสมัยไปแล้ว OPAQUE เป็น PAKE เสริมที่นิยมใช้ ในขณะที่ CPace หรือ SPAKE2 เป็นที่นิยมสำหรับสถานการณ์ PAKE ที่สมดุลซึ่งทั้งสองฝ่ายแบ่งปันรหัสผ่าน[ 4 ] [ 5 ]

ภาพรวม

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

โปรโตคอล SRP สร้างคีย์ส่วนตัวขนาดใหญ่ที่ใช้ร่วมกันระหว่างสองฝ่ายในลักษณะที่คล้ายกับการแลกเปลี่ยนคีย์ Diffie–Hellmanโดยฝั่งไคลเอ็นต์มีรหัสผ่านของผู้ใช้และฝั่งเซิร์ฟเวอร์มี ตัวตรวจสอบ การเข้ารหัสที่ได้มาจากรหัสผ่าน คีย์สาธารณะที่ใช้ร่วมกันนั้นได้มาจากตัวเลขสุ่มสองตัว ตัวหนึ่งสร้างโดยไคลเอ็นต์และอีกตัวหนึ่งสร้างโดยเซิร์ฟเวอร์ ซึ่งแต่ละตัวจะมีเอกลักษณ์เฉพาะสำหรับการเข้าสู่ระบบแต่ละครั้ง ในกรณีที่ต้องการการสื่อสารที่เข้ารหัสและการตรวจสอบสิทธิ์ โปรโตคอล SRP จะมีความปลอดภัยมากกว่า โปรโตคอล SSHและเร็วกว่าการใช้การแลกเปลี่ยนคีย์ Diffie–Hellmanกับข้อความที่ลงนาม นอกจากนี้ยังเป็นอิสระจากบุคคลที่สาม ซึ่งแตกต่างจาก Kerberos

โปรโตคอล SRP เวอร์ชัน 3 ได้รับการอธิบายไว้ใน RFC 2945 SRP เวอร์ชัน 6a ยังใช้สำหรับการตรวจสอบความถูกต้องของรหัสผ่านที่รัดกุมในSSL/TLS [ 6 ] (ในTLS-SRP ) และมาตรฐานอื่นๆ เช่นEAP [ 7 ]และSAMLและเป็นส่วนหนึ่งของIEEE 1363.2และ ISO/IEC 11770-4

โปรโตคอล

ในคำอธิบายโปรโตคอลเวอร์ชัน 6 นี้ ใช้สัญลักษณ์ดังต่อไปนี้:

  • เลือกqและN = 2q + 1 โดยที่ทั้งคู่เป็นจำนวนเฉพาะ (ซึ่งทำให้ qเป็นจำนวนเฉพาะโซฟี แฌร์แม็งและNเป็นจำนวนเฉพาะที่ปลอดภัย ) Nต้องมีขนาดใหญ่พอที่จะทำให้การคำนวณลอการิทึมแบบไม่ต่อเนื่องมอดูลNเป็นไปไม่ได้
  • การคำนวณเลขคณิตทั้งหมดจะดำเนินการในวงแหวนของจำนวนเต็มมอดูลN ซึ่งหมายความว่าg x ด้านล่าง ควรอ่านว่าg x mod N
  • gเป็นตัวสร้างของกลุ่มการคูณ
  • H () คือ ฟังก์ชัน แฮชเช่น SHA-256
  • kเป็นพารามิเตอร์ที่ได้มาจากทั้งสองฝ่าย ใน SRP-6 k = 3 ในขณะที่ใน SRP-6a จะได้มาจากNและg  : k = H ( N , g ) ใช้เพื่อป้องกันการเดาแบบ 2 ต่อ 1 เมื่อผู้โจมตีที่ใช้งานอยู่ปลอมตัวเป็นเซิร์ฟเวอร์[ 8 ] [ 9 ]
  • sคือเกลือชนิด หนึ่ง
  • Iคือชื่อผู้ใช้ที่ใช้ระบุตัวตน
  • pคือรหัสผ่านของผู้ใช้
  • vคือตัวตรวจสอบรหัสผ่านของโฮสต์ โดยv = g xซึ่งอย่างน้อยที่สุดx = H ( s , p ) เนื่องจากxถูกคำนวณเฉพาะบนฝั่งไคลเอ็นต์ จึงสามารถเลือกอัลกอริทึมที่แข็งแกร่งกว่าได้ การใช้งานอาจเลือกใช้x = H ( s | I | p )โดยไม่ส่งผลกระทบต่อขั้นตอนใดๆ ที่โฮสต์ต้องดำเนินการ มาตรฐานRFC2945กำหนดx = H ( s | H ( I | ":" | p ) )การใช้Iภายในxช่วยป้องกันไม่ให้เซิร์ฟเวอร์ที่เป็นอันตรายสามารถเรียนรู้ได้ว่าผู้ใช้สองคนใช้รหัสผ่านเดียวกัน หรือ ไม่
  • AและBคือคีย์ชั่วคราวแบบสุ่มที่ใช้ได้ครั้งเดียวของผู้ใช้และโฮสต์ตามลำดับ
  • | (เครื่องหมาย |) หมายถึงการเชื่อมต่อ

ตัวแปรอื่นๆ ทั้งหมดถูกกำหนดโดยอ้างอิงจากตัวแปรเหล่านี้

ขั้นแรก เพื่อสร้างรหัสผ่านpกับเซิร์ฟเวอร์ Steve ลูกค้า Carol จะเลือกค่า salt แบบสุ่มsและคำนวณ x = H ( s , p ) , v = gx Steve จะจัดเก็บvและsโดยใช้ดัชนีIเป็นตัวตรวจสอบรหัสผ่านและค่า salt ของ Carol Carol ต้องไม่เปิดเผยxให้กับใคร และต้องลบมันอย่างปลอดภัยในขั้นตอนนี้ เพราะมันเทียบเท่ากับรหัสผ่านp ที่เป็นข้อความธรรมดา ขั้นตอนนี้เสร็จสมบูรณ์ก่อนที่ระบบจะถูกใช้เป็นส่วนหนึ่งของการลงทะเบียนผู้ใช้กับ Steve โปรดทราบว่าค่า salt sจะถูกแบ่งปันและแลกเปลี่ยนเพื่อเจรจาคีย์เซสชันในภายหลัง ดังนั้นค่าอาจถูกเลือกโดยฝ่ายใดฝ่ายหนึ่ง แต่ Carol เป็นผู้เลือกเพื่อให้เธอสามารถลงทะเบียนI , sและvในคำขอลงทะเบียนเดียว การส่งและการตรวจสอบความถูกต้องของคำขอลงทะเบียนไม่ได้กล่าวถึงใน SRP

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

  1. แครอล → สตีฟ: สร้างค่าสุ่มa ; ส่งIและA = g a
  2. Steve → Carol: สร้างค่าสุ่มb ; ส่งsและB = kv + g b
  3. ทั้งสอง: u = H ( A , B )
  4. แคโรล: S แคโรล = ( Bkg x ) ( a + ux ) = ( kv + g bkg x ) ( a + ux ) = ( kg xkg x + g b ) (a + ux) = ( g b ) ( a + ux )
  5. แครอล: K แครอล = H ( S แครอล )
  6. Steve: S Steve = ( Av u ) b = ( g a v u ) b = [ g a ( g x ) u ] b = ( g a + ux ) b = ( g b ) (a + ux)
  7. สตีฟ: K สตีฟ = H ( S สตีฟ ) = K แครอล

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

  1. Carol → Steve: M 1 = H [ H ( N ) XOR H ( g ) | H ( I ) | s | A | B | K Carol ] Steve ตรวจสอบM 1แล้ว
  2. Steve → Carol: M 2 = H ( A | M 1 | K Steve ) . Carol ตรวจสอบM 2แล้ว

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

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

  1. Carol → Steve: M 1 = H ( A | B | S Carol ) . Steve ตรวจสอบM 1แล้ว
  2. Steve → Carol: M 2 = H ( A | M 1 | S Steve ) . Carol ตรวจสอบM 2แล้ว

เมื่อใช้ SRP ในการเจรจาเพื่อสร้างคีย์ร่วมKซึ่งจะถูกนำไปใช้ทันทีหลังจากการเจรจาเสร็จสิ้น อาจดูเหมือนง่ายที่จะข้ามขั้นตอนการตรวจสอบM1และM2 เซิร์ฟเวอร์จะปฏิเสธคำขอแรกจากไคลเอ็นต์ที่ไม่สามารถถอดรหัสได้ อย่างไรก็ตาม การทำเช่นนี้อาจเป็นอันตรายได้ ดังที่แสดงไว้ในส่วน " ข้อผิดพลาดในการใช้งาน "ด้านล่าง

ทั้งสองฝ่ายยังได้ใช้มาตรการป้องกันดังต่อไปนี้:

  1. แครอลจะทำแท้งหากเธอได้รับB = 0 (mod N ) หรือu = 0
  2. สตีฟจะยกเลิกหากเขาได้รับA (mod N ) = 0
  3. แครอลต้องแสดงหลักฐานการพิสูจน์K (หรือS ) ของเธอก่อน หากสตีฟตรวจพบว่าหลักฐานการพิสูจน์ของแครอลไม่ถูกต้อง เขาต้องยกเลิกโดยไม่แสดงหลักฐานการพิสูจน์ K (หรือS ) ของตนเอง

ตัวอย่างโค้ดในภาษา Python

""" ตัวอย่างการตรวจสอบสิทธิ์ SRPคำเตือน: ห้ามใช้เพื่อวัตถุประสงค์ทางด้านการเข้ารหัสลับจริงนอกเหนือจากการทดสอบคำเตือน: โค้ดด้านล่างนี้ขาดมาตรการป้องกันที่สำคัญ มันไม่ได้ตรวจสอบว่า A, B และ U ไม่เป็นศูนย์อ้างอิงจาก http://srp.stanford.edu/design.html """ import hashlib import random# หมายเหตุ: str แปลงตามเดิม str([1,2,3,4]) จะแปลงเป็น "[1,2,3,4]" def H ( * args ) -> int : """ฟังก์ชันแฮชแบบทางเดียว""" a = ":" . join ( str ( a ) for a in args ) return int ( hashlib . sha256 ( a . encode ( "utf-8" )) . hexdigest (), 16 )def cryptrand ( n : int = 1024 ): return random . SystemRandom () . getrandbits ( n ) % N# จำนวนเฉพาะขนาดใหญ่ที่ปลอดภัย (N = 2q+1 โดยที่ q เป็นจำนวนเฉพาะ) # การคำนวณทั้งหมดทำโดยใช้โมดูลัส N # (สร้างโดยใช้ "openssl dhparam -text 1024") N = """00:c0:37:c3:75:88:b4:32:98:87:e6:1c:  2d:a3:32: 4b:1b:a4:b8:1a:63:f9:74:8f:ed:2d:8a:41:0c:2f:  c2:1b:12:32:f0:d3:bf:a0:24:27:6c:fd:88:44:81:  97:aa:e4:86:a6:3b:fc:a7:b8:bf:77:54:df:b3:27:  c7:20:1f:6f:d1:7f:d7:fd:74:15:8b:d3:1c:e7:72:  c9:f5:f8:ab:58:45:48:a9:9a:75:9b:5a:2c:05:32:  16:2b:7b:62:18:e8:f1:42:bc:e2:c3:0d:77:84:68:  9a:48:3e:09:5e:70:16:18:43:79:13:a8:c3:9c:3d:  d0:d4:ca:3c:50:0b:88:5f:e3"""N = int ( "" . join ( N . split ()) . replace ( ":" , "" ), 16 ) g = 2 # ตัวสร้างโมดูลัส Nk = H ( N , g ) # พารามิเตอร์ตัวคูณ (k=3 ใน SRP-6 แบบดั้งเดิม)F = '#0x' # ตัวระบุรูปแบบprint ( "#. H, N, g และ k เป็นที่ทราบล่วงหน้าทั้งฝั่งไคลเอ็นต์และเซิร์ฟเวอร์:" ) print ( f ' { H = } \n { N = :{ F }} \n { g = :{ F }} \n { k = :{ F }} ' )พิมพ์( " 0. เซิร์ฟเวอร์จัดเก็บ (I, s, v) ในฐานข้อมูลรหัสผ่าน" )# เซิร์ฟเวอร์ต้องสร้างตัวตรวจสอบรหัสผ่านก่อนI = "person" # ชื่อผู้ใช้p = "password1234" # รหัสผ่านs = cryptrand ( 64 ) # เกลือสำหรับผู้ใช้x = H ( s , I , p ) # คีย์ส่วนตัวv = pow ( g , x , N ) # ตัวตรวจสอบรหัสผ่านprint ( f ' { I = } \n { p = } \n { s = :{ F }} \n { x = :{ F }} \n { v = :{ F }} ' )# 0. เซิร์ฟเวอร์จัดเก็บ (I, s, v) ในฐานข้อมูลรหัสผ่าน# I = 'person' # p = 'password1234' # s = 0x67bc8932cfd26a49 # x = 0x98a4bce8dde877762a90222f1a1161eba9248590a47eb83aa9e5bd7ecda5368d # v = 0xa7e2038e675d577ac0f318999cab67bba7ec2daf45d2d09f7911b1b78d2fc7f963cd0ac8f17851e0516f059e453672c3b70fcecf5f6843180b271a bdd01f552ccda7b24fe4719336409cbc1352f8517be651b8935cc0b74ff2819fa07a3f031537d4cfd9f8df7b788a5f2f88e1cd4106b35c38b3d7205a# <สาธิต> --- หยุด ---print ( " 1. ไคลเอนต์ส่งชื่อผู้ใช้ I และค่าชั่วคราวสาธารณะ A ไปยังเซิร์ฟเวอร์" ) a = cryptrand () A = pow ( g , a , N ) print ( f " { I = } \n { A = :{ F }} " ) # ไคลเอนต์->เซิร์ฟเวอร์ (I, A)# 1. ไคลเอนต์ส่งชื่อผู้ใช้ I และค่าชั่วคราวสาธารณะ A ไปยังเซิร์ฟเวอร์# I = 'บุคคล' # A = 0x678556a7e76581e051af656e8cee57ae46df43f1fce790f7750a3ec5308a85da4ec4051e5cb74d3e463685ee975a2747cf49035be67c931b56e793 f23ea3524af8909dcfbc8675d872361025bf884778587ac49454a57c53a011ac2be2839bfb51bf7847a49a483aba870dc7a8b467a81cec91b8ae7813# <สาธิต> --- หยุด ---print ( " 2. เซิร์ฟเวอร์ส่งค่า salt s ของผู้ใช้และค่าชั่วคราวสาธารณะ B ไปยังไคลเอ็นต์" ) b = cryptrand () B = ( k * v + pow ( g , b , N )) % N print ( f " { s = :{ F }} \n { B = :{ F }} " ) # server->client (s, B)# 2. เซิร์ฟเวอร์ส่งค่า salt s ของผู้ใช้และค่าชั่วคราวสาธารณะ B ไปยังไคลเอ็นต์# s = 0x67bc8932cfd26a49 # B = 0xb615a0a5ea6abf138077bbd869f6a8da37dfc0b7e06a9f5fac5c1e4109c6302cb3e94dcc2cc76da7b3d87d7e9b68a1db998ab239cfde609f3f7a1e ce4a491ce3d9a665c20cf4e4f06730daaa8f52ed61e45bbb67cdc337bf648027ffa7f0f215d5ebe43f9f51832518f1142266aae0dfa960e0082b5154# <สาธิต> --- หยุด ---print ( " 3. ไคลเอนต์และเซิร์ฟเวอร์คำนวณพารามิเตอร์การสุ่ม" ) u = H ( A , B ) # พารามิเตอร์การสุ่มprint ( f " { u = :{ F }} " )# 3. ไคลเอนต์และเซิร์ฟเวอร์คำนวณพารามิเตอร์การสุ่มสลับ# u = 0x796b07e354c04f672af8b76a46560655086355a9bbce11361f01b45d991c0c52# <สาธิต> --- หยุด ---print ( " 4. ไคลเอนต์คำนวณคีย์เซสชัน" ) x = H ( s , I , p ) S_c = pow ( B - k * pow ( g , x , N ), a + u * x , N ) K_c = H ( S_c ) print ( f " { S_c = :{ F }} \n { K_c = :{ F }} " )# 4. ไคลเอนต์คำนวณคีย์เซสชัน# S_c = 0x699170aff6e9f08ed09a1dff432bf0605b8bcba05aadcaeea665757d06dbda4348e211d16c10ef4678585bcb2809a83c62b6c19d97901274ddafd4075f90604c06baf036af587af8540342b47867eaa22b9ca5e35ac14c8e85a0c4e623bd855828dffd513cea4d829c407137a0dd81ab4cde8a904c45cc # K_c = 0x43f8df6e1d2ba762948c8316db5bf03a7af49391742f5f51029630711c1671e# <สาธิต> --- หยุด ---print ( " 5. เซิร์ฟเวอร์คำนวณคีย์เซสชัน" ) S_s = pow ( A * pow ( v , u , N ), b , N ) K_s = H ( S_s ) print ( f " { S_s = :{ F }} \n { K_s = :{ F }} " )# 5. เซิร์ฟเวอร์คำนวณคีย์เซสชัน# S_s = 0x699170aff6e9f08ed09a1dff432bf0605b8bcba05aadcaeea665757d06dbda4348e211d16c10ef4678585bcb2809a83c62b6c19d97901274ddafd4075f90604c06baf036af587af8540342b47867eaa22b9ca5e35ac14c8e85a0c4e623bd855828dffd513cea4d829c407137a0dd81ab4cde8a904c45cc # K_s = 0x43f8df6e1d2ba762948c8316db5bf03a7af49391742f5f51029630711c1671e# <สาธิต> --- หยุด ---print ( " 6. ไคลเอ็นต์ส่งหลักฐานของคีย์เซสชันไปยังเซิร์ฟเวอร์" ) M_c = H ( H ( N ) ^ H ( g ), H ( I ), s , A , B , K_c ) print ( f " { M_c = :{ F }} " ) # ไคลเอ็นต์->เซิร์ฟเวอร์ (M_c) ; เซิร์ฟเวอร์ตรวจสอบ M_c# 6. ไคลเอ็นต์ส่งหลักฐานของคีย์เซสชันไปยังเซิร์ฟเวอร์# M_c = 0x75500df4ea36e06406ac1f8a8241429b8e90a8cba3adda3405c07f19ea3101e8# <สาธิต> --- หยุด ---print ( " 7. เซิร์ฟเวอร์ส่งหลักฐานของคีย์เซสชันไปยังไคลเอ็นต์" ) M_s = H ( A , M_c , K_s ) print ( f " { M_s = :{ F }} " ) # เซิร์ฟเวอร์->ไคลเอ็นต์ (M_s) ; ​​ไคลเอ็นต์ตรวจสอบ M_s# 7. เซิร์ฟเวอร์ส่งหลักฐานของคีย์เซสชันไปยังไคลเอ็นต์# M_s = 0x182ed24d1ad2fb55d2268c46b42435d1ef02e0fc49f647c03dab8b2a48b0bd3d

ข้อผิดพลาดในการนำไปปฏิบัติ

การโจมตีแบบ Brute Force ออฟไลน์ด้วยการส่งข้อความแบบ Server-first โดยไม่มีการตรวจสอบคีย์

หากเซิร์ฟเวอร์ส่งข้อความที่เข้ารหัสโดยไม่รอการตรวจสอบจากไคลเอนต์ ผู้โจมตีจะสามารถทำการโจมตีแบบ Brute Force ออฟไลน์ได้คล้ายกับการถอดรหัสแฮช ซึ่งอาจเกิดขึ้นได้หากเซิร์ฟเวอร์ส่งข้อความที่เข้ารหัสในแพ็กเก็ตที่สองพร้อมกับค่า Salt และBหรือหากข้ามขั้นตอนการตรวจสอบคีย์และเซิร์ฟเวอร์ (แทนที่จะเป็นไคลเอนต์) ส่งข้อความที่เข้ารหัสแรก ซึ่งเป็นสิ่งที่ดึงดูดใจเพราะหลังจากแพ็กเก็ตแรก เซิร์ฟเวอร์จะมีข้อมูลทั้งหมดเพื่อคำนวณคีย์ร่วมKแล้ว

ขั้นตอนการโจมตีมีดังนี้:

  1. แครอล → สตีฟ: สร้างค่าสุ่มa ; ส่งIและA = g a
  2. สตีฟ: u = H ( A , B ); S = Av u ; K = H ( S )
  3. Steve: สร้างข้อความmและเข้ารหัสเพื่อสร้างc =ENC( K , m )
  4. Steve → Carol: สร้างค่าสุ่มb ; ส่งs , B = kv + g bและc

แครอลไม่รู้จัก ค่า xหรือvแต่ถ้าให้รหัสผ่านp ใดๆ เธอก็สามารถคำนวณได้ดังนี้:

  • x p = H (เกลือ, p )
  • S p = ( B - กก. x พี ) ( a + ux p )
  • K p = H ( S p )

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

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

การโจมตีแบบ Brute Force ออฟไลน์โดยอาศัยการจับเวลา

ในปี 2021 Daniel De Almeida Braga, Pierre-Alain Fouque และ Mohamed Sabt ได้ตีพิมพ์ PARASITE [ 10 ]ซึ่งเป็นเอกสารที่พวกเขาสาธิตการใช้ประโยชน์จากการโจมตีแบบจับเวลาบนเครือข่ายในทางปฏิบัติ โดยใช้ประโยชน์จากการใช้งานที่ไม่คงที่ของการยกกำลังแบบโมดูลาร์ของตัวเลขขนาดใหญ่ และส่งผลกระทบต่อ OpenSSL โดยเฉพาะ

การนำไปใช้

  • ตัวแปร SRP-6:ไลบรารี Java ของฟังก์ชันพื้นฐานทางด้านการเข้ารหัสลับที่จำเป็นสำหรับการใช้งานโปรโตคอล SRP-6
  • OpenSSLเวอร์ชัน 1.0.1 หรือใหม่กว่า
  • Botan (ไลบรารีการเข้ารหัสลับที่เขียนด้วยภาษา C++) มีการใช้งาน SRP-6a อยู่ภายใน
  • TLS-SRPคือชุดรหัสลับสำหรับความปลอดภัยระดับชั้นการขนส่งที่ใช้ SRP
  • srp-clientคือการใช้งาน SRP-6a ในJavaScript (เข้ากันได้กับ RFC 5054) เป็นโอเพนซอร์ส ภายใต้ใบ อนุญาต Mozilla Public License (MPL)
  • ไลบรารีJavaScript Crypto Libraryประกอบด้วยการใช้งานโปรโตคอล SRP ในภาษา JavaScript ซึ่งเป็นโอเพนซอร์สและ ได้รับอนุญาตภายใต้ใบ อนุญาตBSD
  • Gnu Cryptoเป็น ไลบรารีที่เขียนด้วย ภาษา Javaซึ่งได้รับอนุญาตภายใต้GNU General Public Licenseโดยมี "ข้อยกเว้นสำหรับไลบรารี" ซึ่งอนุญาตให้ใช้งานเป็นไลบรารีร่วมกับซอฟต์แวร์ที่ไม่ใช่โอเพนซอร์สได้
  • Legion of the Bouncy Castle ให้บริการซอฟต์แวร์ที่ เขียนด้วยภาษา Java และC#ภายใต้สัญญาอนุญาต MIT
  • Nimbus SRPเป็นไลบรารี Java ที่ให้บริการตัวสร้างตัวตรวจสอบความถูกต้อง เซสชันฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ รวมถึงอินเทอร์เฟซสำหรับคีย์รหัสผ่านแบบกำหนดเอง รูทีนข้อความหลักฐานฝั่งไคลเอ็นต์และฝั่งเซิร์ฟเวอร์ ไม่มีการพึ่งพาภายนอกใดๆ เผยแพร่ภายใต้ ใบอนุญาต Apache 2.0
  • srplibcppเป็นไลบรารี C++ ที่พัฒนาต่อยอดจากMIRACL
  • DragonSRPเป็นการใช้งานแบบโมดูลาร์ที่เขียนด้วยภาษา C++ ซึ่งปัจจุบันใช้งานได้กับOpenSSL
  • Json2Ldapให้บริการการตรวจสอบสิทธิ์แบบ SRP-6a สำหรับเซิร์ฟเวอร์ไดเร็กทอรีLDAP
  • การใช้งาน csrp SRP-6a ในภาษา C
  • การใช้งาน Crypt-SRP SRP-6a ในภาษาPerl
  • การใช้งาน pysrp SRP-6a ในภาษา Python (ใช้งานร่วมกับcsrp ได้ )
  • การใช้งาน py3srp SRP-6a ด้วยPython3บริสุทธิ์
  • srptoolsเครื่องมือสำหรับใช้งานการตรวจสอบสิทธิ์ด้วยรหัสผ่านระยะไกลที่ปลอดภัย (SRP) ในPython ตรวจสอบ แล้วว่าใช้ไลบรารีเดียวกัน
  • ระบบบัญชีผู้ใช้ของ Meteor Web Framework ใช้ SRP สำหรับการตรวจสอบสิทธิ์ด้วยรหัสผ่าน
  • srp-rbการใช้งาน SRP-6a ในภาษา Ruby
  • falkmueller demo การใช้งานโปรโตคอลStanford SRP-6aในJavaScriptและPHPภายใต้ใบอนุญาต MIT
  • srp-6a-demoการใช้งาน SRP-6a ในPHPและJavaScript
  • thinbus-srp-js คือ การใช้งาน SRP-6a ในJavaScriptมาพร้อมกับ คลาส Java ที่เข้ากันได้ ซึ่งใช้Nimbus SRP (เก็บถาวรเมื่อ 2014-02-22 บนWayback Machine)แอปพลิเคชันสาธิตที่ใช้Spring Securityนอกจากนี้ยังมีแอปพลิเคชันสาธิตการตรวจสอบสิทธิ์ไปยัง เซิร์ฟเวอร์ PHPเผยแพร่ภายใต้Apache License
  • Stanford JavaScript Crypto Library (SJCL)ใช้หลักการ SRP สำหรับการแลกเปลี่ยนคีย์
  • node-srpเป็นการนำหลักการ SRP มาใช้ในรูปแบบไคลเอ็นต์และเซิร์ฟเวอร์ด้วย JavaScript (node.js)
  • SRP6 สำหรับการใช้งานในภาษา C# และ Java
  • ALOSRPAuthเป็นการใช้งาน SRP-6a ที่เขียนด้วยภาษา Objective-C
  • go-srpคือการนำหลักการ SRP-6a มาใช้ในภาษา Go
  • tssrp6aคือการนำ SRP-6a มาใช้ในรูปแบบ TypeScript
  • ไลบรารี IceNet Cryptography Java สำหรับพัฒนาแอปพลิเคชัน Spring Boot ที่ใช้การเข้ารหัสลับ รองรับมาตรฐาน SRP-6a อยู่ภายใต้ลิขสิทธิ์ Apache License
  • การนำSRP-6a ไปใช้ใน .NET
  • Apple Homekit ใช้ SRP เมื่อจับคู่กับอุปกรณ์และเครื่องใช้ไฟฟ้าในบ้านอัจฉริยะ
  • การตรวจสอบสิทธิ์ Proton Mailสำหรับการเข้ารหัสอีเมล
  • SRPเป็นการนำ SRP มาเขียนด้วยภาษา Go ซึ่งใช้ในการตรวจสอบสิทธิ์ผู้ใช้บนPosterity

ประวัติศาสตร์

โครงการ SRP เริ่มต้นในปี 1997 [ 11 ]แนวทางที่แตกต่างกันสองวิธีในการแก้ไขช่องโหว่ด้านความปลอดภัยใน SRP-1 ส่งผลให้เกิด SRP-2 และ SRP-3 [ 12 ] SRP-3 ได้รับการเผยแพร่ครั้งแรกในปี 1998 ในการประชุม[ 13 ] RFC 2945 ซึ่งอธิบาย SRP-3 ด้วย SHA1 ได้รับการเผยแพร่ในปี 2000 [ 14 ] SRP-6 ซึ่งแก้ไขการโจมตีแบบเดา "สองต่อหนึ่ง" และการโจมตีแบบเรียงลำดับข้อความ ได้รับการเผยแพร่ในปี 2002 [ 8 ] SRP-6a ปรากฏใน "libsrp" อย่างเป็นทางการในเวอร์ชัน 2.1.0 ลงวันที่ 2005 [ 15 ] SRP-6a พบได้ในมาตรฐานดังนี้:

  • ISO/IEC 11770-4:2006 "กลไกข้อตกลงหลัก 2" (เรียกวิธีการนี้ว่า "SRP-6" แต่มี การคำนวณ kเป็น 6a)
  • RFC 5054 TLS-SRP ปี 2007 (เรียกอีกครั้งว่า "SRP-6" แต่แก้ไขใน erratum [ 16 ] )
  • IEEE Std 1363.2-2008 "DLAPKAS-SRP6" (เรียกอีกครั้งว่า "SRP-6") [ 17 ]

IEEE 1363.2 ยังรวมถึงคำอธิบายของ "SRP5" ซึ่งเป็นรูปแบบที่แทนที่ลอการิทึมแบบไม่ต่อเนื่องด้วยเส้นโค้งวงรีที่ Yongge Wang นำเสนอในปี 2001 [ 18 ]นอกจากนี้ยังอธิบาย SRP-3 ดังที่พบใน RFC 2945

ดูเพิ่มเติม

  • เว็บไซต์อย่างเป็นทางการ
  • ใบอนุญาต SRP —โอเพนซอร์สแบบ BSD
  • US6539479 - สิทธิบัตร SRP (หมดอายุเมื่อวันที่ 12 พฤษภาคม 2558 เนื่องจากไม่ชำระค่าบำรุงรักษา (ตามข้อมูลจาก Google Patents) เดิมกำหนดหมดอายุในเดือนกรกฎาคม 2561)

หน้าคู่มือ

  • pppd(8) : เดมอนโปรโตคอลแบบจุดต่อจุด
  • srptool(1) : เครื่องมือรหัสผ่าน SRP แบบง่าย

อาร์เอฟซี

  • RFC  2944 - การตรวจสอบสิทธิ์ Telnet: SRP
  • RFC  2945 - ระบบการตรวจสอบสิทธิ์และการแลกเปลี่ยนคีย์ SRP (เวอร์ชัน 3)
  • RFC  3720 - อินเทอร์เฟซระบบคอมพิวเตอร์ขนาดเล็กทางอินเทอร์เน็ต (iSCSI)
  • RFC  3723 - การรักษาความปลอดภัยของโปรโตคอลการจัดเก็บข้อมูลแบบบล็อกผ่าน IP
  • RFC  3669 - แนวทางสำหรับคณะทำงานด้านประเด็นทรัพย์สินทางปัญญา
  • RFC  5054 - การใช้โปรโตคอลรหัสผ่านระยะไกลที่ปลอดภัย (SRP) สำหรับการตรวจสอบสิทธิ์ TLS
  • อีอีอีอี 1363
  • สไลด์เกี่ยวกับทรัพย์สินทางปัญญาของ SRP (ธันวาคม 2544 - อาจล้าสมัยแล้ว)สิทธิบัตรของ EKE ที่กล่าวถึงหมดอายุในปี 2554 และ 2556
ดึงข้อมูลมาจาก " https://en.wikipedia.org/w/index.php?title=Secure_Remote_Password_protocol&oldid=1334520305 "

สรุปเนื้อหา

ข้อมูลสำคัญจากบทความ

ข้อมูลสำคัญเกี่ยวกับ โปรโตคอลรหัสผ่านระยะไกลที่ปลอดภัย

โปรโตคอลรหัสผ่านระยะไกลที่ปลอดภัย ( SRP ) เป็น โปรโตคอล การแลกเปลี่ยนคีย์ที่ตรวจสอบความถูกต้องด้วยรหัสผ่าน (PAKE) ที่ได้รับการปรับปรุง...

ภาพรวม

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

โปรโตคอล

ในคำอธิบายโปรโตคอลเวอร์ชัน 6 นี้ ใช้สัญลักษณ์ดังต่อไปนี้:

ตัวอย่างโค้ดในภาษา Python

""" ตัวอย่างการตรวจสอบสิทธิ์ SRP คำเตือน: ห้ามใช้เพื่อวัตถุประสงค์ทางด้านการเข้ารหัสลับจริงนอกเหนือจากการทดสอบ คำเตือน: โค้ดด้านล่างนี้ขาดมาตรการป้องกันที่สำคัญ มันไม่ได้ตรวจสอบว่า A, B และ U ไม่เป็นศูนย์ อ้างอิงจาก http://srp.stanford.edu/design.