在 python 中,我们可以指定一些 TLS 上下文选项。例如,文档中的这段代码 here :
client_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
client_context.options |= ssl.OP_NO_TLSv1
client_context.options |= ssl.OP_NO_TLSv1_1
我没有得到这个符号 |=
。我读了它的意思,但不明白为什么我们在这里使用它?为什么我们不使用 =
?我应该使用 |=
来设置任何选项吗?奇怪的是,我发现一些例子也在他的文档中使用 &=
:
ctx = ssl.create_default_context(Purpose.CLIENT_AUTH)
ctx.options &= ~ssl.OP_NO_SSLv3
我需要指定另一个选项。我只需要禁用来自此选项的 session 票证:
ssl.OP_NO_TICKET
如果我有上下文ctx
,如何设置ssl.OP_NO_TICKET
?我应该使用 =
还是 |=
或 &=
?请解释。
最佳答案
实际上,每个选项都是许多可能选项中的一个标志,因此您需要使用按位与 (&
) 和按位或 (|
) 运算组合它们.这样做是因为这些选项并不相互排斥,你需要通过选择你组合在一起的各种选项来组成一个最终值。所以每个都有一个值是 2 的幂,这意味着它在某个特定位置有点为 1,如果每个特定的单独标志打开或关闭,则最终值将进行编码。
因此您需要按位运算符来管理它们并构造您想要的最终值。
参见:
In [8]: print ssl.OP_NO_TLSv1, bin(ssl.OP_NO_TLSv1)
67108864 0b100000000000000000000000000
In [9]: print ssl.OP_NO_TLSv1_1, bin(ssl.OP_NO_TLSv1_1)
268435456 0b10000000000000000000000000000
In [13]: print ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1, bin(ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
335544320 0b10100000000000000000000000000
In [14]: print ssl.OP_NO_TLSv1 & ssl.OP_NO_TLSv1_1, bin(ssl.OP_NO_TLSv1 & ssl.OP_NO_TLSv1_1)
0 0b0
你看到如果你想要这两个选项,你需要将两个位都翻转为 1,因此需要一个 OR (|
) 否则用一个 AND (&
) 因为每个值只有一位设置为 1,每次都在不同的位置,所以保证结果总是 0,这意味着根本没有特征,所以肯定不是你需要的。
简而言之,在这种情况下,您永远不会使用 AND (&
) 来组合值。
现在,关于&= ~
:~
是按位取反,因此在保留其他已设置选项的同时删除一些选项很有用。
ctx.options &= ~ssl.OP_NO_SSLv3
此构造使您将最终值中与 ssl.OP_NO_SSLv3
相关的位翻转为 0。
参见:
In [34]: ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
In [37]: print ctx.options, bin(ctx.options)
2197816319 0b10000011000000000000001111111111
In [38]: print bin(ssl.OP_NO_SSLv3)
0b10000000000000000000000000
In [40]: print ctx.options & ~ssl.OP_NO_SSLv3
2164261887
In [41]: print ctx.options & ~ssl.OP_NO_SSLv3, bin(ctx.options & ~ssl.OP_NO_SSLv3)
2164261887 0b10000001000000000000001111111111
如果你比较 ctx.options
和 ctx.options & ~ssl.OP_NO_SSLv3
你会看到一位从 1
翻转到0
,因为您实际上删除了功能 OP_NO_SSLv3
。
If I have context ctx, how to set ssl.OP_NO_TICKET? Should I use = or |= or &=? please explain.
这是一个您想要添加到您已有的所有其他选项的选项,因此您不想丢失它们。因此,您需要按位或 (|
)。
- 如果您只执行
=
设置此选项,但会丢失所有当前已设置的其他选项,所以不是您需要的。 - 如果你执行
|=
,你会将与你想要的选项相关的位翻转为1,并且不要触及其他位;这就是你想要的! - 如果您执行
&=
,您只会翻转到 1 那些同时在您的新值和现有值中的位,这意味着如果尚未设置该值,则此处的结果只能为 0 或者相同的确切值(如果已设置):
(我的例子是用另一个值 OP_NO_TICKET
完成的,因为我那里没有它,但行为与任何一个都相同,因为每个 OP_
值是 2n,即一位对一,所有其他位对 0)
In [16]: ctx = ssl.OP_NO_TLSv1
In [17]: print ctx, bin(ctx)
67108864 0b100000000000000000000000000
In [19]: ctx = ssl.OP_NO_TLSv1_1
In [20]: print ctx, bin(ctx)
268435456 0b10000000000000000000000000000
In [21]: ctx = ssl.OP_NO_TLSv1
In [22]: ctx |= ssl.OP_NO_TLSv1_1
In [23]: print ctx, bin(ctx)
335544320 0b10100000000000000000000000000
In [24]: ctx = ssl.OP_NO_TLSv1
In [25]: ctx &= ssl.OP_NO_TLSv1_1
In [26]: print ctx, bin(ctx)
0 0b0
请注意在 |
的情况下,两个位如何翻转为 1
。
关于python - 如何更改 TLS 上下文选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51672803/