TLS1.2和TLS1.1的区别

TLS1.2和TLS1.1的区别

参考

TLS/SSL 协议详解 (28) TLS 1.0、TLS 1.1、TLS 1.2之间的区别

区别点

1:对finished报文(Encrypted handshake message)影响

TLS 1.0 TLS 1.1 在计算finish时,进行的是MD5+ SHA1组合方式运算,而在TLS 1.2下,摘要算法变成了单次SHA256。

伪代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
If(version >= TLS1_2)
{


If (cipher.mac == SHA384)
{


restult = SHA384(handshake_in );
}
Else
{
restult = SHA256(handshake_in);
}
}
Else
{
restult = md5(handshake_in) + sha1(handshake_in);
}

其中handshake_in是 字符串常量+所有握手信息(类型为Handshake的message)。

例如

作为client端handshake_in =“client finidhed” + all_handshake
作为Server 端handshake_in = “server finidhed” + all_handshake

注:对于加密套件存在SHA384及其以上的高级摘要算法,无论TLS哪个版本,都用 加密套件指定的 握手摘要算法计算 摘要,如上伪代码所示(RFC上说对于每一种新的算法, 都需要指定default还是SHAXXX,但是在实现上,都是根据MAC是什么,SHAXXX就是什么)。

其实加密套件中指定的摘要算法是用来在加密时进行HMAC的,并不影响握手流程中的运算,但是如果两端协商的加密套件支持SHAXXX,那么必然表示两端支持SHAXXX算法,那么在SHAXXX安全性高于SHA256的情况下,握手阶段需要摘要算法就没必要那么‘死’只用SHA256。当然目前也没有比SHA384更高的了。

总结来说:

1:TLS 1.2需要增加2个字节表明签名算法类型(非对称+摘要)。而TLS1.2之前的协议默认就用md5+sha1的形式计算摘要,非对称算法肯定使用私钥类型对应的算法,这个无需显示表明。

2:ECDSA签名需要特殊对待。


2:对PRF算法的影响

先用伪代码梳理逻辑:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
If(version >= TLS1_2)
{
If (cipher.mac == SHA384)
{
TLS1_2_PRF(SHA384, in, srcret);
}
Else
{
TLS1_2_PRF(SHA256, in, srcret);
}
}
Else
{
TLS1_PRF(MD5,SHA1, in, srcret);
}

1:对于SHA384的判断,上面已经说过,这里不再赘述。
2:可以看到TLS1.2和TLS 1.0 TLS 1.1的PRF实现也不同,参数不同。

TLS 1.2 的PRF
单次P_HASH,P_HASH使用的是SHA256

TLS 1.1 的PRF
两次P_HASH,第一次P_HASH使用的是MD5,以及secret的前半部分;第二次P_HASH使用的SHA1,以及secret的后半部分。两次P_HASH的结果进行亦或(xor),得到最后结果。

注意secret如果是偶数,则正好各一半,如果是奇数:

例如secret是1234567,则前一半 指的是1234,后一半指的是4567,中间一个字节公用。


3:对Certificate verify的影响

Certificate vertify是客户端在发送证书后,为了表明自己是证书的拥有者,用自己的私钥对之前收到、发送的握手信息进行签名。(和finished类似)。

同样签名前,需要对握手信息进行HASH运算。


TLS1.0 TLS1.1:

使用MD5+SHA1的形式对握手信息进行摘要运算,这个流程和计算finished一样,只是不加字符串常量’XXX finished’。

注:有一个例外,对于ECDSA签名算法(客户端证书是ECC证书),只做单次SHA1计算。

TLS 1.2:

TLS 1.2 下, certificate verify报文格式和之前的不同,多出2个字节(Signature Hash Algorithm),表示hash_alg以及sign_alg。具体握手摘要根据hash_alg进行单次计算。

同样,如果加密套件存在SHA384,则使用SHA384


4:对server key exchange的影响

TLS1.2下和 certificate verify类似,报文格式较之前版本有不同。多了2个字节表示HASH算法和签名算法。


5:对加密的影响

这个变化是TLS1.1开始变化的,不是TLS1.2。

为了对抗beast攻击,SSL在加密数据前,需要填充一个BLOCK_SIZE(IV_SIZE)长度的随机数,这个随机值也被作为数据的一部分进行加密,在解密时,同样进行解密,然后丢弃。

CBC下,对于上述这个场景我们其实可以进行优化,这个BLOCK_SIZE的数据对于发送端来说可以不进行加密,然后下一个数据块的Write_IV改成这个随机数,这样CBC模式就可以完整的工作。对于解密方来说,这个BLOCK_SIZE的数据可以不解密,然后解密下一个块时的Read_IV变成这个随机数,CBC模式也能正常工作。减少了一个BLOCK_SIZE的解密、加密数据。详细优化方案见我的博客 http://blog.csdn.net/mrpre/article/details/78093370

Windows+OpenSSL创建自签名证书脚本

Windows+OpenSSL创建自签名证书脚本

前言

如果您想经常创建自签名证书,可以使用以下 shell 脚本。您只需要使用要添加到证书的域名或 IP 执行脚本。 将以下 shell 脚本另存为ssl.sh

准备工作

  • Git For Windows
  • Git Bash

