sách gpt4 ăn đã đi

Lập trình mạng Java - giao tiếp mạng an toàn

In lại Tác giả: Tôi là chú chim nhỏ Thời gian cập nhật: 27-06-2023 06:31:09 26 4
mua khóa gpt4 giày nike

Giới thiệu về SSL

SSL (Lớp cổng bảo mật) là giao thức đảm bảo liên lạc an toàn giữa hai nút trên mạng. Tổ chức quốc tế IETF (Interet Engineering Task Force) đã tiêu chuẩn hóa SSL và xây dựng đặc tả RFC2246, được gọi là Bảo mật lớp vận chuyển (TLS).

Cả SSL và TLS đều dựa trên TCP/IP. Một số giao thức lớp ứng dụng, chẳng hạn như HTTP và IMAP, có thể sử dụng SSL để đảm bảo liên lạc an toàn. HTTP được xây dựng trên giao thức SSL được gọi là giao thức HTTPS. Cổng mặc định được HTTP sử dụng là 80, trong khi cổng mặc định được HTTPS sử dụng là 443.

SSL sử dụng công nghệ mã hóa để đạt được giao tiếp an toàn, đảm bảo tính bảo mật và toàn vẹn của dữ liệu liên lạc và đảm bảo rằng cả hai bên giao tiếp đều có thể xác minh danh tính của bên kia.

1. Giao tiếp được mã hóa

Khi máy khách liên lạc với máy chủ, dữ liệu liên lạc có thể bị các máy tính khác trên mạng chặn trái phép. SSL sử dụng công nghệ mã hóa để đạt được việc truyền thông tin an toàn giữa cả hai bên trong phiên. Nguyên tắc cơ bản của công nghệ mã hóa là khi dữ liệu được gửi từ đầu này sang đầu kia, trước tiên người gửi sẽ mã hóa dữ liệu rồi gửi đến người nhận. Bằng cách này, dữ liệu được mã hóa sẽ được truyền qua mạng. Nếu ai đó chặn trái phép lô dữ liệu này trên Internet thì không có cách nào lấy được dữ liệu gốc thực sự vì không có khóa giải mã. Sau khi nhận được dữ liệu được mã hóa, trước tiên người nhận sẽ giải mã dữ liệu rồi xử lý dữ liệu đó.

2. Chứng chỉ bảo mật

Ngoài việc mã hóa giao tiếp dữ liệu, SSL còn sử dụng cơ chế xác thực danh tính để đảm bảo rằng cả hai bên tham gia giao tiếp đều có thể xác minh danh tính thực sự của bên kia. Điều này rất giống với cách chúng ta dùng chứng minh thư để chứng minh thân phận trong cuộc sống, chẳng hạn như khi bạn đến ngân hàng rút tiền và tự nhận mình là Zhang San, bạn làm cách nào để khiến đối phương tin vào danh tính của mình? Cách hiệu quả nhất là xuất trình CMND của bạn. Mọi người đều có một thẻ ID duy nhất, ghi lại thông tin thực của bạn. Chứng minh nhân dân do cơ quan có thẩm quyền cấp quốc gia và không được phép giả mạo. Miễn là thẻ ID của bạn không thể bị người khác làm giả hoặc sao chép, bạn có thể chứng minh danh tính của mình bằng cách xuất trình nó.

Các cá nhân có thể chứng minh danh tính của mình thông qua chứng minh nhân dân và đối với một tổ chức, chẳng hạn như trung tâm mua sắm, họ có thể chứng minh danh tính của mình thông qua giấy phép kinh doanh. Giấy phép kinh doanh cũng do cơ quan nhà nước có thẩm quyền cấp và không được phép làm giả, điều này đảm bảo độ tin cậy của giấy phép kinh doanh.

SSL sử dụng chứng chỉ bảo mật để chứng minh danh tính của máy khách hoặc máy chủ. Khi máy khách liên lạc với máy chủ thông qua kết nối an toàn, trước tiên máy chủ sẽ xuất trình chứng chỉ bảo mật của nó cho máy khách. Chứng chỉ này tuyên bố rằng máy chủ thực sự an toàn. máy chủ này. Chứng chỉ này là duy nhất trên toàn thế giới và không thể bị làm giả bởi các máy chủ bất hợp pháp khác. Chứng chỉ bảo mật có thể được so sánh với thẻ ID điện tử.

Đối với khách hàng cá nhân, việc đến cơ quan được công nhận để lấy chứng chỉ bảo mật là điều rườm rà. Để mở rộng cơ sở khách hàng và tạo điều kiện cho khách hàng tiếp cận, nhiều máy chủ không yêu cầu khách hàng xuất trình chứng chỉ bảo mật. Trong một số trường hợp, máy chủ cũng sẽ yêu cầu khách hàng xuất trình chứng chỉ bảo mật để xác minh danh tính của khách hàng. Điều này chủ yếu xảy ra trong các giao dịch B2B.

Có hai cách để lấy chứng chỉ bảo mật, một là lấy chứng chỉ từ cơ quan có thẩm quyền, hai là tạo chứng chỉ tự ký.

2.1 Nhận chứng chỉ từ cơ quan có thẩm quyền

Chứng chỉ bảo mật được cấp bởi các cơ quan cấp chứng chỉ có thẩm quyền quốc tế, đảm bảo độ tin cậy của chứng chỉ. Khi xin giấy chứng nhận bảo đảm phải nộp phí. Chứng chỉ bảo mật chỉ có hiệu lực cho một địa chỉ IP. Nếu có nhiều địa chỉ IP trong môi trường hệ thống của người dùng thì phải mua chứng chỉ bảo mật cho mỗi địa chỉ IP.

