การรักษาความปลอดภัยด้วยโปรโตคอลเครือข่าย

การโต้ตอบที่เข้ารหัสระหว่างไคลเอ็นต์กับเซิร์ฟเวอร์จะใช้ Transport Layer Security (TLS) เพื่อปกป้องข้อมูลของแอป

บทความนี้กล่าวถึงแนวทางปฏิบัติแนะนำเกี่ยวกับโปรโตคอลเครือข่ายที่ปลอดภัยและข้อควรพิจารณาเกี่ยวกับโครงสร้างพื้นฐานคีย์สาธารณะ (PKI) อ่านรายละเอียดเพิ่มเติมได้ในภาพรวมความปลอดภัยของ Android และภาพรวมสิทธิ์

แนวคิด

เซิร์ฟเวอร์ที่มีใบรับรอง TLS จะมีคีย์สาธารณะและคีย์ส่วนตัวที่ตรงกัน เซิร์ฟเวอร์ใช้วิทยาการเข้ารหัสคีย์สาธารณะเพื่อลงนามในใบรับรองระหว่างแฮนด์เชค TLS

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

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

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

โดยปกติแล้ว CA ที่เชื่อถือได้จะแสดงอยู่ในแพลตฟอร์มโฮสต์ Android 8.0 (API ระดับ 26) มี CA มากกว่า 100 รายการที่อัปเดตในแต่ละเวอร์ชันและจะไม่เปลี่ยนแปลงระหว่างอุปกรณ์

แอปไคลเอ็นต์ต้องมีกลไกในการยืนยันเซิร์ฟเวอร์เนื่องจาก CA มีใบรับรองสำหรับเซิร์ฟเวอร์จํานวนมาก ใบรับรองของ CA จะระบุเซิร์ฟเวอร์โดยใช้ชื่อที่เฉพาะเจาะจง เช่น gmail.com หรือใช้ไวลด์การ์ด เช่น *.google.com

หากต้องการดูข้อมูลใบรับรองเซิร์ฟเวอร์ของเว็บไซต์ ให้ใช้คำสั่ง s_client ของเครื่องมือ openssl โดยส่งหมายเลขพอร์ต โดยค่าเริ่มต้น HTTPS จะใช้พอร์ต 443

คำสั่งนี้จะส่งเอาต์พุต openssl s_client ไปยัง openssl x509 ซึ่งจะจัดรูปแบบข้อมูลใบรับรองในมาตรฐาน X.509 คำสั่งจะขอหัวข้อ (ชื่อเซิร์ฟเวอร์) และผู้ออกใบรับรอง (CA)

openssl s_client -connect WEBSITE-URL:443 | \
  openssl x509 -noout -subject -issuer

ตัวอย่าง HTTPS

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

Kotlin

val url = URL("https://wikipedia.org")
val urlConnection: URLConnection = url.openConnection()
val inputStream: InputStream = urlConnection.getInputStream()
copyInputStreamToOutputStream(inputStream, System.out)

Java

URL url = new URL("https://wikipedia.org");
URLConnection urlConnection = url.openConnection();
InputStream in = urlConnection.getInputStream();
copyInputStreamToOutputStream(in, System.out);

หากต้องการปรับแต่งคำขอ HTTP ให้แคสต์ไปยัง HttpURLConnection HttpURLConnectionเอกสารประกอบของ Android มีตัวอย่างการจัดการส่วนหัวคำขอและการตอบกลับ การเผยแพร่เนื้อหา การจัดการคุกกี้ การใช้พร็อกซี การแคชการตอบกลับ และอื่นๆ เฟรมเวิร์ก Android จะยืนยันใบรับรองและชื่อโฮสต์โดยใช้ API เหล่านี้

ใช้ API เหล่านี้ทุกครั้งที่เป็นไปได้ ส่วนต่อไปนี้จะกล่าวถึงปัญหาที่พบได้ทั่วไปซึ่งต้องใช้วิธีแก้ปัญหาที่แตกต่างกัน

ปัญหาที่พบบ่อยเกี่ยวกับการยืนยันใบรับรองเซิร์ฟเวอร์

