openssl生成網站證書逐步詳解

完成HTTPS請求的主體

  • 首先是服務端(server),要生成證書請求(csr),提交給CA(Certificate Authority),即證書授權中心,獲得一張證書。這個證書裏面包括了服務端的公鑰,CA使用其私鑰對服務端的公鑰進行加密後得到的簽名。
  • 然後是證書授權中心(CA),負責接收證書請求(包含請求主體的主體信息、公鑰和簽名算法),使用自己的私鑰對請求中的信息進行加密簽名。此前CA需要先給自己頒發一個根證書,下面還要用來給其他主體的證書請求頒發證書。
  • 最後是客戶端(client),在訪問HTTPS網站時,收到了服務端發來的證書,此時客戶端要向CA查詢這張證書是否合法,從而決定是否與此網站通信。這是就要用CA的公鑰來解密這張證書中的數字簽名,看是否與證書的明文部分一致。這意味着CA的根證書需要保存在瀏覽器中,各大瀏覽器開發商一般都會把根證書內置在瀏覽器中

openssl基礎命令

openssl genrsa命令:https://blog.csdn.net/as3luyuan123/article/details/14498397?utm_source=blogxgwz3
openssl req 命令:https://blog.csdn.net/lsyyff23/article/details/79445370
openssl x509 命令:https://blog.csdn.net/u010846177/article/details/54356897

openssl模擬該過程

  • openssl安裝
$ sudo apt-get install openssl
$ sudo apt-get install libssl-dev
  • 生成CA根證書
    • 創建私鑰:
      $ openssl genrsa -out ca-key.pem 1024
    • 創建 csr 證書請求
      $ openssl req -new -key ca-key.pem -out ca-req.csr -subj "/C=CN/ST=BJ/L=BJ/O=BD/OU=BD/CN=CS"
    • 生成根證書(用自己(CA)的私鑰來簽名):
      $ openssl x509 -req -in ca-req.csr -out ca-cert.pem -signkey ca-key.pem -days 3650
  • 生成服務端證書
    • 創建服務端私鑰:
      $ openssl genrsa -out server-key.pem 1024
    • 創建csr證書請求:
      $ openssl req -new -out server-req.csr -key server-key.pem -subj "/C=CN/ST=SH/L=SH/O=TM/OU=TM/CN=CS"
    • 生成證書(用根證書和CA的私鑰來簽名):
      $ openssl x509 -req -in server-req.csr -out server-cert.pem -signkey server-key.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -days 3650
  • 確認證書
    openssl verify -CAfile ca-cert.pem server-cert.pem

基於Python的簡單HTTPS服務

調用Python的http,ssl庫,實現簡單的HTTPS服務,這裏提供服務端的證書與私鑰即可。這裏的CA證書是我們本地生成的,瀏覽器不會信任,訪問時點擊允許訪問不安全的網站即可。若要避免這一問題,需要在網上購買權威CA的服務,生成被瀏覽器信任的證書。

下面的小程序實現了GET請求的處理,將調用其他Python程序來進一步處理請求。

#-*-coding:utf-8-*-
from http import server
from http.server import BaseHTTPRequestHandler  
import socket  
import ssl  
import sys
import subprocess
import os

class RequestHandler(BaseHTTPRequestHandler):
	def send_content(self, page, status = 200):
		self.send_response(status)
		self.send_header("Content-type", "text/html")
		self.send_header("Content-Length", str(len(page)))
		self.end_headers()
		# print(type(page))
		if type(page) == type('a'):
			self.wfile.write(bytes(page, encoding = 'utf-8'))
		elif type(page) == type(b'1'):
			self.wfile.write(page)
		print("response: ",page)

	def runpy(self, path, query):
		try:
			res = subprocess.check_output("python %s %s"%(path, query),
										stderr = subprocess.STDOUT,
										shell = True)
			self.send_content(res)
		except subprocess.CalledProcessError as exc:
			res = "returncode: %r" % exc.returncode
			res += "cmd: %s" % exc.cmd
			res += "output: %s" % exc.output
			self.send_content(res)

	def do_GET(self):
		print("self.path",self.path)
		if "?" in self.path:
			path, query = self.path.split('?')
			self.full_path = os.getcwd() + path
			if (os.path.isfile(self.full_path) and self.full_path.endswith('.py')):
				print("runing %s"%path.lstrip('/'))
				self.runpy(path.lstrip('/'), query)
			else:
				print("%s not exist"%path)
				self.send_content("%s not exist"%path)
		else:
			self.send_content("<h1 align='center'>Hello, World</h1>")

port = 443
try:
	httpd = server.HTTPServer(("0.0.0.0", port),RequestHandler)
	print("Listening on 0.0.0.0:443")
except:
	port = 8443
	httpd = server.HTTPServer(("0.0.0.0", port),RequestHandler)
	print("Listening on 0.0.0.0:8443")

context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain("server-cert.pem","server-key.pem") #自己添加
httpd.socket = context.wrap_socket(httpd.socket, server_side = True)

try:
	print("HTTTPS Server listening on 0.0.0.0:%d"%port)
	httpd.serve_forever()
except KeyboardInterrupt:
	print("User quit.")
	exit()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章