2.2 Tạo chứng chỉ tự ký

Trong một số trường hợp, các bên giao tiếp chỉ quan tâm đến việc dữ liệu có thể được truyền an toàn trên mạng và không yêu cầu bên kia xác thực. Trong trường hợp này, chứng chỉ tự ký có thể được tạo. Cũng giống như một tấm danh thiếp do người dùng tự làm, nó thiếu thẩm quyền và không thể đạt được mục đích xác thực danh tính. Khi bạn trao danh thiếp của mình cho bên kia, nó khẳng định bạn là CEO của một công ty lớn, bạn có tin hay không chỉ có thể do đối phương phán xét.

Vì chứng chỉ tự ký không chứng minh được danh tính của bạn một cách hiệu quả, vậy mục đích là gì? Về mặt kỹ thuật, cho dù đó là chứng chỉ nhận được từ một tổ chức có thẩm quyền hay chứng chỉ do chính họ tạo ra thì công nghệ mã hóa được sử dụng đều giống nhau. Khi sử dụng các chứng chỉ này, bạn có thể đạt được thông tin liên lạc được mã hóa an toàn.

3. Bắt tay SSL

Chứng chỉ bảo mật chứa cả khóa dùng để mã hóa dữ liệu và chữ ký số dùng để chứng minh danh tính. Chứng chỉ bảo mật sử dụng công nghệ mã hóa khóa chung. Mã hóa khóa chung đề cập đến việc sử dụng một cặp khóa bất đối xứng để mã hóa hoặc giải mã. Mỗi cặp khóa bao gồm một khóa chung và một khóa riêng. Khóa chung được công bố rộng rãi, còn khóa riêng được ẩn và không được công khai. Dữ liệu được mã hóa bằng khóa chung chỉ có thể được giải mã bằng khóa riêng và ngược lại, dữ liệu được mã hóa bằng khóa riêng chỉ có thể được giải mã bằng khóa chung.

Khi máy khách liên lạc với máy chủ, việc bắt tay SSL trước tiên phải được thực hiện. Việc bắt tay SSL chủ yếu hoàn thành các nhiệm vụ sau:

  • Thương lượng bộ mật mã được sử dụng. Bộ mật mã bao gồm một tập hợp các tham số mã hóa chỉ định thuật toán mã hóa và độ dài khóa.
  • Xác minh danh tính của bên kia, thao tác này là tùy chọn
  • Xác định thuật toán mã hóa được sử dụng

Quá trình bắt tay SSL sử dụng mã hóa bất đối xứng để truyền dữ liệu nhằm thiết lập phiên bảo mật. Sau khi quá trình bắt tay SSL hoàn tất, các bên giao tiếp sẽ sử dụng mã hóa đối xứng để truyền dữ liệu ứng dụng thực tế. Cái gọi là mã hóa đối xứng có nghĩa là cả hai bên giao tiếp đều sử dụng cùng một khóa để mã hóa dữ liệu.

Quá trình bắt tay SSL cụ thể như sau:

  1. Máy khách gửi số phiên bản SSL, tham số mã hóa, dữ liệu liên quan đến phiên và thông tin cần thiết khác đến máy chủ
  2. Máy chủ gửi số phiên bản SSL, tham số mã hóa, dữ liệu liên quan đến phiên và thông tin cần thiết khác cho máy khách cũng như chứng chỉ của máy chủ. Nếu máy chủ cần xác minh danh tính của máy khách, máy chủ cũng đưa ra yêu cầu chứng chỉ bảo mật từ máy khách.
  3. Máy khách xác minh chứng chỉ máy chủ. Nếu xác minh không thành công, nó sẽ nhắc nhở rằng không thể thiết lập kết nối SSL. Nếu thành công thì tiếp tục bước tiếp theo
  4. Máy khách tạo một bí mật tiền chính cho phiên này, mã hóa nó bằng khóa chung được đính kèm với chứng chỉ bảo mật của máy chủ và gửi nó đến máy chủ.
  5. Nếu máy chủ yêu cầu xác minh danh tính của khách hàng, khách hàng cũng sẽ cần ký một số dữ liệu bổ sung và gửi nó đến máy chủ cùng với chứng chỉ ứng dụng khách.
  6. Nếu máy chủ yêu cầu xác minh danh tính của khách hàng, hãy kiểm tra xem CA đã ký chứng chỉ của khách hàng có đáng tin cậy hay không. Nếu nó không có trong danh sách tin cậy, hãy kết thúc phiên này. Nếu quá trình kiểm tra thành công, máy chủ sẽ sử dụng khóa riêng của nó để giải mã mật khẩu chính sơ bộ đã nhận được và sử dụng nó để tạo bí mật chính cho phiên này thông qua một số thuật toán.
  7. Cả máy khách và máy chủ đều sử dụng mật khẩu chính này để tạo khóa phiên (khóa đối xứng) cho phiên này. Khóa phiên này được sử dụng cho mọi tin nhắn được gửi sau khi bắt tay SSL giữa hai bên. Lý do chính cho điều này là độ phức tạp tính toán của mã hóa đối xứng thấp hơn nhiều so với mã hóa bất đối xứng, điều này có thể cải thiện đáng kể tốc độ tính toán của cuộc trò chuyện giữa hai bên.
  8. Máy khách thông báo cho máy chủ rằng tất cả các tin nhắn được gửi sau đó sẽ được mã hóa bằng khóa phiên này và thông báo cho máy chủ rằng máy khách đã hoàn tất quá trình bắt tay SSL này.
  9. Máy chủ thông báo cho khách hàng rằng tất cả các tin nhắn tiếp theo sẽ được mã hóa bằng khóa phiên này và sẽ được liên lạc như thể máy chủ đã hoàn tất quá trình bắt tay SSL này.
  10. Quá trình bắt tay này kết thúc và phiên đã được thiết lập. Trong phiên tiếp theo, cả hai bên sử dụng cùng một khóa phiên để mã hóa và giải mã thông tin được gửi và nhận tương ứng.