สมมติว่า getInputStream() แสดงข้อยกเว้นแทนที่จะแสดงผลลัพธ์

javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
        at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:374)
        at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478)
        at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:433)
        at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290)
        at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240)
        at libcore.net.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:282)
        at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)
        at libcore.net.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:271)

ปัญหานี้อาจเกิดขึ้นได้จากหลายสาเหตุ เช่น

  1. ไม่ทราบ CA ที่ออกใบรับรองเซิร์ฟเวอร์
  2. ใบรับรองเซิร์ฟเวอร์ไม่ได้ลงนามโดย CA แต่ลงนามด้วยตนเอง
  3. การกําหนดค่าเซิร์ฟเวอร์ไม่มี CA ระดับกลาง

ส่วนต่อไปนี้จะอธิบายวิธีแก้ปัญหาเหล่านี้ขณะที่รักษาการเชื่อมต่อกับเซิร์ฟเวอร์ให้ปลอดภัย

ผู้ออกใบรับรองที่ไม่รู้จัก

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

หากต้องการเชื่อถือ CA ที่กําหนดเองโดยไม่ต้องเปลี่ยนโค้ดของแอป ให้เปลี่ยนการกําหนดค่าความปลอดภัยของเครือข่าย

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

ใบรับรองเซิร์ฟเวอร์ที่ลงนามด้วยตนเอง

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

ไม่มีผู้ออกใบรับรองกลาง

ประการที่สาม SSLHandshakeException เกิดขึ้นเนื่องจากไม่มี CA ระดับกลาง CA สาธารณะไม่ค่อยลงนามในใบรับรองเซิร์ฟเวอร์ แต่ CA ระดับสูงจะลงนามใน CA ระดับกลางแทน

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

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

ตัวอย่างเช่น ต่อไปนี้คือเชนใบรับรอง mail.google.com ตามที่แสดงโดยคำสั่ง openssl s_client

$ openssl s_client -connect mail.google.com:443
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=mail.google.com
   i:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
 1 s:/C=ZA/O=Thawte Consulting (Pty) Ltd./CN=Thawte SGC CA
   i:/C=US/O=VeriSign, Inc./OU=Class 3 Public Primary Certification Authority
---

ข้อมูลนี้แสดงให้เห็นว่าเซิร์ฟเวอร์ส่งใบรับรองสำหรับ mail.google.com ที่ออกโดย CA ของ Thawte SGC ซึ่งเป็น CA ระดับกลาง และใบรับรองที่ 2 สำหรับ CA ของ Thawte SGC ที่ออกโดย CA ของ Verisign ซึ่งเป็น CA หลักที่ Android เชื่อถือ

อย่างไรก็ตาม เซิร์ฟเวอร์อาจไม่ได้กําหนดค่าให้รวม CA ระดับกลางที่จําเป็น ตัวอย่างเช่น เซิร์ฟเวอร์ที่อาจทำให้เกิดข้อผิดพลาดในเบราว์เซอร์ Android และข้อยกเว้นในแอป Android

$ openssl s_client -connect egov.uscis.gov:443
---
Certificate chain
 0 s:/C=US/ST=District Of Columbia/L=Washington/O=U.S. Department of Homeland Security/OU=United States Citizenship and Immigration Services/OU=Terms of use at www.verisign.com/rpa (c)05/CN=egov.uscis.gov
   i:/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=Terms of use at https://www.verisign.com/rpa (c)10/CN=VeriSign Class 3 International Server CA - G3
---

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

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

วิธีแก้ไขปัญหานี้คือให้กําหนดค่าเซิร์ฟเวอร์ให้รวม CA ตัวกลางไว้ในเชนเซิร์ฟเวอร์ CA ส่วนใหญ่มีวิธีการดำเนินการนี้สำหรับเว็บเซิร์ฟเวอร์ทั่วไป

คำเตือนเกี่ยวกับการใช้ SSLSocket โดยตรง

