【ssl认证、证书】TLS/SSL双向认证概念、openssl genrsa示例

文章目录

  • 一、PKI、CA、TLS/SSL、OpenSSL等概念及原理
  • 二、基于OpenSSL生成自签名证书
    • 1、明确X509证书标准的两种编码格式PEM和DER
    • 2、证书相关文件常用扩展名
  • 三、WebSocket基于TLS/SSL双向认证通信(Python示例)
  • 参考

相关文章:
//-----------Java SSL begin----------------------
【ssl认证、证书】SSL双向认证和SSL单向认证的区别(示意图)
【ssl认证、证书】java中的ssl语法API说明(SSLContext)、与keytool 工具的联系
【ssl认证、证书】SSL双向认证java实战、keytool创建证书
【ssl认证、证书】Wireshark抓包分析
【ssl认证、证书】 查看keystore文件内容
//------------Java SSL end--------------------------

//-----------下面的是CA证书和openssl相关的知识--------------
【ssl认证、证书】TLS/SSL双向认证概念、openssl genrsa示例
【ssl认证、证书】openssl genrsa 命令详解
【ssl认证、证书】SSL 证书基本概念、证书格式、openssl和keytool的区别

一、PKI、CA、TLS/SSL、OpenSSL等概念及原理

  • CA 证书签发机构,自己持有私钥,创建根证书,并把根证书发送给操作系统厂商,内置于操作系统中。CA利用根证书和私钥,签发企业证书
  • TLS/SSL 是认证协议,https采用这种协议,可以保证通信安全
  • OpenSSL 是生成证书、根证书、数字签名的工具包

二、基于OpenSSL生成自签名证书

1、明确X509证书标准的两种编码格式PEM和DER

  • PEM(Privacy Enhanced Mail):内容是Base64编码的ASCII码文件,通常用于证书颁发机构(Certificate Authorities,CA),扩展名可为.pem/.crt/.cer/.key。纯文本以"-----BEGIN XXX-----" 和 "-----END XXX-----"作开头和结尾。服务器认证证书,中级认证证书(可理解为公钥)和私钥都可以储存为PEM格式。Apache和类似的服务器使用PEM格式证书。
  • DER(Distinguished Encoding Rules):使用二进制,扩展名为.der,但也经常使用.cer用作扩展名,所有类型的认证证书和私钥都可以存储为DER格式。Java是其典型使用平台。

2、证书相关文件常用扩展名