4. Tạo chứng chỉ bảo mật tự ký

JDK cung cấp keytool, một công cụ để tạo chứng chỉ và vị trí của nó là: \bin\keytool.exe.

Công cụ keytool đề xuất khái niệm về kho khóa, có thể chứa nhiều mục nhập, mỗi mục nhập bao gồm chứng chỉ bảo mật tự ký và một cặp khóa bất đối xứng.

Lệnh tạo kho khóa thông qua công cụ keytool là:

                        
                          keytool -genkeypair -alias weiqin -keyalg RSA -keystore C:\chapter15\test.keystore

                        
                      
  • genkeypair: tạo một cặp khóa bất đối xứng
  • bí danh: chỉ định bí danh của cặp mục nhập và khóa, được công khai
  • keyalg: Chỉ định thuật toán mã hóa Trong ví dụ này, thuật toán RSA chung được sử dụng.
  • keystore: Đặt đường dẫn lưu trữ và tên file của file keystore

Trong quá trình chạy lệnh, trước tiên bạn sẽ được nhắc nhập mật khẩu của kho khóa, sau đó được nhắc nhập thông tin cá nhân, chẳng hạn như tên, đơn vị tổ chức, thành phố, v.v. Bạn chỉ cần nhập thông tin thật.

Lệnh sau kiểm tra thông tin của kho khóa test.keystore và liệt kê thông tin của các mục được bao gồm.

                        
                          keytool -list -v -keystore C:\chapter15\test.keystore -storepass "123456”

                        
                      

Lệnh sau xuất mục nhập có bí danh weiqin trong kho khóa test.keystore sang chứng chỉ bảo mật có tên tệp weiqin.crt. Bài viết weiqin.crt chứa chứng chỉ bảo mật tự ký và khóa chung trong cặp khóa, nhưng không bao gồm khóa riêng trong cặp khóa.

                        
                          keytool -export -alias weigin -keystore C:\chapter15\test.keystore -file C:\chapter15\weigin.crt -storepass “123456”

                        
                      

Lệnh sau sẽ xóa mục có bí danh weiqin trong kho khóa test.keystore.

                        
                          keytool -delete -alias weigin -keystore C:\chapter15\test.keystore -storepass “123456”

                        
                      

Lệnh sau nhập chứng chỉ bảo mật weiqin.crt vào kho khóa testTrust.keystore để tạo mục nhập có bí danh weiqin. Mục nhập này chứa khóa chung trong cặp khóa nhưng không chứa khóa riêng trong cặp khóa.

                        
                          keytool -import -alias weiqin -keystore C:\chapter15\testTrust.keystore -file C:\chapter15\weiqin.crt -storepass "123456"

                        
                      

Giới thiệu về JSSE

JSSE đóng gói các chi tiết liên lạc bảo mật phức tạp cơ bản, cho phép các nhà phát triển dễ dàng sử dụng nó để phát triển các ứng dụng mạng an toàn.

1. Các lớp KeyStore, KeyManager và TrustManager

Khi tiến hành liên lạc an toàn, cả máy khách và máy chủ đều phải hỗ trợ giao thức SSL hoặc TCL. Cả máy khách và máy chủ đều có thể cần thiết lập chứng chỉ bảo mật để chứng minh danh tính của mình, đồng thời đặt chứng chỉ bảo mật nào họ tin cậy. Một tình huống phổ biến hơn là máy chủ chỉ cần đặt chứng chỉ bảo mật dùng để chứng minh danh tính của nó và máy khách chỉ cần đặt chứng chỉ bảo mật nào của máy chủ mà nó tin cậy.

Lớp KeyStore được sử dụng để lưu trữ kho khóa chứa chứng chỉ bảo mật. Mã chương trình sau đây tạo một đối tượng KeyStore tải chứng chỉ bảo mật từ tệp kho khóa test.keystore.

                        
                          String passphrase = "123456"; //JKS là loại KeyStore được JDK KeyStore hỗ trợ keyStore = KeyStore.getInstance("JKS"); kho khóa keyStore.load(new FileInputStream("test.keystore"), mật khẩu);

                        
                      

Nhiệm vụ của giao diện KeyManager là chọn chứng chỉ bảo mật dùng để chứng minh danh tính của nó và gửi cho bên kia. Ví dụ: KeyManagerFactory chịu trách nhiệm tạo các đối tượng KeyManager.

                        
                          KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); keyManagerFactory.init(keyStore, mật khẩu); KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

                        
                      

Nhiệm vụ của giao diện TrustManager là quyết định có tin cậy chứng chỉ bảo mật của bên kia hay không. Ví dụ: TruesManagerFactory chịu trách nhiệm tạo các đối tượng TrustManager.

                        
                          TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509"); trustManagerFactory.init(keyStore); TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

                        
                      

2. Lớp SSLContext

Lớp SSLContext chịu trách nhiệm thiết lập nhiều thông tin khác nhau liên quan đến giao tiếp an toàn, chẳng hạn như giao thức được sử dụng (SSL hoặc TLS), chứng chỉ bảo mật của chính nó và chứng chỉ bảo mật của bên kia. SSLContext cũng chịu trách nhiệm xây dựng các đối tượng SSLServerSocketFactory, SSLSocketFactory và SSLEngine.