ตัวอย่างที่ผ่านมามุ่งเน้นที่ HTTPS โดยใช้ HttpsURLConnection บางครั้งแอปต้องใช้ TLS แยกจาก HTTPS เช่น แอปอีเมลอาจใช้ TLS รูปแบบต่างๆ ของ SMTP, POP3 หรือ IMAP ในกรณีดังกล่าว แอปจะใช้ SSLSocket ได้โดยตรงในลักษณะเดียวกับที่ HttpsURLConnection ใช้ภายใน

เทคนิคที่อธิบายไปก่อนหน้านี้เพื่อจัดการปัญหาการยืนยันใบรับรองจะใช้กับ SSLSocket ได้ด้วย จริงๆ แล้ว เมื่อใช้ TrustManager ที่กําหนดเอง สิ่งที่ส่งไปยัง HttpsURLConnection คือ SSLSocketFactory ดังนั้นหากต้องการใช้ TrustManager ที่กําหนดเองกับ SSLSocket ให้ทําตามขั้นตอนเดียวกันและใช้ SSLSocketFactory นั้นเพื่อสร้าง SSLSocket

ข้อควรระวัง: SSLSocket ไม่ได้ทำการยืนยันชื่อโฮสต์ ขึ้นอยู่กับแอปของคุณที่จะทำการยืนยันชื่อโฮสต์ด้วยตนเอง โดยควรเรียกใช้ getDefaultHostnameVerifier() ด้วยชื่อโฮสต์ที่คาดไว้ และโปรดทราบว่า HostnameVerifier.verify() จะไม่แสดงข้อยกเว้นเมื่อเกิดข้อผิดพลาด แต่จะให้ผลลัพธ์บูลีนซึ่งคุณต้องตรวจสอบอย่างชัดเจน

การตรวจสอบใบรับรอง

TLS อาศัย CA ในการออกใบรับรองให้กับเจ้าของเซิร์ฟเวอร์และโดเมนที่ยืนยันแล้วเท่านั้น ในบางกรณีที่พบได้ไม่บ่อยนัก CA ถูกหลอกลวง หรือในกรณีของ Comodo หรือ DigiNotar มีการละเมิด ส่งผลให้มีการออกใบรับรองสำหรับชื่อโฮสต์ให้กับบุคคลอื่นที่ไม่ใช่เจ้าของเซิร์ฟเวอร์หรือโดเมน

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

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

การจำกัดแอปของคุณให้ใช้ใบรับรองที่เฉพาะเจาะจง

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

หากต้องการจํากัดแอปให้ยอมรับเฉพาะใบรับรองที่คุณระบุ คุณควรระบุ PIN สำรองหลายรายการ รวมถึงคีย์อย่างน้อย 1 รายการที่คุณควบคุมได้ทั้งหมด และกำหนดระยะเวลาหมดอายุให้สั้นพอที่จะป้องกันปัญหาความเข้ากันได้ ค่ากําหนดความปลอดภัยของเครือข่าย ให้การปักหมุดด้วยความสามารถเหล่านี้

ใบรับรองไคลเอ็นต์

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

Nogotofail: เครื่องมือทดสอบความปลอดภัยของการรับส่งข้อมูลในเครือข่าย

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

Nogotofail มีประโยชน์สำหรับกรณีการใช้งานหลัก 3 กรณี ได้แก่

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

Nogotofail ใช้งานได้กับ Android, iOS, Linux, Windows, ChromeOS, macOS และอุปกรณ์ใดก็ตามที่คุณใช้เชื่อมต่ออินเทอร์เน็ต มีไคลเอ็นต์สําหรับการกําหนดค่าและการรับการแจ้งเตือนใน Android และ Linux และสามารถติดตั้งใช้งานเครื่องมือโจมตีเป็นเราเตอร์ เซิร์ฟเวอร์ VPN หรือพร็อกซี

คุณสามารถเข้าถึงเครื่องมือนี้ได้ที่โปรเจ็กต์โอเพนซอร์ส Nogotofail

การอัปเดต SSL และ TLS

Android 10