注意:这个扩展名是随便叫的,你叫.txt也行,这里是为了规范使用,便于识别,尽量采用下面标准后缀

  • CRT :多用于*NIX系统,多数使用PEM编码,DER编码也有使用;
  • CER :多用于Windows系统,多数使用DER编码,PEM编码也有使用;
  • KEY:通常用于存放公钥或者私钥,非X509证书,PEM/DER编码均有;
  • CSR(Certificate Signing Request):证书签名请求,不是证书,用于证书颁发机构申请签名证书,是一个公钥和附加信息,在生成CSR时,还会生成一个私钥;
  • PFX/P12(predecessor of PKCS#12):CRT和KEY存在一个PFX文件中,通常会有一个”提取密码“,用于提取证书内容,使用的DER编码;
  • JKS (Java Key Storage):Java的专利,与OpenSSL关系不大,使用专用工具keytool生成具,可将PFX转为JKS。

使用openssl自签名产生SSL证书过程如下图:
【ssl认证、证书】TLS/SSL双向认证概念、openssl genrsa示例_第1张图片

OpenSSL执行过程:

//1、生成CA秘钥,过程中要输入密码,这里用123456

openssl genrsa -des3 -out ca.key 2048

【ssl认证、证书】TLS/SSL双向认证概念、openssl genrsa示例_第2张图片

查看ca.key的内容:

[root-controller-3:/home/ubuntu/test]$ cat ca.key
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,6034ECBB98C5D57B

Wnd0rLwfSvwpaQDPULnGyyzHp8j4ZG/q0vcTl/82MBpUIX5H+nQO1fjlZlnQUPR2
RnVSm+YAQET4MFERxQrJ4k4cmm3kpdMs/JhoEiWGPLGCJqPiXXhGsyNsdGAn/NHQ
IpUBrXZtxOegi2o5+YBgqwEpUSdy2/GI0WrcZGLeQtXQCLYxo/2ag//KQn4UBkoE
pJnZ+ChIVTr7qqwx97DWjHXqq6YQ684V/sTrypnTrcdtiTl1GKm30DaJWFA+pma0
du4vi2T0fkthwAhBmRbgyPrV0pk6cM6V+3lhX/3k9Shl1MQ1r5jyBCwmG5qmVPt7
tFgk2fCo0K2c5gkSK0oVKzx42TaHLHP5PCV3J+CHtkFmNrj/jX0UYUhucTjhQq0B
es2nGYo9lCzTY75qv4tfbXuKGdWmjXV0xWz/NZlR0CM7dbvHXg0NbtGkxX6ukhAu
AI3FATZwMndOTJpNwt+y2xrnjz2xVjJA9M4VbNkODEioHkhyDJZ8tnFzvywD0Svz
qkx38BAa0ecH03eLfdHiwejgjU+DQv4FGkrAGhMrYdq15gyjvDW2mDloNzf/ZFXX
r1Byqomoki/k5Cs3rdVA6SUnu5EbBQ0L4G1NUapgSotGmvG46rWwNPF7y+zAb/Hk
DuYHz13w6X0VQiiFs8G7PrZfIj81zFNTrWUzJlgozSfLOG9Ay82b9Bs6VN1130pm
UYYnSdOlNtsmlcTujXJI0OWiCq+Vvdh+j6iLIhQ/lT3srxY6R9RkV3nxgP04Xf36
0tXeONrxfp3X8SWw4WapjTAbvDueHr0yO2XjJRseP2wHEjYf4X6oqsF5A1GFcgDx
V2FA2IoRTSKkF3FZYu03QzZ6C+a7BDYNyerL5xQa6R2JLJWTVQBRBS1mH0d8flpa
X+AQUu6oI8wPmqIDw8Gupai5+TUTy8wVIUbD7NNH98Ow0KMM6WaHIlduAsy3jjY1
vJaCu/wDCR2madmWDxOlcKyXjcmsK/SexdJjJH6WkLEfKNm3Jby6Xkf49Igk//mt
BhDNZHrYKwBlF1hGMEMQ9MCorZND84nNoY+iSFS5noGhy7/Z9v8QJLXYe9tOMU7H
e/IYZa+IgUaeU/kXapWmQ53zDRQIKkvflWkoZlMEMrG1eYryQ4Cs87474O5RN3mn
g29L9OceSTQlwFG5oD567RNcips5xEYTDXtAq0hu8j8iwYkCPNceQyaum+4MvbYS
oiBHbd+N+7NCaIxs9RBM2cqqgOf0EMgbV2rNtJZHvL6MlxD66eFxNihe4u7xnTiZ
pqLEeihjKxTWbvPx0kKdcw9f2uCnmZtGcYSeZSmOfOQDdbw3WMyBsJBkC9+2+J2o
CRkCl90PiE7i4S/hR/0m7ONLqmKqHsuSj3Ai6nL8iJNJDMsJIp+miVTlFZhqFsag
6/mqIq3bYwQRTzF3L4yGII2iSXmW+p2obnz7YSlE32+cTcbvOm4LoPrcA878aUOD
CShHY5dO1FKzgq0hhoEVcSnnl61ORZJpH0HbarngKX7etsyMLq47OR7trdMBWI3O
Es6lueObyjP03bcT2lTF524f58hYIEVRmlPmEM7z9fDs0OH1VDPOA9xbLXCWjTV8
-----END RSA PRIVATE KEY-----

//2、生成CA证书请求文件,过程中输入密码:123456

openssl req -new -out ca.csr -key ca.key -keyform PEM -subj "/C=CN/ST=省/L=城市/O=单位/OU=部门/CN=域名或ip"

keyform和subj都是可选参数,只是提供更完善信息而已

.csr 是证书请求文件,是由 RFC 2986定义的PKCS10格式,包含部分/全部的请求证书的信息,比如,主题, 机构,国家等,并且包含了请求证书的公玥,这些被CA中心签名后返回一张证书。返回的证书是公钥证书(只包含公玥不含私钥)。

也就是说公司名称等这些参数是放在请求文件中的,并且含有公钥,一并交给CA机构,公钥怎么来的?是利用私钥生成的,因此这个步骤入参需要私钥

证书签名请求是申请人向证书颁发机构发送的一条消息,用于申请数字身份证书。

有 CSR 必定有 KEY,是成对的,CSR 最终变成为证书 crt,和私钥 key 配对使用。证书下发后,CSR 就没有用了,只是在交时候需要。

查看ca.csr:

[root-controller-3:/home/ubuntu/test]$ cat ca.csr
-----BEGIN CERTIFICATE REQUEST-----
MIICyDCCAbACAQAwgYIxCzAJBgNVBAYTAkNOMQ8wDQYDVQQIDAbDp8KcwoExFTAT
BgNVBAcMDMOlwp/CjsOlwrjCgjEVMBMGA1UECgwMw6XCjcKVw6TCvcKNMRUwEwYD
VQQLDAzDqcKDwqjDqcKXwqgxHTAbBgNVBAMMFMOlwp/Cn8OlwpDCjcOmwojClmlw
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxXTdnBNsceXd5cc8KZPI
dr6wZiAUwYNdnY+eprQXd52CBXhPAiV0VQlJkYfZZqPN60Lyl3KNqLpQIjR4fhka
yr5waeG+D+b9vhPMWPdp6C6xTbZ8bWlXdpWD5iOQUdk8/GAh7GiFZbow7aMoWqTk
TmtZZAU086msZ7VY5ArTy5oiiQNfk+OoRT3Qj2yoAlJTQ2zjbgz8NxK8AU6oaD9U
PoGVTDQkvQ5KhG+KjhQcbZkEb3cd24Q7lsL6WqRdx/c6yOrkpgN/B5rIjVPmVOUx
CFSl/5WapvWd4bBuWn9cODL7YPmGU+2TdqXPzzI1Y714NL/mIIHM9Pnr0XVLIa4g
FwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAC4Xmz9hEb3qw4XBvsmvmK/Zcgiz
eNrkFwccCVOs/BVZcV3dCtBCnAkJzxpM5oR9/7FQPRg70AgRg/uJMeoCZgaTaIOr
vQgdzk49UquLZyJwDpbHc922BbdUSsPj6Y/7PKW8dWrkRtekntA11I6ifam0fgBv
vT4qyqkUFAS/EPPsErldHWLyk/0qJ9pOdam1MuETKvN07Twb5MBGVsDNPpB3eoM9
jXhGWehj0i74sSZb9eJoyDFfdvX1DFWphU+/5Djv4xANiBZbeCFN4FQOGPRS69YU
FRngPtshMVllDSNlmvWZE5Y/mz7p3/3WFn+xCPwbvFazD/+9A8QIuhCPcrQ=
-----END CERTIFICATE REQUEST-----

//3、生成CA自签名 根证书,过程中输入密码:123456

这一步是模拟CA公司执行的命令;之前的步骤私钥和请求文件都是客户自己生成的

openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crt -CAcreateserial

生成了ca.crt ,查看ca.crt内容:

[root-controller-3:/home/ubuntu/test]$ cat ca.crt
-----BEGIN CERTIFICATE-----
MIIDgjCCAmoCCQDrYTDSFjBJdTANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMC
Q04xDzANBgNVBAgMBsOnwpzCgTEVMBMGA1UEBwwMw6XCn8KOw6XCuMKCMRUwEwYD
VQQKDAzDpcKNwpXDpMK9wo0xFTATBgNVBAsMDMOpwoPCqMOpwpfCqDEdMBsGA1UE
AwwUw6XCn8Kfw6XCkMKNw6bCiMKWaXAwHhcNMjMwMjA4MDY1MjM4WhcNMjQwMjA4
MDY1MjM4WjCBgjELMAkGA1UEBhMCQ04xDzANBgNVBAgMBsOnwpzCgTEVMBMGA1UE
BwwMw6XCn8KOw6XCuMKCMRUwEwYDVQQKDAzDpcKNwpXDpMK9wo0xFTATBgNVBAsM
DMOpwoPCqMOpwpfCqDEdMBsGA1UEAwwUw6XCn8Kfw6XCkMKNw6bCiMKWaXAwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFdN2cE2xx5d3lxzwpk8h2vrBm
IBTBg12dj56mtBd3nYIFeE8CJXRVCUmRh9lmo83rQvKXco2oulAiNHh+GRrKvnBp
4b4P5v2+E8xY92noLrFNtnxtaVd2lYPmI5BR2Tz8YCHsaIVlujDtoyhapOROa1lk
BTTzqaxntVjkCtPLmiKJA1+T46hFPdCPbKgCUlNDbONuDPw3ErwBTqhoP1Q+gZVM
NCS9DkqEb4qOFBxtmQRvdx3bhDuWwvpapF3H9zrI6uSmA38HmsiNU+ZU5TEIVKX/
lZqm9Z3hsG5af1w4Mvtg+YZT7ZN2pc/PMjVjvXg0v+Yggcz0+evRdUshriAXAgMB
AAEwDQYJKoZIhvcNAQELBQADggEBAMFNvG5Oma0jS7IUeVJjvJjwVnmS+ICAspVF
I8aKp3ArGYxS26YeTpr3jHznFJTDl6UzLRZfSSmRvk/zsNWIY8GHduq/c9lyQdG3
J1mKmmYgHWDkdyAY353nWUaYJtal6y5e1WhfQ6MyOd9uzigDpkBNFtXhyshcT24/
l64NGUQbvgrvXatbPdJyJf82ZUNGr6jnLL0nQ1ofkQ5D4tTi1Qk/4y6VBzqUQ2Z7
NWrHc3hgp4UylNV4UjM7WJ2nE/MdGMXWaXKSN7lo5bLGfKG9MIiWhXQCk6vTn3++
D9vkZzLLAS/QHw57WzXWOJYEiTt3BYBFcGybdg6y/pJwozy6LJI=
-----END CERTIFICATE-----

//4、生成server端秘钥,过程中输入密码:123456

openssl genrsa -des3 -out server.key 2048    

生成了server.key

//5、生成server证书请求文件,过程中输入密码:123456

openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=省/L=城市/O=单位/OU=部门/CN=域名或ip"

生成了server.csr

//6、生成自签名SSL证书,过程中输入密码:123456

这次和以上不一样,加上了一个中间人 CA ,表示这是由 CA 认可并颁发的证书

openssl x509 -req -in server.csr -out server.crt -signkey server.key -CA ca.crt -CAkey ca.key -days 365 -CAcreateserial

生成了server.crt
注意:生成了证书,证书内含有公钥,因此,不需要单独提供公钥

//7、生成client证书,与生成server证书过程一样,重复4-6步
分别生成 客户端密钥 client.key、客户端请求文件client.csr、客户端证书 client.crt

总结:请求文件是中间临时文件,不会在代码应用中体现,而密钥和证书都会在代码中体现

三、WebSocket基于TLS/SSL双向认证通信(Python示例)

网上有一些http和https的SSL双向认证示例,没有挨个尝试,可自行搜索引擎。这里写一个Websocket的示例,仅供分享。

Python环境:3.6.6
依赖模块:websockets
这里引用了部分Websockets example中的示例代码,感谢!

server.py(server端代码)

#!/usr/bin/env python

import asyncio
import pathlib
import ssl
import websockets

async def hello(websocket, path):
    name = await websocket.recv()
    print(f"< {name}")

    greeting = f"Hello {name}!"

    await websocket.send(greeting)
    print(f"> {greeting}")
//服务端声明CLIENT_AUTH
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
//certfile和keyfile参数为,证书及文件的路径
ssl_context.load_cert_chain(certfile="cert/server.crt",keyfile="cert/server.key")
//load_verify_locations加载客户端证书
ssl_context.load_verify_locations("cert/client.crt")
ssl_context.verify_mode=ssl.CERT_REQUIRED


start_server = websockets.serve(
    hello, "localhost", 1234, ssl=ssl_context
)

asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()

client.py(client端代码)

#!/usr/bin/env python

import asyncio
import pathlib
import ssl
import websockets

//服务端声明SERVER_AUTH,并加载server端证书
ssl_context=ssl.create_default_context(ssl.Purpose.SERVER_AUTH,cafile="cert/server.crt")
ssl_context.check_hostname=False
//certfile和keyfile参数为,证书及文件的路径
ssl_context.load_cert_chain(certfile="cert/client.crt",keyfile="cert/client.key")
ssl_context.verify_mode=ssl.CERT_REQUIRED

async def hello():
    uri = "wss://localhost:1234"
    async with websockets.connect(
        uri, ssl=ssl_context
    ) as websocket:
        name = input("What's your name? ")

        await websocket.send(name)
        print(f"> {name}")

        greeting = await websocket.recv()
        print(f"< {greeting}")

asyncio.get_event_loop().run_until_complete(hello())

参考

手把手实现TLS/SSL双向认证(附Websocket实现代码)

你可能感兴趣的:(ssl,https,服务器,证书)