Mã chương trình sau đây tạo và khởi tạo một đối tượng SSLContext, sau đó tạo một đối tượng SSLServerSocketFactory từ nó.

                        
                          SSLContext sslCtx = SSLContext.getInstance("TLS");//Sử dụng TLS sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); SSLServerSocketFactory ssf = sslCtx.getServerSocketFactory();

                        
                      

Phương thức init của SSLContext được định nghĩa như sau.

                        
                          public final void init(KeyManager[] km, TrustManager[] tm, SecureRandom ngẫu nhiên) ném KeyManagementException

                        
                      
  • Tham số ngẫu nhiên được sử dụng để đặt số ngẫu nhiên an toàn. Nếu tham số này là null, phương thức init sẽ sử dụng triển khai SecureRandom mặc định.
  • Nếu tham số km là null, phương thức init sẽ tạo một đối tượng KeyManager mặc định và đối tượng KeyStore liên quan của nó sẽ nhận được chứng chỉ bảo mật từ thuộc tính hệ thống javax.net.ssl.keyStore. Nếu không có thuộc tính hệ thống như vậy tồn tại thì nội dung đối tượng KeyStore trống
  • Nếu tham số tm là null, phương thức init sẽ tạo một đối tượng TrustManager mặc định và đối tượng KeyStore liên quan của nó sẽ nhận được chứng chỉ bảo mật theo các bước sau:
    • Trước tiên hãy thử lấy chứng chỉ bảo mật từ thuộc tính hệ thống javax.net.ssl.trustStore
    • Nếu bước trước không thành công, hãy sử dụng tệp /lib/security/jsecacerts làm chứng chỉ bảo mật
    • Nếu bước trước không thành công, hãy sử dụng tệp /lib/security/cacerts làm chứng chỉ bảo mật
    • Nếu bước trước không thành công, nội dung của đối tượng KeyStore sẽ trống

3. Lớp SSLServerSocketFactory

Lớp SSLServerSocketFactory chịu trách nhiệm tạo các đối tượng SSLServerSocket.

                        
                          SSLServerSocket serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(8000); // Kích thước tệp 8000

                        
                      

Có hai cách để tạo đối tượng SSLServerSocketFactory:

  • Gọi phương thức getServerSocketFactory của lớp SSLContext
  • Gọi phương thức getDefault tĩnh của lớp SSLServerSocketFactory

Phương thức getDefault tĩnh của lớp SSLServerSocketFactory trả về một đối tượng SSLServerSocketFactory mặc định, được liên kết với một đối tượng SSLContext mặc định. Việc triển khai phương thức getDefault sẽ khởi tạo đối tượng SSLContext mặc định như sau.

                        
                          sslContext.init(null,null,null);

                        
                      

4. Lớp SSLSocketFactory

Lớp SSLSocketFactory chịu trách nhiệm tạo các đối tượng SSLSocket.

                        
                          Ổ cắm SSLSocket = (SSLSocket) sslSocketFactory.createSocket("localhost",8000);

                        
                      

Có hai cách để tạo đối tượng SSLSocketFactory.

  • Gọi phương thức getSocketFactory của lớp SSLContext
  • Gọi phương thức getDefault tĩnh của lớp SSLSocketFactory

Phương thức getDefault tĩnh của lớp SSLSocketFactory trả về một đối tượng SSLSocketFactory mặc định, được liên kết với một đối tượng SSLContext mặc định. Việc triển khai phương thức getDefault sẽ khởi tạo đối tượng SSLContext mặc định như sau.

                        
                          sslContext.init(null,null,null);

                        
                      

5. Lớp SSLSocket

Lớp SSLSocket là một lớp con của lớp Socket nên có nhiều điểm tương đồng trong cách sử dụng chúng. Ngoài ra, lớp SSLSocket còn có các phương thức liên quan đến giao tiếp an toàn.

5.1 Thiết lập bộ mã hóa

Máy khách và máy chủ cần thương lượng bộ mật mã thực tế được sử dụng trong giai đoạn bắt tay. Hai tình huống sau đây sẽ khiến quá trình bắt tay không thành công:

  • Không có bộ mật mã giống hệt nhau mà cả hai bên có thể sử dụng
  • Mặc dù bộ mật mã như vậy tồn tại nhưng một hoặc cả hai bên không có chứng chỉ bảo mật để sử dụng bộ mật mã đó.

Phương thức getSupportedCipherSuites của lớp SSLSocket trả về một mảng chuỗi chứa các nhóm bộ Cipher được hỗ trợ bởi đối tượng SSLSocket. Phương thức setEnabledCipherSuites(String[] suites) của lớp SSLSocket thiết lập các nhóm bộ mật mã có thể sử dụng được của đối tượng SSLSocket hiện tại. Các nhóm bộ mật mã có thể sử dụng phải là tập hợp con của các nhóm bộ mật mã được hỗ trợ.

Đoạn mã sau chỉ kích hoạt các bộ mật mã có cường độ mã hóa cao, có thể cải thiện tính bảo mật của đầu giao tiếp và cấm những đầu giao tiếp không hỗ trợ mã hóa mạnh kết nối với đầu giao tiếp hiện tại.

                        
                          String[] strongSuites = { "SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA" }; sslSocket.setEnabledCipherSuites(strongSuites);

                        
                      
5.2 Xử lý sự kiện kết thúc bắt tay

Quá trình bắt tay SSL mất nhiều thời gian. Khi quá trình bắt tay SSL hoàn tất, một sự kiện HandshakeCompletedEvent sẽ được phát ra và được giám sát bởi HandshakeCompletedListener. Phương thức addHandshakeCompletedListener của lớp SSLSocket chịu trách nhiệm đăng ký trình nghe HandshakeCompletedListener.