เบราว์เซอร์บางประเภท เช่น Google Chrome อนุญาตให้ผู้ใช้เลือกใบรับรองเมื่อเซิร์ฟเวอร์ TLS ส่งข้อความคำขอใบรับรองเป็นส่วนหนึ่งของการจับมือ TLS ตั้งแต่ Android 10 เป็นต้นไป ออบเจ็กต์ KeyChain จะยึดตามพารามิเตอร์ผู้ออกใบรับรองและข้อกำหนดเฉพาะของคีย์เมื่อเรียกใช้ KeyChain.choosePrivateKeyAlias() เพื่อแสดงข้อความแจ้งให้ผู้ใช้เลือกใบรับรอง โดยเฉพาะอย่างยิ่ง พรอมต์นี้ไม่มีตัวเลือกที่ไม่เป็นไปตามข้อกำหนดเฉพาะของเซิร์ฟเวอร์

หากไม่มีใบรับรองที่ผู้ใช้เลือกได้ เช่น ในกรณีที่ไม่มีใบรับรองที่ตรงกับข้อกําหนดของเซิร์ฟเวอร์หรืออุปกรณ์ไม่ได้ติดตั้งใบรับรองไว้เลย ข้อความแจ้งให้เลือกใบรับรองจะไม่ปรากฏขึ้นเลย

นอกจากนี้ ใน Android 10 ขึ้นไป คุณไม่จำเป็นต้องล็อกหน้าจออุปกรณ์เพื่อนำเข้าคีย์หรือใบรับรอง CA ไปยังออบเจ็กต์ KeyChain

เปิดใช้ TLS 1.3 โดยค่าเริ่มต้น

ใน Android 10 ขึ้นไป ระบบจะเปิดใช้ TLS 1.3 โดยค่าเริ่มต้นสำหรับการเชื่อมต่อ TLS ทั้งหมด รายละเอียดสําคัญบางประการเกี่ยวกับการใช้งาน TLS 1.3 มีดังนี้

  • คุณปรับแต่งชุดการเข้ารหัส TLS 1.3 ไม่ได้ ระบบจะเปิดใช้ชุดการเข้ารหัส TLS 1.3 ที่รองรับเสมอเมื่อเปิดใช้ TLS 1.3 ระบบจะไม่สนใจความพยายามในการปิดใช้โดยเรียกใช้ setEnabledCipherSuites()
  • เมื่อมีการเจรจา TLS 1.3 ระบบจะเรียกใช้ออบเจ็กต์ HandshakeCompletedListener ก่อนเพิ่มเซสชันลงในแคชเซสชัน (ใน TLS 1.2 และเวอร์ชันอื่นๆ ก่อนหน้านี้ ระบบจะเรียกใช้ออบเจ็กต์เหล่านี้หลังจากเพิ่มเซสชันลงในแคชเซสชันแล้ว)
  • ในบางกรณีที่อินสแตนซ์ SSLEngine แสดง SSLHandshakeException ใน Android เวอร์ชันก่อนหน้า อินสแตนซ์เหล่านี้จะแสดง SSLProtocolException แทนใน Android 10 ขึ้นไป
  • ไม่รองรับโหมด 0-RTT

หากต้องการ คุณจะได้รับ SSLContext ที่ปิดใช้ TLS 1.3 โดยการเรียกใช้ SSLContext.getInstance("TLSv1.2") นอกจากนี้ คุณยังเปิดหรือปิดใช้เวอร์ชันโปรโตคอลตามการเชื่อมต่อแต่ละรายการได้โดยเรียกใช้ setEnabledProtocols() บนออบเจ็กต์ที่เหมาะสม

ใบรับรองที่ลงนามด้วย SHA-1 จะไม่ได้รับการเชื่อถือใน TLS

ใน Android 10 ใบรับรองที่ใช้อัลกอริทึมแฮช SHA-1 จะไม่น่าเชื่อถือในการเชื่อมต่อ TLS CA รูทไม่ได้ออกใบรับรองดังกล่าวมาตั้งแต่ปี 2016 และใบรับรองเหล่านี้ไม่ได้รับความเชื่อถือใน Chrome หรือเบราว์เซอร์หลักอื่นๆ อีกต่อไป