脚本

ssl.sh脚本

ssl.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#! /bin/bash
# 自签证书【IP版】
# Grafana
# ./test.sh -co "SOYBEAN" -cou "SOYBEAN" -ccn "192.168.1.1" -cdomain "192.168.1.1" -so "SOYBEAN" -sou "192.168.1.2" -scn "Grafana" -sdomain "192.168.1.2"

if [ -s "$PWD/m_msg.sh" ]; then
source "$PWD/m_msg.sh"
fi
if [ -s "$PWD/common.sh" ]; then
source "$PWD/common.sh"
fi

# 固定参数【按需修改】
_C_C="CN"
_C_ST="ZJ"
_C_L="HZ"

_S_C="CN"
_S_ST="ZJ"
_S_L="HZ"
_S_Days=3650

# 参数

# Root CA
# 根CA 所在 IP/域名
_C_DOMAIN=
# CA组织、单位名称
_C_O=
_C_OU=
# Common Name
_C_CN=
# 签发证书序列号
_C_SRL="rootCA.SRL"


# Server
_S_O=
_S_OU=
# 服务的 Common Name
_S_CN=
_S_DOMAIN=

# openssl

_dhparamFlag=

# 参数获取

# Setup getopt.
long_opts="co:,cou:,ccn:,cdomain:,so:,sou:,scn:,sdomain:,dhparam"
getopt_cmd=$(getopt -a -o : --l "$long_opts" \
-- "$@") ||
{
echo -e "\nERROR: Getopt failed. Extra args\n"
exit 1
}

eval set -- "$getopt_cmd"
while true; do
case "$1" in
--co)
_C_O="$2"
shift
;;
--cou)
_C_OU="$2"
shift
;;
--ccn)
_C_CN="$2"
shift
;;
--cdomain)
_C_DOMAIN="$2"
shift
;;
--so)
_S_O="$2"
shift
;;
--sou)
_S_OU="$2"
shift
;;
--scn)
_S_CN="$2"
shift
;;
--sdomain)
_S_DOMAIN="$2"
shift
;;
--dhparam)
_dhparamFlag="1"
;;
--)
shift
break
;;
esac
shift
done

