如何更改 TLS 上下文选项

How to change a TLS context option

在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

我需要指定另一个选项。我只需要禁用来自此选项的会话票证:

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 (&),因为每个value只有一位设置为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.optionsctx.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