Ví dụ sau đăng ký HandshakeCompletedListener cho SSLSocket.

                        
                          socket.addHandshakeCompletedListener { new HandshakeCompletedListener() { public void handshakeCompleted(HandshakeCompletedEvent event) { System.out.println("Handshake Complete"); System.out.println("Bộ mật mã là:" + event.getCipherSuite()); .out.println("Phiên là:" + event.getSession()); System.out.println("Đối tác giao tiếp là:" + event.getSession().getPeerHost());

                        
                      
5.3 Quản lý phiên SSL

Một chương trình máy khách có thể mở nhiều ổ cắm an toàn vào cùng một cổng trên máy chủ. Nếu bắt tay SSL được thực hiện cho mọi kết nối an toàn, hiệu quả liên lạc sẽ giảm đi đáng kể. Để nâng cao hiệu quả liên lạc an toàn, giao thức SSL cho phép nhiều SSLSockets chia sẻ cùng một phiên SSL. Trong cùng một phiên, chỉ SSLSocket đầu tiên được mở mới cần thực hiện bắt tay SSL và chịu trách nhiệm tạo khóa và trao đổi khóa. Phần còn lại của SSLSockets chia sẻ thông tin khóa. Nếu máy khách mở nhiều ổ cắm an toàn vào cùng một cổng trên máy chủ trong một khoảng thời gian hợp lý, JSSE sẽ tự động sử dụng lại phiên đó.

Phương thức getSession của SSLSocket trả về phiên mà SSLSocket thuộc về. Phương thức setEnableSessionCreation(boolean flag) của SSLSocket xác định xem SSLSocket có cho phép tạo phiên mới hay không. Giá trị mặc định của cờ là đúng. Nếu tham số cờ là đúng thì đối với SSLSocket mới được tạo, nếu hiện có phiên có sẵn, hãy tham gia trực tiếp vào phiên đó, nếu không có phiên nào có sẵn, hãy tạo một phiên mới. Nếu cờ là tham số sai thì đối với SSLSocket mới được tạo, nếu hiện có phiên có sẵn, nó sẽ được thêm trực tiếp vào phiên. Nếu không có phiên có sẵn thì SSLSocket không thể giao tiếp an toàn với bên kia.

Phương thức startHandshake của SSLSocket thực hiện bắt tay SSL một cách rõ ràng. Phương thức này có các mục đích sau:

  • Làm cho phiên sử dụng khóa mới
  • Làm cho phiên sử dụng bộ mật mã mới
  • Khởi động lại một phiên. Để đảm bảo rằng phiên ban đầu không được sử dụng lại, trước tiên phiên ban đầu phải bị vô hiệu hóa.
                        
                          socket.getSession().invalidate(); socket.startHandshake();

                        
                      
5.4 Chế độ máy khách

Trong hầu hết các trường hợp, máy khách không cần xác nhận danh tính của mình với máy chủ, vì vậy khi thiết bị đầu cuối liên lạc không cần xác nhận danh tính của nó với bên kia, nó được cho là ở chế độ máy khách, nếu không thì nó được cho là ở chế độ chế độ máy chủ. Chỉ một bên trong các bên giao tiếp có thể ở chế độ máy chủ và bên kia ở chế độ máy khách.

Phương thức setUseClientMode(boolean mode) của SSLSocket được sử dụng để đặt chế độ máy khách hoặc chế độ máy chủ. Nếu tham số chế độ là đúng, điều đó có nghĩa là bạn đang ở chế độ máy khách, nghĩa là bạn không cần phải chứng minh danh tính của mình cho bên kia; nếu tham số chế độ là sai, có nghĩa là bạn đang ở chế độ máy chủ, tức là bạn đang ở chế độ máy chủ. , bạn cần chứng minh giá trị của mình với đối phương.

Khi bắt tay SSL ban đầu đã bắt đầu, không được phép gọi phương thức seUseClientMode(boolean mode) của SSLSocket, nếu không sẽ xảy ra ngoại lệ.

Khi SSLSocket ở chế độ máy chủ, bạn cũng có thể quyết định xem có yêu cầu bên kia cung cấp xác thực danh tính hay không thông qua các phương pháp sau:

  • setWantClientAuth(boolean want):: Khi tham số mong muốn là đúng, điều đó có nghĩa là bạn muốn bên kia cung cấp xác thực danh tính. Nếu bên kia không xuất trình chứng chỉ bảo mật, kết nối sẽ không bị gián đoạn và việc liên lạc có thể tiếp tục
    setNeedClientAuth(boolean need): Khi tham số cần là đúng, điều đó có nghĩa là bên kia được yêu cầu cung cấp xác thực danh tính. Nếu bên kia không xuất trình chứng chỉ bảo mật, kết nối sẽ bị gián đoạn và không thể tiếp tục liên lạc.

6. Lớp SSLServerSocket

Lớp SSLServerSocket là một lớp con của lớp ServerSocket nên có nhiều điểm tương đồng trong cách sử dụng chúng. Ngoài ra, lớp SSLServerSocket còn có các phương thức liên quan đến giao tiếp an toàn có tác dụng tương tự như các phương thức cùng tên trong lớp SSLSocket.

7. Lớp SSLEngine

Lớp SSLEngine được sử dụng cùng với lớp SocketChannel để đạt được khả năng liên lạc an toàn không bị chặn. Lớp SSLEngine đóng gói các chi tiết liên quan đến giao tiếp an toàn và đóng gói dữ liệu ứng dụng được ứng dụng gửi vào dữ liệu mạng. Bao bì đề cập đến việc mã hóa dữ liệu ứng dụng, thêm dữ liệu bắt tay SSL và biến nó thành dữ liệu mạng. Lớp SSLEngine cũng có thể mở rộng dữ liệu mạng đã nhận thành dữ liệu ứng dụng. Mở rộng đề cập đến việc giải mã dữ liệu mạng và xóa dữ liệu bắt tay SSL, từ đó khôi phục dữ liệu đó thành dữ liệu ứng dụng mà ứng dụng có thể xử lý. Phương thức bọc của lớp SSLEngine chịu trách nhiệm đóng gói dữ liệu ứng dụng và phương thức unwrap chịu trách nhiệm mở dữ liệu mạng.

                        
                          lớp công khai SSLEngineDemo { ghi nhật ký boolean tĩnh riêng tư = true; riêng tư SSLContext sslc; riêng tư SSLEngine clientEngine; // Công cụ khách hàng riêng tư ByteBuffer clientOut; // Dữ liệu ứng dụng lưu trữ được gửi bởi khách hàng Private ByteBuffer clientIn; máy chủ SSLEngine riêngEngine; //Máy chủ ByteBuffer riêng phía máy chủOut; //Dữ liệu ứng dụng lưu trữ được gửi bởi máy chủ ByteBuffer riêngIn; // Dữ liệu ứng dụng lưu trữ được máy chủ ByteBuffer cTO riêng tư nhận; // Dữ liệu mạng lưu trữ được máy khách gửi đến máy chủ ByteBuffer sTOc riêng tư; // Dữ liệu mạng lưu trữ được máy chủ gửi đến máy khách // Đặt tệp kho khóa và Thư viện tin cậy tập tin và mật khẩu tĩnh riêng tư Chuỗi keyStoreFile = "test.keystore"; chuỗi tĩnh riêng tư TrustStorefile = "test.keystore" chuỗi mật khẩu tĩnh riêng tư = "123456"; main(String args[]) ném Ngoại lệ { SSLEngineDemo demo = new SSLEngineDemo(); } /**Khởi tạo SSLContext*/ public SSLEngineDemo() ném Ngoại lệ { KeyStore ks = KeyStore.getInstance("JKS") ; KeyStore ts = KeyStore.getInstance("JKS"); mật khẩu char[] = passphrase.toCharArray(); ks.load(FileInputStream mới(keyStoreFile), mật khẩu); ts.load(new FileInputStream(trustStoreFile), mật khẩu); mật khẩu); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ts); SSLContext sslCtx = SSLContext.getInstance("TLS"); sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); ; } khoảng trống riêng tư runDemo() ném Ngoại lệ { boolean dataDone = false; /*Tạo SSLEngine phía máy khách và máy chủ*/ serverEngine = sslc.createSSLEnqine(); serverEngine.setUseClientMode(false); serverEngine.setNeedClientAuth(true); "khách hàng", 80); clientEngine.setUseClientMode(true); /*Tạo bộ đệm ứng dụng và bộ đệm mạng cho máy khách và máy chủ*/ SSLSession session = clientEngine.getsSession(); int appBufferMax = session.getApplicationBufferSize(); ByteBuffer.allocate(appBufferMax + 50); serverIn = ByteBuffer.allocate(appBufferMax + 50) cTOs = ByteBuffer.allocateDirect(netBufferMax); sTOc = ByteBuffer.allocateDirect(netBufferMax); clientOut = ByteBuffer.wrap("Xin chào máy chủ, tôi là khách hàng".getBytes()); .wrap("Xin chào khách hàng, tôi là máy chủ".getBytes()); SSLEngineResult clientResult; SSLEngineResult serverResult; while (!isEnqineClosed(clientEngine) || !isEngineClosed(serverEngine)) { log("==================="); dữ liệu ứng dụng clientResult = clientEngine.wrap(clientOut, cTOs); clientResult); // Hoàn thành tác vụ bắt tay runDelegatedTasks(clientResult, clientEngine); // Dữ liệu ứng dụng đóng gói phía máy chủ serverResult = serverEngine.wrap(serverOut, sTOc); nhiệm vụ bắt tay runDelegatedTasks (serverResult, serverEngine cTOs.flip(); sTOc.flip(); log("---------------"); //Client mở rộng dữ liệu mạng clientResult = clientEngine.unwrap(sTOc, clientIn log("client unwrap : ", clientResult); //Hoàn thành nhiệm vụ bắt tay runDelegatedTasks(clientResult,clientEngine); //Máy chủ mở rộng dữ liệu mạng serverResult = serverEngine.unwrap(cTOs, serverIn); log("server unwrap:", serverResult //Hoàn thành nhiệm vụ bắt tay runDeleqatedTasks(serverResult, serverEngine()); sTOc.compact(); if (!dataDone && (clientOut.limit() == serverIn.position()) && (serverOut,limit()=m clientIn.position())) { checkTransfer(serverOut, clientIn); checkTransfer(clientOut, serverIn); log("\tĐóng clientEngine's *OUTBOUND*..." ); clientEngine.closeOutbound(); /**Khi đầu ra và đầu vào của SSLEngine bị đóng, điều đó có nghĩa là SSLEngine đã bị đóng*/ boolean tĩnh riêng tư isEngineClosed(SSLEngine engine) { return(engine.isOutboundDone() && engine.isInboundDone()); } /**Execute Nhiệm vụ bắt tay SSL*/ riêng tư tĩnh void runDelegatedTasks(kết quả SSLEngineResult, công cụ SSLEngine) ném Ngoại lệ { if(result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while((runnable = engine.getDelegatedTask()) != null) { log("\trunning task được ủy quyền..."); ); } HandshakeStatus hsStatus = engine.getHandshakeStatus(); if(hsStatus == HandshakeStatus.NEED_TASK) { ném ngoại lệ mới("bắt tay không cần thêm tác vụ"); } log("\tnew HandshakeStatus:" + hsStatus); bộ đệm giống nhau*/ riêng tư void void checkTransfer(ByteBuffer a, ByteBuffer b) ném Ngoại lệ { a.flip(); if(!a.equals(b)) { ném Ngoại lệ mới("pata không truyền rõ ràng"); } else { log("\tData được truyền rõ ràng" } a.position(a.limit()); b.position(b.limit()); a.limit(a.capacity()); b.limit(b.capacity()); } kết quả boolean tĩnh riêngOnce = true; /**Nhật ký xuất ra, in kết quả của SSLEngineResult*/ Private static void log(String str, SSLEngineResult result) { if(resultOnce) { resultOnce = false; System.out.println("Định dạng của SSLEngineResult là: \n " +"\t\"getStatus() / getHandshakeStatus()\"+\n" +"\t\"bytesConsumed() / bytesProduced()\"\n"); } HandshakeStatus hsStatus = result.getHandshakeStatus(); log(str + result,getStatus() + "/" + hsStatus + "," + result,bytesConsumed() + "/" + result.bytesProduced() + " byte"); (hsStatus == HandshakeStatus.FINISHED) { log("\t...sẵn sàng cho dữ liệu ứng dụng"); } } /**Nhật ký đầu ra*/ nhật ký void tĩnh riêng tư(String str) { System.out.printin(str) ;isOutboundDone() && engine.isInboundDone()); } /**Trình duyệt SSL không hoạt động*/ private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) throws Exception { if(result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while((runnable = engine.getDelegatedTask()) != null) { log("\trunning delegated task..."); runnable.run(); } HandshakeStatus hsStatus = engine.getHandshakeStatus(); if(hsStatus == HandshakeStatus.NEED_TASK) { throw new Exception("handshake không cần thêm tác vụ"); } log("\tnew HandshakeStatus:" + hsStatus); } } /**判断两个缓冲区内容是否相同*/ Private static void checkTransfer(ByteBuffer a, ByteBuffer b) ném Ngoại lệ { a.flip(); b.flip(); if(!a.equals(b)) { ném Ngoại lệ mới("pata không chuyển sạch"); } else { log("\tDữ liệu được truyền sạch"); } a.position(a.limit()); b.position(b.limit()); a.limit(a.capacity()); b.limit(b.capacity()); } kết quả boolean tĩnh riêngOnce = true; /**输出日志,打印SSLEngineResult的结果*/ Private static void log(String str, SSLEngineResult result) { if(resultOnce) { resultOnce = false; System.out.println("Định dạng của SSLEngineResult là: \n" +"\t\"getStatus() / getHandshakeStatus()\"+\n" +"\t\"bytesConsumed() / bytesProduced()\"\n"); } HandshakeStatus hsStatus = result.getHandshakeStatus(); log(str + result,getStatus() + "/" + hsStatus + "," + result,bytesConsumed() + "/" + result.bytesProduced() + "bytes"); if (hsStatus == HandshakeStatus.FINISHED) { log("\t...ready for application data"); } } /**Ready to the application*/ private static void log(String str) { System.out.printin(str); } }isOutboundDone() && engine.isInboundDone()); } /**Trình duyệt SSL không hoạt động*/ private static void runDelegatedTasks(SSLEngineResult result, SSLEngine engine) throws Exception { if(result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { Runnable runnable; while((runnable = engine.getDelegatedTask()) != null) { log("\trunning delegated task..."); runnable.run(); } HandshakeStatus hsStatus = engine.getHandshakeStatus(); if(hsStatus == HandshakeStatus.NEED_TASK) { throw new Exception("handshake không cần thêm tác vụ"); } log("\tnew HandshakeStatus:" + hsStatus); } } /**判断两个缓冲区内容是否相同*/ Private static void checkTransfer(ByteBuffer a, ByteBuffer b) ném Ngoại lệ { a.flip(); b.flip(); if(!a.equals(b)) { ném Ngoại lệ mới("pata không chuyển sạch"); } else { log("\tDữ liệu được truyền sạch"); } a.position(a.limit()); b.position(b.limit()); a.limit(a.capacity()); b.limit(b.capacity()); } kết quả boolean tĩnh riêngOnce = true; /**输出日志,打印SSLEngineResult的结果*/ Private static void log(String str, SSLEngineResult result) { if(resultOnce) { resultOnce = false; System.out.println("Định dạng của SSLEngineResult là: \n" +"\t\"getStatus() / getHandshakeStatus()\"+\n" +"\t\"bytesConsumed() / bytesProduced()\"\n"); } HandshakeStatus hsStatus = result.getHandshakeStatus(); log(str + result,getStatus() + "/" + hsStatus + "," + result,bytesConsumed() + "/" + result.bytesProduced() + "bytes"); if (hsStatus == HandshakeStatus.FINISHED) { log("\t...ready for application data"); } } /**Ready to the application*/ private static void log(String str) { System.out.printin(str); } }\n" +"\t\"getStatus() / getHandshakeStatus()\”+\n" +"\t\"bytesConsumed() / bytesProduced()\"\n"); } HandshakeStatus hsStatus = result.getHandshakeStatus(); log(str + result,getStatus() + "/" + hsStatus + "," + result,bytesConsumed() + "/" + result.bytesProduced() + " bytes"); if (hsStatus == HandshakeStatus.FINISHED) { log("\t...ready for application data"); } } /**Ready time*/ private static void log(String str) { System.out.printin(str); } }\n" +"\t\"getStatus() / getHandshakeStatus()\”+\n" +"\t\"bytesConsumed() / bytesProduced()\"\n"); } HandshakeStatus hsStatus = result.getHandshakeStatus(); log(str + result,getStatus() + "/" + hsStatus + "," + result,bytesConsumed() + "/" + result.bytesProduced() + " bytes"); if (hsStatus == HandshakeStatus.FINISHED) { log("\t...ready for application data"); } } /**Ready time*/ private static void log(String str) { System.out.printin(str); } }

                        
                      

Tạo máy chủ bảo mật dựa trên SSL và máy khách bảo mật

                        
                          lớp công khai EchoServer { cổng int riêng tư = 8000; SSLServerSocket serverSocket riêng tư; EchoServer công khai() ném ngoại lệ { //Nhật ký theo dõi đầu ra Bối cảnh SSLContext = createSSLContext(); (đậu); String[] được hỗ trợ = serverSocket.getSupportedCipherSuites(); serverSocket.setEnabledCipherSuites(supported); } public SSLContext createSSLContext() ném ra ngoại lệ { // Kho khóa chứa chứng chỉ bảo mật được máy chủ sử dụng để chứng minh danh tính của nó String keyStoreFile = "test .keystore "; Cụm mật khẩu chuỗi = "123456"; KeyStore ks = KeyStore.getInstance("JKS"); char[] mật khẩu = passphrase.toCharArray(); ks.load(new FileInputStream(keyStoreFile), mật khẩu); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); , mật khẩu); SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(kmf.getKeyManagers(), null, null); // Khi máy khách được yêu cầu cung cấp chứng chỉ bảo mật, máy chủ có thể tạo TrustManagerFactory, // và sử dụng nó để tạo TrustManager, TrustManger Dựa trên thông tin trong KeyStore được liên kết // Quyết định xem có tin cậy chứng chỉ bảo mật do khách hàng cung cấp hay không // Kho khóa chứa chứng chỉ bảo mật được khách hàng sử dụng để chứng minh danh tính của nó // Chuỗi TrustStorefile = "test.keystore"; //KeyStore ts = KeyStore.getInstance("JKS"); //ts.load(new FileInputStream(trustStoreFile), mật khẩu); //TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509") ; //tmf.init(ts); //sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return sslContext; } printWriter riêng getWriter(Socket socket) ném IOException { OutputStream socketOut = socket.getOutputStream(); true); } riêng BufferedReader getReader(Ổ cắm ổ cắm) ném IOException { inputStream socketIn = socket.getInputstream(); return new BufferedReader(new inputStreamReader(socketIn)); } public void service() { while (true) { Ổ cắm socket = null thử { //Đợi ổ cắm kết nối máy khách đặc biệt = serverSocket.accept(); BufferedReader br = getReader(socket); PrintWriter pw = getWriter(socket); Chuỗi tin nhắn = null; while ((msg = br.readLine()) != null) { System.out.println(msg); } } bắt (IOException e) { e.printStackTrace(); } cuối cùng { thử { if(socket != null) socket.close(); //Ngắt kết nối} bắt (IOException e) { e.printStackTrace(); } } } } public static void main(String args[]) ném Ngoại lệ { new EchoServer().service();

                        
                      
                        
                          lớp công khai EchoClient { máy chủ chuỗi riêng tư = "localhost"; cổng int riêng = 8000; ổ cắm SSLSocket riêng; public EchoClient() ném IOException { SSLContext context = createSSLContext(); Nhà máy SSLSocketFactory = context.getSocketFactory(); socket = (SSLSocket)factory.createSocket(host,port); Stringl] được hỗ trợ = socket.getSupportedCipherSuites(); socket.setEnabledCipherSuites(được hỗ trợ); } public SSLContext createSSLContext() ném ngoại lệ { Chuỗi mật khẩu = "123456"; char[] mật khẩu = passphrase.toCharArray(); //设置客户端所信任的安全证书所在的密钥库 Chuỗi TrustStoreFile = "test.keystore"; KeyStore ts = KeyStore.getInstance("JKS"); ts.load(fileinputstream mới(trustStoreFile), mật khẩu)); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ts); SSLContext sslContext = SSLContext. getInstance("SSL"); sslContext.init(null, tmf.getTrustManagers(), null); trả về sslContext; } public static void main(String args[]) throws IOException { new EchoClient().talk(); } public void talk()throws IOException { try { BufferedReader br = getReader(socket); PrintWriter pw = getWriter(socket); BufferedReader localReader = new BufferedReader(new InputStreamReader(System.in)); String msg = null; trong khi((msg = localReader.readLine()) != null) { pw.println(msg); System.out.println(br.readline()); nếu(msg.equals("tạm biệt")) { ngắt; } } } catch(IOException e) { e.printStackTrace(); } finally { try { if(socket != null) socket.close(); //Kết thúc } catch (IOException e) { e.printStackTrace() ; } } } private PrintWriter getWriter(Socket socket) throws IOException { OutputStream socketOut = socket.getoutputstream(); return new PrintWriter(socketOut, true); } private BufferedReader getReader(Socket socket) throws IOException { InputStream socketIn = socket.getInputstream( ); trả về BufferedReader mới(InputStreamReader mới(socketIn)); } }

                        
                      

Cuối cùng, bài viết về lập trình mạng Java - giao tiếp mạng an toàn kết thúc tại đây. Nếu bạn muốn biết thêm về lập trình mạng Java - giao tiếp mạng an toàn, vui lòng tìm kiếm các bài viết về CFSDN hoặc tiếp tục duyệt các bài viết liên quan. tương lai! .

26 4 0
tôi là một con chim nhỏ
Hồ sơ

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá taxi Didi miễn phí
Phiếu giảm giá taxi Didi
Chứng chỉ ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com
Xem sitemap của VNExpress