การพยายามเชื่อมต่อจะล้มเหลวหากการเชื่อมต่อไปยังเว็บไซต์ที่แสดงใบรับรองโดยใช้ SHA-1

การเปลี่ยนแปลงและการปรับปรุงลักษณะการทํางานของ KeyChain

เบราว์เซอร์บางประเภท เช่น Google Chrome อนุญาตให้ผู้ใช้เลือกใบรับรองเมื่อเซิร์ฟเวอร์ TLS ส่งข้อความคำขอใบรับรองเป็นส่วนหนึ่งของการจับมือ TLS ตั้งแต่ Android 10 เป็นต้นไป ออบเจ็กต์ KeyChain จะเป็นไปตามพารามิเตอร์ของผู้ออกใบรับรองและข้อกำหนดเฉพาะของคีย์เมื่อเรียกใช้ KeyChain.choosePrivateKeyAlias() เพื่อแสดงข้อความแจ้งให้เลือกใบรับรองแก่ผู้ใช้ โดยเฉพาะอย่างยิ่ง พรอมต์นี้ไม่มีตัวเลือกที่ไม่เป็นไปตามข้อกำหนดของเซิร์ฟเวอร์

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

นอกจากนี้ ใน Android 10 ขึ้นไป คุณไม่จำเป็นต้องล็อกหน้าจออุปกรณ์เพื่อนำเข้าคีย์หรือใบรับรอง CA ไปยังออบเจ็กต์ KeyChain

การเปลี่ยนแปลงอื่นๆ เกี่ยวกับ TLS และวิทยาการเข้ารหัส

มีการเปลี่ยนแปลงเล็กน้อยหลายอย่างในไลบรารี TLS และวิทยาการเข้ารหัสที่มีผลใน Android 10 ดังนี้

  • การเข้ารหัส AES/GCM/NoPadding และ ChaCha20/Poly1305/NoPadding จะแสดงขนาดบัฟเฟอร์ที่แม่นยำมากขึ้นจาก getOutputSize()
  • ระบบจะไม่รวมชุดการเข้ารหัส TLS_FALLBACK_SCSV ในการพยายามเชื่อมต่อด้วยโปรโตคอลสูงสุด TLS 1.2 ขึ้นไป เราไม่แนะนำให้ลองใช้ TLS ภายนอกสำรอง เนื่องจากมีการปรับปรุงการติดตั้งใช้งานเซิร์ฟเวอร์ TLS เราขอแนะนำให้ใช้การเจรจาต่อรองเวอร์ชัน TLS แทน
  • ChaCha20-Poly1305 เป็นชื่อแทนของ ChaCha20/Poly1305/NoPadding
  • ระบบจะไม่ถือว่าชื่อโฮสต์ที่มีจุดต่อท้ายเป็นชื่อโฮสต์ SNI ที่ถูกต้อง
  • ระบบจะพิจารณาส่วนขยาย supported_signature_algorithms ใน CertificateRequest เมื่อเลือกคีย์การลงชื่อสำหรับการตอบกลับใบรับรอง
  • คีย์การลงนามแบบทึบ เช่น คีย์จาก Android Keystore สามารถใช้กับลายเซ็น RSA-PSS ใน TLS ได้

การเปลี่ยนแปลงการเชื่อมต่อ HTTPS

หากแอปที่ใช้ Android 10 ส่งค่า Null ไปยัง setSSLSocketFactory() ระบบจะแสดง IllegalArgumentException ในเวอร์ชันก่อนหน้า การส่งค่า Null ไปยัง setSSLSocketFactory() จะมีผลเหมือนกับการส่ง default factory ปัจจุบัน

Android 11

ซ็อกเก็ต SSL ใช้เครื่องมือ SSL ของ Conscrypt โดยค่าเริ่มต้น

การใช้งาน SSLSocket เริ่มต้นของ Android อิงตาม Conscrypt ตั้งแต่ Android 11 การใช้งานดังกล่าวสร้างขึ้นภายในโดยอิงตาม SSLEngine ของ Conscrypt