if [ ${#_C_DOMAIN} -lt 1 ]; then
printERROR "错误:未提供【C_DOMAIN】参数!"
exit 1
elif [ ${#_C_O} -lt 1 ]; then
printERROR "错误:未提供【C_O】参数!"
exit 1
elif [ ${#_C_OU} -lt 1 ]; then
printERROR "错误:未提供【C_OU】参数!"
exit 1
elif [ ${#_C_CN} -lt 1 ]; then
printERROR "错误:未提供【C_CN】参数!"
exit 1
elif [ ${#_S_O} -lt 1 ]; then
printERROR "错误:未提供【S_O】参数!"
exit 1
elif [ ${#_S_OU} -lt 1 ]; then
printERROR "错误:未提供【S_OU】参数!"
exit 1
elif [ ${#_S_CN} -lt 1 ]; then
printERROR "错误:未提供【S_CN】参数!"
elif [ ${#_S_DOMAIN} -lt 1 ]; then
printERROR "错误:未提供【S_DOMAIN】参数!"
fi


# 根CA 所在 IP/域名 格式化【处理特殊符号】替换".""-"
_C_DOMAINFORMAT=$(getFormaterStr "$_C_DOMAIN");
# 根CA 私钥、证书文件名称
_C_FileName="${_C_DOMAINFORMAT}_RootCA"
# 根CA 输出文件夹路径【默认为_C_DOMAINFORMAT】
_FilePath="./${_C_DOMAINFORMAT}"
# 根 CA 证书、私钥路径【默认目录为根据_FilePath】
_CAKey="${_C_FileName}.key"
_CACrt="${_C_FileName}.crt"


# 脚本工作目录
work_path=$(dirname "$(readlink -f "$0")")
printINFO "脚本工作目录:$work_path"

# 这里的-x 参数判断 $FilePath 是否存在并且是否具有可执行权限,不存在创建目录,存在输出路径;
if [ ! -x "$_FilePath" ]; then
mkdir "$_FilePath" && cd "$_" && printINFO "文件输出目录:$PWD"
else
cd "$_FilePath" && printINFO "文件输出目录:$PWD"
fi

# Server 证书序列号,默认1【十进制】
SERIAL_NUM=$(getSerialNum) ; printINFO "Server 证书序列号:$SERIAL_NUM"

# Server 私钥、证书文件名称
# 生成文件名称格式为:$_C_DOMAINFORMAT_$_S_CN
_S_FileName="${_C_DOMAINFORMAT}_"$(getFormaterStr "$_S_CN");

#当前命令行所在路径是否存在根 CA 证书和私钥
FileFLAG="true"

if [ ! -s "$_CAKey" ]; then
printERROR "根 CA 私钥 ${_CAKey} 不存在";FileFLAG="false"
elif [ ! -s "$_CACrt" ]; then
printERROR "根 CA 证书 ${_CACrt} 不存在";FileFLAG="false"
else
FileFLAG="true"
fi

if [ $FileFLAG = "true" ]; then
printOK "文件已存在,使用下列文件创建SSL证书:根CA证书:${_CAKey},根CA私钥:${_CACrt} "
else
printINFO "创建根 CA 证书和 CA 私钥 "
# 创建根 CA 证书和 CA 私钥【-nodes:无密码】
openssl req -x509 \
-sha256 -days 3560 \
-nodes \
-newkey rsa:2048 \
-subj "//C=${_C_C}/C=${_C_C}/ST=${_C_ST}/L=${_C_L}/O=${_C_O}/OU=${_C_OU}/CN=${_C_CN}" \
-keyout "${_C_FileName}".key -out "${_C_FileName}".crt
fi



printOK "生成 Server 私钥 : ${_S_FileName}.key"
# 生成 Server 私钥

openssl genrsa -out "${_S_FileName}".key 2048

printOK "创建 csr 配置: csr.conf "
# 创建 csr 配置

cat >csr.conf <<EOF
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = $_S_C
ST = $_S_ST
L = $_S_L
O = $_S_O
OU = $_S_OU
CN = $_S_CN

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
#DNS.1 = ${_S_DOMAIN}
IP.1 = ${_S_DOMAIN}

EOF

printOK "使用 Server 私钥创建 CSR 请求"
# 使用Server 私钥创建 CSR 请求

openssl req -new -key "${_S_FileName}".key -config csr.conf -out "${_S_FileName}".csr

printOK "为 Server CSR 请求创建一个外部配置文件:cert.conf"
# 为 Server CSR 请求创建一个外部配置文件

cat >cert.conf <<EOF

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
#DNS.1 = ${_S_DOMAIN}
IP.1 = ${_S_DOMAIN}

EOF

printOK "使用自签名 CA ${_CACrt} 创建 SSl证书 :${_S_FileName}.crt"
# 使用自签名 CA 创建 SSl证书

openssl x509 -req \
-in "${_S_FileName}".csr \
-CA "${_C_FileName}".crt -CAkey "${_C_FileName}".key \
-days "${_S_Days}" \
-sha256 -extfile cert.conf \
-CAcreateserial \
-set_serial "${SERIAL_NUM}" \
-out "${_S_FileName}".crt

printOK "合成 pkcs#12 证书"
# 转换证书编码格式
# 合成 pkcs#12 证书(含私钥和CA 证书)
openssl pkcs12 -export -name "${_S_CN}" -caname "${_C_CN}" \
-in "${_S_FileName}".crt \
-inkey "${_S_FileName}".key \
-nodes \
-password pass: \
-chain \
-CAfile "${_C_FileName}".crt \
-out "${_S_FileName}".pfx

if [ $_dhparamFlag ]
then
openssl dhparam 2048 -check -out dhparam.pem ; printOK "已生成dhparam.pem ! "
fi

printSUCCESS "CA 证书内容:"
openssl x509 -in "${_C_FileName}".crt -noout -text

printSUCCESS "SSl证书内容:"
openssl x509 -in "${_S_FileName}".crt -noout -text

printSUCCESS "CRT证书链 合成"
cat "${_S_FileName}".crt "${_C_FileName}".crt > "${_S_FileName}_ALL".crt

printSUCCESS "CRT证书链 合成内容:"
openssl x509 -in "${_S_FileName}_ALL".crt -noout -text

m_msg.sh脚本

m_msg.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#! /bin/bash

# echo 颜色样式
OK="\033[42;37m "
# OK="\033[32m "
SUCCESS="\033[42;37m "
INFO="\033[34m "
ERROR="\033[41;30m "
RESET="\033[0m "

printOK() {
echo -e "${OK}==== $* ====${RESET}"
}
printSUCCESS() {
echo -e "${SUCCESS}==== $* ====${RESET}"
}
printINFO() {
echo -e "${INFO}==== $* ====${RESET}"
}
printERROR() {
echo -e "${ERROR}==== $* ====${RESET}"
}

common.sh脚本

common.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#! /bin/bash

# 方法

# dec to hex
dec2hex() {
printf "%x" "$1"
}

# rootCA.SRL获取证书序列号【十进制数】,并更新数值
# 根据文件中的数值返回对应的十六进制值
# 文件不存在或无值,默认返回 0x1
getSerialNum() {
if [ ! -s "rootCA.SRL" ]; then
cat >rootCA.SRL <<EOF
1
EOF
else
num=$(<rootCA.SRL) &&
cat >rootCA.SRL <<EOF
$((num + 1))
EOF
fi

#十进制转十六进制
strserialnum=$(<rootCA.SRL)
printf "%s""$(dec2hex "$strserialnum")"
}

getFormaterStr() {
para=$1
for char in "." ":" "\\" "*" "?"; do
para=${para//"$char"/-}
done
echo "$para"
}

ssl.sh 脚本的使用

1
./ssl.sh -co "SOYBEAN" -cou "SOYBEAN" -ccn "192.168.1.1" -cdomain "192.168.1.1" -so "SOYBEAN" -sou "192.168.1.2" -scn "Grafana" -sdomain "192.168.1.2"

该脚本将创建我们使用各个命令创建的所有证书和密钥。 SSL 证书和私钥使用您作为脚本参数传递的IP命名。


Sign.sh脚本【按需修改脚本内容,执行脚本生成证书,可生成V1版本证书,用于兼容特殊环境。】

下列脚本生成了CA根证书 以及CAS服务证书:

Tips:通过-extfile x509.ext -extensions ca该参数,可以控制生成的证书是否添加证书拓展属性,该参数行默认添加,可以自行移除,移除后生成的证书为V1版本,无拓展属性。

sign.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#! /bin/bash
# V1证书 移除此参数:-extfile x509.ext -extensions ca
# https://www.openssl.org/docs/man3.0/man1/openssl-x509.html#-extfile
# https://***/openssl-x509.html#-req
cat >x509.ext <<EOF

[ ca ]
# X509 extensions for a ca
keyUsage = critical, cRLSign, keyCertSign
basicConstraints = CA:TRUE, pathlen:0
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer:always

[ server ]
# X509 extensions for a server
keyUsage = critical,digitalSignature,keyEncipherment
extendedKeyUsage = serverAuth,clientAuth
basicConstraints = critical,CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always

EOF
# CA 根证书
openssl req -new -sha256 -nodes -newkey rsa:2048 \
-subj "//C=CN/C=CN/ST=ZJ/L=HZ/O=SOYBEAN/OU=SOYBEAN/CN=SOYBEANCA" \
-keyout CA.key \
-out CA.csr \

openssl x509 -req -sha256 -days 3650 \
-extfile x509.ext -extensions ca \
-in CA.csr \
-signkey CA.key \
-out CA.pem

# CAS
openssl req -new -sha256 -nodes \
-newkey rsa:2048 \
-subj "//C=CN/C=CN/ST=ZJ/L=HZ/O=SOYBEAN/OU=SOYBEAN/CN=CASSERVER" \
-keyout CAS.key \
-out CAS.csr \

openssl x509 -req -sha256 \
-CA CA.pem -CAkey CA.key \
-days 3650 -CAcreateserial -CAserial CA.srl \
-extfile x509.ext -extensions server \
-in CAS.csr \
-out CAS.pem

openssl pkcs12 -export -nodes -password pass: \
-name "CAS" \
-caname "SOYBEANCA" \
-in CAS.pem -inkey CAS.key \
-chain -CAfile CA.pem \
-out CAS.pfx


笔记

使用自签名证书有什么好处?

使用自签名证书有几个好处:

  1. 您无需依赖第三方来签署您的证书。
  2. 您可以创建和使用自己的证书颁发机构。
  3. 您不必为 CA 的证书付费。
  4. 您可以更好地控制您的证书。

使用自签名证书有什么缺点?

使用自签名证书也有几个缺点:

  1. 您的用户需要在他们的浏览器或应用程序中安装证书。
  2. 您的用户将需要手动信任您的证书颁发机构。
  3. 它们对于面向公众的应用程序不安全。
  4. 除非用户安装它们,否则所有浏览器或操作系统都不信任自签名证书。
  5. 容易受到中间人攻击。

通常,对于需要证明自己身份的应用程序,自签名证书是一个不错的选择。它们也是开发和测试环境的不错选择。但是,它们不应该用于生产应用程序。

组织中的自签名证书

许多组织对其不面向 Internet 的内部应用程序使用自签名证书。这些证书是使用组织的内部 PKI 基础结构生成的。

CRT、CER、PEM

.CRT = CRT扩展用于证书。证书可以被编码为二进制DERASCII PEM

CERCRT扩展几乎是同义词,最常见的于Unix 或类Unix系统。

CER = .crt的替代形式(Microsoft Convention)

可以用微软的工具把CRT文件转换为CER文件(CRT和CER必须是相同编码的,DER或者PEM)。

扩展名为CER的文件可以被IE识别并作为命令调用微软的cryptoAPI(具体点就是rudll32.exe cryptext.dll, CyrptExtOpenCER),进而弹出一个对话框来导入并/或查看证书内容。

查看证书细节

1
openssl x509 -in SOYBEAN.crt -noout -text

转换证书编码格式

.cer、crt 与 pem、pfx

.cer/.crt是用于存放证书,它是2进制形式存放的,不含私钥,含公钥

.pem跟.crt/.cer的区别是它以Ascii码来表示(字符串)

.pfx/.p12用于存放个人证书/私钥,它通常包含保护密码,2进制方式

注:node服务器需要的是.pem格式的私钥与证书,iOS中需要的是.cer二进制格式的证书。

1
2
3
4
5
6
7
8
#   .crt 转 .pem
openssl x509 -in SOYBEAN.crt -inform PEM -outform PEM -out SOYBEAN.pem
# .cer 转 .pem
# openssl x509 -in SOYBEAN.cer -inform PEM -outform PEM -out SOYBEAN.pem
# 合成 pkcs#12 证书(含私钥)
openssl pkcs12 -export -in SOYBEAN.crt -inkey SOYBEAN.key -name SOYBEANAPP -passout pass: -out SOYBEAN.pfx
# 合成 pkcs#12 证书(含私钥和CA 证书)
openssl pkcs12 -export -name SOYBEANAPP -caname CAServer -in SOYBEAN.crt -inkey SOYBEAN.key -nodes -password pass: -chain -CAfile ca.crt -out server-all.pfx

-subj项在Windows的git Bash 里报错

  1. 修改MSYS_NO_PATHCONV环境变量为1
  2. 将第一个/变成//,并将第一个参数重复;看起来像:-subj "/C=CN/ST=ZJ/L=HZ/O=SOYBEAN/OU=SOYBEANDEPT/CN=CASERVER"==>-subj "//C=CN/C=CN/ST=ZJ/L=HZ/O=SOYBEAN/OU=SOYBEANDEPT/CN=CASERVER"

Unable to use -subj with Windows Git Bash

1
2
3
4
5
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt -subj "//C=CN/C=CN/ST=ZJ/L=HZ/O=SOYBEAN/OU=SOYBEANDEPT/CN=CASERVER"
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "//C=CN/C=CN/ST=ZJ/L=HZ/O=SOYBEAN/OU=SOYBEANDEPT/CN=192.168.1.1"
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

输出为pfx文件

生成pfx文件无响应,原来是少了个参数:-passout pass:SomePassword;即使密码为空也需要这个参数。

OpenSSL hangs during PKCS12 export with “Loading ‘screen’ into random state”

1
openssl pkcs12 -export -in server.crt -inkey server.key -name server -passout pass: -out server.pfx

参考

https://www.jianshu.com/p/e5f46dcf4664
https://ningyu1.github.io/site/post/51-ssl-cert/
https://www.cnblogs.com/junjiany/p/6273560.html
https://www.cnblogs.com/f-ck-need-u/p/7113610.html
https://blog.miniasp.com/post/2022/06/14/How-to-request-new-tls-certificate-using-OpenSSL

Windows创建自定义根证书、自签名服务证书【一】

Windows创建自定义根证书、自签名服务证书【一】

Windows创建自定义根证书、自签名服务证书【一】

参考文章

https://devopscube.com/create-self-signed-certificates-openssl

环境

  • Windows 21H2
  • Git For Windows
  • Git Bash

起步

创建自签根证书

我们需要为浏览器创建自己的根 CA 证书以信任自签名证书。因此,让我们首先创建根 CA 证书。 让我们创建一个名为 openssl 的目录来保存所有生成的密钥和证书。

1
mkdir openssl && cd openssl

执行以下openssl命令来创建rootCA.keyrootCA.crt。替换SOYBEANCA为您的域名或 IP 地址,这里用SOYBEAN作为单位和组织名称。

1
openssl req -new -x509 -days 3650 -nodes -subj "//C=CN/C=CN/ST=ZJ/L=HZ/O=SOYBEAN/OU=SOYBEAN/CN=SOYBEANCA" -keyout rootCA.key -out rootCA.crt

创建自签名服务证书

请按照以下步骤创建自签名证书。我们将使用我们在上一步中创建的根 CA 注销证书。

创建自签名服务私钥

1
openssl genrsa -out lis.key 2048

创建”证书签名请求”配置文件

证书签名请求英文名:Certificate signing request

我们将创建一个 lis_csr.conf 文件以包含生成 CSR 的所有信息。将 alt_names节点中的值替换为您的域名或 IP 地址。

lis_csr.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[ dn ]
C = CN
ST = ZJ
L = HZ
O = SOYBEAN
OU = SOYBEAN
CN = 192.168.1.1

[ req_ext ]
subjectAltName = @alt_names

[ alt_names ]
IP.1 = 192.168.1.1
#DNS.1 = site.com

使用自签名服务私钥生成证书签名请求 (CSR)

1
openssl req -new -key lis.key -out lis.csr -config lis_csr.conf

现在我们的文件夹应该有三个文件。lis_csr.conf,lis.csrlis.key

创建自签名服务证书拓展属性配置文件

为 SSL 证书创建lis_cert.conf。将 alt_names节点中的值替换为您的域名或 IP 地址。

lis_cert.conf
1
2
3
4
5
6
7
8
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
IP.1 = 192.168.1.1
#DNS.1 = site.com

使用自签名根证书 生成 自签名服务证书

现在,执行以下命令来生成以rootCA.crtrootCA.key为证书颁发机构,创建自签名证书:lis.crt

1
openssl x509 -req  -days 3650 -CAcreateserial -set_serial 01 -CA rootCA.crt  -extfile lis_cert.conf -CAkey rootCA.key -in lis.csr  -out lis.crt  

上面的命令将生成 lis.crt ,它将与我们的 lis.key 一起使用,以在应用程序中启用 SSL。

tips:-CAcreateserial使用后,需要添加-set_serial 01以避免一些问题的发生。如果不指定serial值,会在输出目录生成一个SRL文件,是openssl跟踪可用于新证书的最新序列号的文件,关于SRL文件的问题,见:https://stackoverflow.com/a/66357989。

结束

执行上述流程后,应该会拥有4个文件:rootCA.crtrootCA.keylis.crtlis.key

认识加密算法

认识加密算法

加密算法

对称加密就是将信息使用一个密钥进行加密,解密时使用同样的密钥,同样的算法进行解密。

非对称加密又称公开密钥加密,是加密和解密使用不同密钥的算法,广泛用于信息传输中。

在现实世界上可作比拟的例子是:

一个传统保管箱,开门和关门都是使用同一条钥匙,这是对称加密

而一个公开的邮箱,投递口是任何人都可以寄信进去的,这可视为公钥;而只有信箱主人拥有钥匙可以打开信箱,这就视为私钥

对称加密

对称密钥算法(英语:Symmetric-key algorithm)又称为对称加密、私钥加密、共享密钥加密,是密码学中的一类加密算法。这类算法在加密和解密时使用相同的密钥,或是使用两个可以简单地相互推算的密钥。事实上,这组密钥成为在两个或多个成员间的共同秘密,以便维持专属的通信联系。

与公开密钥加密相比,要求双方获取相同的密钥是对称密钥加密的主要缺点之一。

对称加密的速度比公钥加密快很多,在很多场合都需要对称加密。

常见的对称加密算法有AES、ChaCha20、3DES、Salsa20、DES、Blowfish、IDEA、RC5、RC6、Camellia。

非对称加密

公开密钥密码学(英语:Public-key cryptography)也称非对称式密码学(英语:Asymmetric cryptography)是密码学的一种算法,它需要两个密钥,一个是公开密钥,另一个是私有密钥;公钥用作加密,私钥则用作解密。使用公钥把明文加密后所得的密文,只能用相对应的私钥才能解密并得到原本的明文,最初用来加密的公钥不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密;不同于加密和解密都使用同一个密钥的对称加密。公钥可以公开,可任意向外发布;私钥不可以公开,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方。

基于公开密钥加密的特性,它还能提供数字签名的功能,使电子文件可以得到如同在纸本文件上亲笔签署的效果。

公开密钥基础建设透过信任数字证书认证机构的根证书、及其使用公开密钥加密作数字签名核发的公开密钥认证,形成信任链架构,已在TLS实现并在万维网的HTTP以HTTPS、在电子邮件的SMTP以SMTPS或STARTTLS引入。

另一方面,信任网络则采用去中心化的概念,取代了依赖数字证书认证机构的公钥基础设施,因为每一张电子证书在信任链中最终只由一个根证书授权信任,信任网络的公钥则可以累积多个用户的信任。PGP就是其中一个例子。

与对称密码学的比较

对称密码是指在加密和解密时使用同一个密钥的方式
公钥密码是指在加密和解密时使用不同密钥的方式

对称密钥加密牵涉到密钥管理的问题,尤其是密钥交换,它需要通信双方在通信之前先透过另一个安全的渠道交换共享的密钥,才可以安全地把密文透过不安全的渠道发送;对称密钥一旦被窃,其所作的加密将即时失效;而在互联网,如果通信双方分隔异地而素未谋面,则对称加密事先所需要的“安全渠道”变得不可行;非对称加密则容许加密公钥随便散布,解密的私钥不发往任何用户,只在单方保管;如此,即使公钥在网上被截获,如果没有与其匹配的私钥,也无法解密,极为适合在互联网上使用。

另一方面,公钥解密的特性可以形成数字签名,使数据和文件受到保护并可信赖;如果公钥透过数字证书认证机构签授成为电子证书,更可作为数字身份的认证,这都是对称密钥加密无法实现的。

不过,公钥加密在在计算上相当复杂,性能欠佳、远远不比对称加密;因此,在一般实际情况下,往往通过公钥加密来随机创建临时的对称秘钥,亦即对话键,然后才通过对称加密来传输大量、主体的数据。

认识ProtoBuf

认识ProtoBuf

参考

深入 ProtoBuf - 简介
深入 ProtoBuf - 编码


初识

何为 ProtoBuf
我们先来看看官方文档给出的定义和描述:

protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等。

Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。

你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序。

简单来讲, ProtoBuf 是结构数据序列化 方法,可简单类比于 XML,其具有以下特点:

  • 语言无关、平台无关。即 ProtoBuf 支持 Java、C++、Python 等多种语言,支持多个平台
  • 高效。即比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单
  • 扩展性、兼容性好。你可以更新数据结构,而不影响和破坏原有的旧程序

关于 ProtoBuf 的一些思考

官方文档以及网上很多文章提到 ProtoBuf 可类比 XML 或 JSON。

那么 ProtoBuf 是否就等同于 XML 和 JSON 呢,它们是否具有完全相同的应用场景呢?

个人认为如果要将 ProtoBuf、XML、JSON 三者放到一起去比较,应该区分两个维度。一个是数据结构化,一个是数据序列化。这里的数据结构化主要面向开发或业务层面,数据序列化面向通信或存储层面,当然数据序列化也需要“结构”和“格式”,所以这两者之间的区别主要在于面向领域和场景不同,一般要求和侧重点也会有所不同。数据结构化侧重人类可读性甚至有时会强调语义表达能力,而数据序列化侧重效率和压缩。

总结

  1. XML、JSON、ProtoBuf 都具有数据结构化和数据序列化的能力
  2. XML、JSON更注重数据结构化,关注人类可读性和语义表达能力。
  3. ProtoBuf 更注重数据序列化,关注效率、空间、速度,人类可读性差,语义表达能力不足(为保证极致的效率,会舍弃一部分元信息)
  4. ProtoBuf 的应用场景更为明确,XML、JSON 的应用场景更为丰富。
2022第一次感染新冠记载

2022第一次感染新冠记载

  • 2022-12-19 周一

早上起床就感觉头有点晕,但影响不大,只是当作起的太早。
到了公司上班后,因为上周已经有同事确定感染,所以公司未开空调,并且打开了窗户;
12月份的杭州+不开空调+开窗,直接导致我吹了一上午的寒风,当时整个人就感觉不对劲,头开始晕晕沉沉,当时也只是以为没有休息好导致的,加上下班后,在路边等公交又吹了几十分钟的寒风。
直接导致我一回到房间,整个人开始出现各种症状,先是头晕加重,身体开始发热,两个小时内,体温从37.5升到了38.5,当时个人感觉还是很好的,只是早早的躺在了床上。

半夜开始,头痛+发热,折腾一晚上没睡着。

  • 2022-12-20 周二

早上起来,整个人头痛欲裂,浑身发热,全身酸痛,体温是38.3,随便吃了点东西就又躺了
中午起来量了下体温,39.4,赶紧吃了颗布洛芬缓释胶囊,又睡下。
到了晚上,体温已经正常,爬起来吃了点东西,玩了会手机后,又吃了颗布洛芬后睡觉。

  • 2022-12-21 周三

早上起来,整个人状态感觉恢复了很多,就是喉咙开始痛起来了,以为退烧了,一量体温还是38.4,期间起床活动,头还是会晕,还是躺了一天,中午的时候,量了下体温,38.9,又起来吃了颗布洛芬。

  • 2022-12-22 周四

早上起来,体温还是38左右,不过没有再上过38.5,也就没再吃退烧药,开始出现其它并发症,开始咳嗽,喉咙也开始痛,喝水像吞刀片,有很明显的气喘、体力不支、心悸的后遗症。不过人也有了点力气,抗原还是两道杠。

  • 2022-12-23 周五

体温在第四天恢复了正常,37左右,低烧,整个人也恢复了精神,基本正常了。


后遗症有:

  • 喉咙痛
  • 咳嗽
  • 体力虚弱
  • 胸闷、心悸
  • 流涕
  • 用脑久了会出现头晕情况
Nginx配置Basic Auth

Nginx配置Basic Auth

Basic Auth模块文档地址:Module ngx_http_auth_basic_module

生成加密的密码

Nginx支持Basic Auth身份认证,当启用此功能时,浏览器会弹出窗口要求用户输入用户名和密码,输入正确才允许访问网页。
注意:用于后台解析验证,只是使用Nginx做权限控制,密码可以不加密

在让Nginx启用Basic Auth身份认证前,首先要生成一个密码文件,格式如下:

1
2
3
username1:password1
username2:password2:comment
username3:password2

每一行为一条用户信息,每条用户信息包含3个字段:用户名、密码、注释,其中注释可以省略,字段间使用冒号分隔。其中第二个字段,即密码的部分并不是明文保存的,而是经过hash运算过的字符串,这样可以避免密码以明文方式呈现,对密码的hash运算可以使用openssl passwd命令生成。

注意:

  • 只是使用Nginx做权限控制,不进行后台解析处理的,第二个字段密码可以不加密
  • 加密的字符不适用IIS

生成示例

例如要将字符串abc进行hash运算,使用的命令及输出的结果如下:

1
2
$ openssl passwd abc
5SzUqTnPPSXCY

注意:由于在hash运算时自动加入了随机的salt,因此相同的字符串每次进行hash时,产生的结果都是不一样的。

默认的算法为:Standard Unix password algorithm,此算法最多只支持对8个字符进行hash。可以选择使用其他的算法,通过openssl帮助查看可用的算法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ openssl help passwd
Usage: passwd [options]
Valid options are:
-help Display this summary
-in infile Read passwords from file
-noverify Never verify when reading password from terminal
-quiet No warnings
-table Format output as table
-reverse Switch table columns
-salt val Use provided salt
-stdin Read passwords from stdin
-6 SHA512-based password algorithm
-5 SHA256-based password algorithm
-apr1 MD5-based password algorithm, Apache variant
-1 MD5-based password algorithm
-aixmd5 AIX MD5-based password algorithm
-crypt Standard Unix password algorithm (default)
-rand val Load the file(s) into the random number generator
-writerand outfile Write random data to the specified file

从上述帮助信息中可以看到还可以选择SHA512、SHA256、MD5等方式进行hash。根据使用的openssl版本的不同,可用的算法也可能会不同。

下面,我们使用一个例子来说明如何用命令行批量对密码信息进行hash。

首先创建一个文件user.txt,包含3条用户信息,每行为一条信息,使用冒号作为字段分隔符,字段分别为用户名、明文密码、注释(只在第1条和第3条信息中包含),注意请不要在用户名、密码或注释中包含冒号:

1
2
3
4
cat user.txt
user1:abcde:comment
user2:xyz123
m3ng9i:123456:mengqi.info

然后使用下面的命令生成密码文件passwd.txt:

1
cut -d ":" -f 2 user.txt | openssl passwd -6 -stdin | paste -d ":" user.txt - | tr -d '\r' | awk 'BEGIN{FS=":";OFS=":"}{if (NF==4) print $1,$4,$3; else if (NF==3) print $1,$3}' > passwd.txt

以上命令组合了cutopensslpastetrawk5个命令,作用简单说明如下:

cut: 取出user.txt的第二个字段(密码明文),将结果输出到stdout;
openssl: 将stdin中输入的数据(3条密码明文)使用SHA512形式进行hash,输出到stdout;
paste: 将user.txt中的原始内容与hash过的密码组合起来,输出到stdout;
tr: 去除可能出现的\r符号;
awk: 从stdin中提取出用户名、hash过的密码、注释字段,将结果输出到passwd.txt。
生成的密码文件内容如下,可以看到和user.txt相比,新生成的文件中,密码字段已经被hash:

1
2
3
4
$ cat passwd.txt
user1:$6$gjGELGyOCDsUrRtG$OcQy9GXbdpZ9Iujd1Jmzwyd5dJaXxyWUgcsiQxAOAbBj/OEQChPSD0iojfDIn3qKd82Spm5yVd3qAUmJno0KP.:comment
user2:$6$ak/BIY4C7knXMVq5$hVGDCcKaz5ExcJ2Fv9xusW6ZdqCoWQrveqrK3pWgtbUebi5CCsO4e9GbxgGfSThuVILIfJUaIBjUv7B.60nez1
m3ng9i:$6$euEJqJ4PmiMdJJXC$gPLLrYkPWz.LqW50RcMA/rPzOTI9j1pWjxSlgXtHd8RJbBedpxjf.w67QnjG2m8MIxnY9G.fDCIlbDw5E2aXu.:mengqi.i

Nginx 配置

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 7070;
server_name localhost;

location / {
proxy_pass http://10.170.24.114:7077/;
.....
auth_basic "Please enter your username and password";
auth_basic_user_file htpasswd;
autoindex on;
}
}

auth_basic指令开启Nginx的Basic Auth认证功能,并设置了一个字符串,该字符串可能会显示在浏览器的密码输入提示窗口中(根据浏览器的不同,有些会显示,有些不会显示),你可以在HTTP Response header中的WWW-Authenticate字段看到这个字符串。

auth_basic_user_file指令设置了密码文件的路径

autoindex打开了目录浏览功能

重启Nginx服务后,访问localhost:7070就会要求输入用户名、密码。

备注:一定要注意auth_basic_user_file路径,如果文件不存在,会不厌其烦的出现403。

如果只想某一个页面支持Basic Auth,可以将auth_basic配置到location里:

1
2
3
4
location /test {
auth_basic "Please enter your username and password";
auth_basic_user_file htpasswd;
}
XML Schema初识

XML Schema初识

定义

XML Schema和DTD有什么区别

XML Schema和DTD有什么区别

https://stackoverflow.com/questions/1544200/what-is-difference-between-xml-schema-and-dtd

https://stackoverflow.com/a/1544368:

DTD 和 XML Schema 之间的关键区别在于 XML Schema 使用基于 XML 的语法,而
DTD 具有从 SGML DTD 保留下来的独特语法。尽管 DTD 经常因为需要学习新语法而受
到批评,但语法本身非常简洁。 XML Schema 的情况正好相反,它很冗长,但也使用了标
记和 XML,因此 XML 的作者应该会发现 XML Schema 的语法不那么令人生畏。

https://stackoverflow.com/a/10608432:

XML 架构定义 (XSD) 和文档类型定义 (DTD) 之间的差异包括:

  • XML Schema是用 XML 编写的,而 DTD 是从 SGML 语法派生的。
  • XML Schema定义元素和属性的数据类型,而 DTD 不支持数据类型。
  • XML Schema允许支持命名空间,而 DTD 不支持。
  • XML Schema定义了子元素的数量和顺序,而 DTD 没有。
  • 您可以使用 XML DOM 自行操作 XML Schema,但在 DTD 的情况下这是不可能的。
  • 使用 XML Schema的用户不需要学习一门新语言,但使用 DTD 对用户来说却很困难。
  • XML Schema提供安全的数据通信,即发送方可以以接收方能够理解的方式描述数据,但>在 DTD 的情况下,接收方可能会误解数据。
  • XML Schema是可扩展的,而 DTD 是不可扩展的。
  • 并非所有这些要点都是 100% 准确的,但您明白了要点。

另一方面:

  • DTD 允许您定义新的 ENTITY 值以在 XML 文件中使用。
  • DTD 允许您将其本地扩展到单个 XML 文件。
xml中的xsd、xsi、xmlns的含义

xml中的xsd、xsi、xmlns的含义

XML是可扩展标记语言,它定义了按格式编码文件的一系列规则[3],编码的文件是机器可读和人可读的。XML文件对于机器可读是基于XSD(XML Schema Definition)[1]的。XSD是受W3C推荐的XML文件的结构描述文件的规范文档,其中详细说明了如何正式描述XML文件中的元素[3];也就是说,XSD是XML文件的结构描述文件(比如.xsd文件,一个XSD的实例,它是依照XSD的规范来书写的)的规范文档。编译xml的方式是跨语言的,不同语言的解析方式相同,只是具有不同的语言形式。java中解析XML的方式之一是DOM解析,他是基于jdk的lang包中DocumentBuilderFactory类的,如下所示[2]。

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×