<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>HTTPS on prometheus</title><link>https://new.halfrost.com/zh/tags/https/</link><description>Recent content in HTTPS on prometheus</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><copyright>halfrost</copyright><lastBuildDate>Sun, 17 Mar 2019 03:08:00 +0000</lastBuildDate><atom:link href="https://new.halfrost.com/zh/tags/https/index.xml" rel="self" type="application/rss+xml"/><item><title>HTTPS 温故知新（六） —— TLS 中的 Extensions</title><link>https://new.halfrost.com/zh/https-extensions/</link><pubDate>Sun, 17 Mar 2019 03:08:00 +0000</pubDate><guid>https://new.halfrost.com/zh/https-extensions/</guid><description>扩展是 TLS 比较重要的一个知识点。它的存在能让 Client 和 Server 在不更新 TLS 的基础上，获得新的能力。扩展的官方文档在 [RFC 6066] 中定义。Extension 像 TLS 中的一系列可水平扩展的插件。
Client 在 ClientHello 中申明多个自己可以支持的 Extension，以向 Server 表示自己有以下这些能力，或者向 Server 协商某些协议。Server 收到 ClientHello 以后，依次解析 Extension，有些如果需要立即回应，就在 ServerHello 中作出回应，有些不需要回应，或者 Server 不支持的 Extension 就不用响应，忽略不处理。
TLS 握手中的 Extension 有以下几个特点:
Extension 不影响 TLS 握手的成功与否。Server 对 ClientHello 中的 Extension 有些不支持，忽略不处理即可，不影响握手的流程。
ServerHello 中回应 Client 的 Extension 一定要是 ClientHello 中的 Extension 的子集(小于等于)。ServerHello 中禁止出现 ClientHello 中没有出现的 Extension。如果一个 Client 在 ServerHello 中收到一个扩展类型但在相关的 ClientHello 中并没有请求，它必须用一个 unsupported_extension 致命 alert 消息来丢弃握手。</description></item><item><title>HTTPS 温故知新（五） —— TLS 中的密钥计算</title><link>https://new.halfrost.com/zh/https-key-cipher/</link><pubDate>Sun, 10 Mar 2019 03:00:00 +0000</pubDate><guid>https://new.halfrost.com/zh/https-key-cipher/</guid><description>本篇文章我们来对比对比 TLS 1.2 和 TLS 1.3 中的密钥计算。
一. TLS 1.2 中的密钥 在 TLS 1.2 中，有 3 种密钥：预备主密钥、主密钥和会话密钥(密钥块)，这几个密钥都是有联系的。
struct { uint32 gmt_unix_time; opaque random_bytes[28]; } Random; struct { ProtocolVersion client_version; opaque random[46]; } PreMasterSecret; struct { uint8 major; uint8 minor; } ProtocolVersion; 对于 RSA 握手协商算法来说，Client 会生成的一个 48 字节的预备主密钥，其中前 2 个字节是 ProtocolVersion，后 46 字节是随机数，用 Server 的公钥加密之后通过 Client Key Exchange 子消息发给 Server，Server 用私钥来解密。对于 (EC)DHE 来说，预备主密钥是双方通过椭圆曲线算法生成的，双方各自生成临时公私钥对，保留私钥，将公钥发给对方，然后就可以用自己的私钥以及对方的公钥通过椭圆曲线算法来生成预备主密钥，预备主密钥长度取决于 DH/ECDH 算法公钥。预备主密钥长度是 48 字节或者 X 字节。
主密钥是由预备主密钥、ClientHello random 和 ServerHello random 通过 PRF 函数生成的。主密钥长度是 48 字节。可以看出，只要我们知道预备主密钥或者主密钥便可以解密抓包数据，所以 TLS 1.</description></item><item><title>HTTPS 温故知新（四） —— 直观感受 TLS 握手流程(下)</title><link>https://new.halfrost.com/zh/https_tls1-3_handshake/</link><pubDate>Sat, 02 Feb 2019 23:58:00 +0000</pubDate><guid>https://new.halfrost.com/zh/https_tls1-3_handshake/</guid><description>在 HTTPS 开篇的文章中，笔者分析了 HTTPS 之所以安全的原因是因为 TLS 协议的存在。TLS 能保证信息安全和完整性的协议是记录层协议。(记录层协议在上一篇文章中详细分析了)。看完上篇文章的读者可能会感到疑惑，TLS 协议层加密的密钥是哪里来的呢？客户端和服务端究竟是如何协商 Security Parameters 加密参数的？这篇文章就来详细的分析一下 TLS 1.2 和 TLS 1.3 在 TLS 握手层上的异同点。
TLS 1.3 在 TLS 1.2 的基础上，针对 TLS 握手协议最大的改进在于提升速度和安全性。本篇文章会重点分析这两块。
先简述一下 TLS 1.3 的一些优化和改进:
减少握手等待时间，将握手时间从 2-RTT 降低到 1-RTT，并且增加 0-RTT 模式。
删除 RSA 密钥协商方式，静态的 Diffie-Hellman 密码套件也被删除了。因为 RSA 不支持前向加密性。TLS 1.3 只支持 (EC)DHE 的密钥协商算法。删除了 RSA 的方式以后，能有效预防心脏出血的攻击。所有基于公钥的密钥交换算法现在都能提供前向安全。TLS 1.3 规范中只支持 5 种密钥套件，TLS13-AES-256-GCM-SHA384、TLS13-CHACHA20-POLY1305-SHA256、TLS13-AES-128-GCM-SHA256、TLS13-AES-128-CCM-8-SHA256、TLS13-AES-128-CCM-SHA256，隐藏了非对称加密密钥协商算法，因为默认都是椭圆曲线密钥协商。
删除对称加密中，分组加密和 MAC 导致的一些隐患。在 TLS1.3 之前的版本中，选择的是 MAC-then-Encrypt 方式。但是这种方式带来了一些漏洞，例如 BEAST，一系列填充 oracle 漏洞(Lucky 13 和 Lucky Microseconds)。CBC 模式和填充之间的交互也是 SSLv3 和一些 TLS 实现中广泛宣传的 POODLE 漏洞原因。在 TLS 1.</description></item><item><title>HTTPS 温故知新（三） —— 直观感受 TLS 握手流程(上)</title><link>https://new.halfrost.com/zh/https_tls1-2_handshake/</link><pubDate>Sat, 26 Jan 2019 23:56:00 +0000</pubDate><guid>https://new.halfrost.com/zh/https_tls1-2_handshake/</guid><description>在 HTTPS 开篇的文章中，笔者分析了 HTTPS 之所以安全的原因是因为 TLS 协议的存在。TLS 能保证信息安全和完整性的协议是记录层协议。(记录层协议在上一篇文章中详细分析了)。看完上篇文章的读者可能会感到疑惑，TLS 协议层加密的密钥是哪里来的呢？客户端和服务端究竟是如何协商 Security Parameters 加密参数的？这篇文章就来详细的分析一下 TLS 1.2 和 TLS 1.3 在 TLS 握手层上的异同点。
TLS 1.3 在 TLS 1.2 的基础上，针对 TLS 握手协议最大的改进在于提升速度和安全性。本篇文章会重点分析这两块。
一. TLS 对网络请求速度的影响 由于部署了 HTTPS，传输层增加了 TLS，对一个完成的请求耗时又会多增加一些。具体会增加几个 RTT 呢？
先来看看一个请求从零开始，完整的需要多少个 RTT。假设访问一个 HTTPS 网站，用户从 HTTP 开始访问，到收到第一个 HTTPS 的 Response，大概需要经历一下几个步骤(以目前最主流的 TLS 1.2 为例)：
流程 消耗时间 总计 1. DNS 解析网站域名 1-RTT 2. 访问 HTTP 网页 TCP 握手 1-RTT 3.</description></item><item><title>HTTPS 温故知新（二） —— TLS 记录层协议</title><link>https://new.halfrost.com/zh/https_record_layer/</link><pubDate>Sun, 20 Jan 2019 05:57:00 +0000</pubDate><guid>https://new.halfrost.com/zh/https_record_layer/</guid><description>TLS 记录协议是一个层次化的协议。在每一层中，消息都可能包含长度、描述、内容等字段。记录协议主要功能包括装载了被发送的消息，将数据分片为可管理的块，有选择地压缩数据，应用 MAC，加密，传输最终数据。接收到的数据被解密，验证，解压缩，重组，然后传递给高层应用。
特别需要注意的是一条记录消息的类型 type 和长度 length 是不会被加密保护的，它们是明文的。如果这个信息本身是敏感的，应用设计者可能会希望采取一些措施(填充 padding，覆盖流量cover traffic) 来以减小信息泄露。
这篇文章我们重点来讨论一下 TLS 1.2 和 TLS 1.3 在记录层上的不同。先从共同点开始。
一、TLS 记录层的连接状态 一个 TLS 连接的状态就是 TLS 记录协议的操作环境。它指定了一个压缩算法，一个加密算法，一个 MAC 算法。此外，这些算法的参数必须是已知的：用于 connection 连接的读、写两个方向的 MAC 密钥和块加密密钥。逻辑上总是有4个状态比较突出：可读和可写状态，挂起的读和写状态。所有的记录协议都在可读写状态下处理。挂起状态的安全参数可以通过 TLS 握手协议来设置，而 ChangeCipherSpec 可以有选择地设置当前状态为挂起状态，在这种情况下适当的当前状态被设置，并被挂起状态所替代; 挂起状态随后会被重新初始化为一个空状态。将一个状态未经安全参数的初始化就设置为一个当前状态是非法的。初始当前状态一直会指定不使用加密，压缩或 MAC。
ChangeCipherSpec 在官方 TLS 1.3 的规范中已经去掉了，但是为了兼容老的 TLS 1.2 或者网络中间件，这个协议还可能存在。
简单来说，Client 和 Server 在建立链接之前都处于：
pending read status 待读状态 pending write status 待写状态 一旦接收到对端的 ChangeCipherSpec 消息以后，Client 和 Server 就会开始转换为：
current read status 可读状态 current write status 可写状态 在收到对端的 ChangeCipherSpec 之前，所有的 TLS 握手消息都是明文处理的，没有安全性和完整性的保护。一旦所有的加密参数都准备好，就会转换成可读可写状态，进入到了可读可写状态以后就会开始加密和完整性保护了。</description></item><item><title>HTTPS 温故知新（一） —— 开篇</title><link>https://new.halfrost.com/zh/https-begin/</link><pubDate>Sun, 13 Jan 2019 05:31:00 +0000</pubDate><guid>https://new.halfrost.com/zh/https-begin/</guid><description>一、为什么需要 HTTPS HTTP1.1 有以下安全性问题：
使用明文(不加密)进行通信，内容可能会被窃听； 不验证通信方的身份，通信方的身份有可能遭遇伪装； 无法证明报文的完整性，报文有可能遭篡改。 由于 HTTP 设计之初没有考虑到这几点，所以基于 HTTP 的这些应用都会存在安全问题。
1. 数据没有加密 基于 TCP/IP 的网络，网络各处都会存在被监听的风险。而且如果用 HTTP 协议进行通信，HTTP 本身没有加密功能，所以也无法做到对通信整体(使用 HTTP 协议通信的请求和响应的内容)进行加密。即，HTTP 报文使用明文(指未经过加密的报文)方式发送。
像上图表示的那样，在互联网各个环节都可能被监听。就算是加密通信，也能被监听到通信内容，只不过监听者看到的是密文。要解决 HTTP 上面 3 个大的安全问题，第一步就是要先进行加密通信。于是在传输层增加了一层 SSL（Secure Sockets Layer 安全套接层）/ TLS (Transport Layer Security 安全层传输协议) 来加密 HTTP 的通信内容。
HTTPS (HTTP Secure) 并不是新协议，而是 HTTP 先和 SSL（Secure Sockets Layer 安全套接层）/ TLS (Transport Layer Security 安全层传输协议) 通信，再由 SSL/TLS 和 TCP 通信。也就是说 HTTPS 使用了隧道进行通信。
这个时候可能有同学会有疑问了，为什么不直接对 HTTP 报文进行加密，这样就不需要 SSL/TLS 这一层了。确实，如果直接对 HTTP 报文进行加密也可以做到加密通信，但是虽然解决了第一条，但是后面 2 条就不好解决了。</description></item><item><title>TLS &amp; DTLS Heartbeat Extension</title><link>https://new.halfrost.com/zh/tls_heartbeat/</link><pubDate>Sun, 06 Jan 2019 05:14:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_heartbeat/</guid><description>这篇文章我们主要来讨论讨论 Transport Layer Security (TLS) 和 Datagram Transport Layer Security (DTLS) 中的 Heartbeat 扩展。
Heartbeat 扩展为 TLS/DTLS 提供了一种新的协议，允许在不需要重协商的情况下，使用 keep-alive 功能。Heartbeat 扩展也为 path MTU (PMTU) 发现提供了基础。
一. Introduction 这篇文章描述了 [RFC5246] 和 [RFC6347] 中定义的传输层安全性 (TLS) 和数据报传输层安全性 (DTLS) 协议的心跳扩展，以及它们对 [RFC3436]，[RFC5238] 和 [RFC6083] 中描述的特定传输协议的适应性。
DTLS 协议设计的目的是，保护在不可靠的传输协议之上运行的流量数据。通常，此类协议没有会话管理。DTLS 层可用于确定对等方是否仍然 alive 的唯一机制是昂贵的重新协商机制，尤其是当应用程序使用单向流量时。此外，DTLS 需要执行路径 MTU (PMTU) 发现，但在不影响用户消息的传输的情况下，没有特定的消息类型来实现 PMTU 发现。
TLS 是基于可靠的协议，但没有必要的功能可以在没有连续数据传输的情况下保持连接存活。
本文中描述的心跳扩展克服了这些限制。用户可以使用新的 HeartbeatRequest 消息，该消息必须由具有 HeartbeartResponse 的对端立即应答。要执行 PMTU 发现，如 RFC4821 中所述，可以将包含填充的 HeartbeatRequest 消息用作探测包。
二. Heartbeat Hello Extension Hello Extensions 表示支持 Heartbeats。对端不仅可以表明其实现支持Heartbeats，还可以选择是否愿意接收 HeartbeatRequest 消息并使用 HeartbeatResponse 消息进行响应或仅发送 HeartbeatRequest 消息。前者通过使用 peer_allowed_to_send 作为 HeartbeatMode 来表示;后者通过使用 peer_not_allowed_to_send 作为心跳模式来表示。每次重新谈判都可以改变这一决定。HeartbeatRequest 消息禁止发送到已经表明了 peer_not_allowed_to_send 的对端。如果已经表明了 peer_not_allowed_to_send 的端点收到 HeartbeatRequest 消息，则端点应该以静默方式丢弃该消息，并且可以发送 unexpected_message Alert 消息。</description></item><item><title>The Transport Layer Security (TLS) Protocol Version 1.3</title><link>https://new.halfrost.com/zh/tls_1-3_rfc8446/</link><pubDate>Sun, 23 Dec 2018 01:10:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_rfc8446/</guid><description>Table of Contents 1. Introduction 1.1. Conventions and Terminology 1.2. Major Differences from TLS 1.2 1.3. Updates Affecting TLS 1.2 2. Protocol Overview 2.1. Incorrect DHE Share 2.2. Resumption and Pre-Shared Key (PSK) 2.3. 0-RTT Data 3. Presentation Language 这一章都是一些公认的表达语言，笔者觉得读者基本都清楚，所以就不翻译了。
3.1. Basic Block Size 3.2. Miscellaneous 3.3. Numbers 3.4. Vectors 3.5. Enumerateds 3.6. Constructed Types 3.7. Constants 3.8. Variants 4. Handshake Protocol 4.</description></item><item><title>TLS 1.3 Overview of Security Properties</title><link>https://new.halfrost.com/zh/tls_1-3_security_properties/</link><pubDate>Sun, 16 Dec 2018 01:07:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_security_properties/</guid><description>对 TLS 的完整安全性分析超出了本文的讨论范围。在本附录中，我们提供了对所需属性的非正式描述，以及对更加正式定义的研究文献中提出更详细工作的参考。
我们将握手的属性与记录层的属性分开。
一. Handshake TLS 握手是经过身份验证的密钥交换(AKE，Authenticated Key Exchange)协议，旨在提供单向身份验证(仅 Server)和相互身份验证(Client 和 Server)功能。在握手完成时，每一侧都输出其以下值：
一组 &amp;ldquo;会话密钥&amp;rdquo;(从主密钥导出的各种密钥)，可以从中导出一组工作密钥。
一组加密参数（算法等）。
沟通各方的身份标识
我们假设攻击者是一个活跃的网络攻击者，这意味着它可以完全控制双方通信的网络 [RFC3552]。即使在这些条件下，握手也应提供下面列出的属性。请注意，这些属性不一定是独立的，而是反映了协议消费者的需求的。
建立相同的会话密钥：握手需要在握手的两边输出相同的会话密钥集，前提是它在每个端点上成功完成（参见 [CK01]，定义1，第1部分）
会话密钥的保密性：共享会话密钥只能由通信方而不是攻击者所知（参见 [CK01]，定义 1，第 2 部分）。请注意，在单方面验证的连接中，攻击者可以与 Server 建立自己的会话密钥，但这些会话密钥与 Client 建立的会话密钥不同。
对等身份验证：Client 对等身份的视图应该反映 Server 的身份标识。如果 Client 已通过身份验证，则 Server 的对等标识视图应与 Client 的标识匹配。
会话密钥的唯一性：任何两个不同的握手都应该产生不同的，不相关的会话密钥。握手产生的各个会话密钥也应该是不同且独立的。
降级保护：双方的加密参数应该相同，并且应该与在没有攻击的情况下双方进行通信的情况相同（参见 [BBFGKZ16]，定义 8 和 9）
关于长期密钥的前向保密：如果长期密钥材料（在这种情况下，是基于证书的认证模式中的签名密钥或具有 (EC)DHE 模式的 PSK 中的外部/恢复 PSK）在握手后完成后泄露了，只要会话密钥本身已被删除，这不会影响会话密钥的安全性（参见 [DOW92]）。当在 &amp;ldquo;psk_ke&amp;rdquo; PskKeyExchangeMode 中使用 PSK 时，不能满足前向保密属性。
密钥泄露模拟 (KCI，Key Compromise Impersonation) 抵抗性：在通过证书进行相互认证的连接中，泄露一个参与者的长期密钥不应该破坏该参与者在这个给定连接中对通信对端的认证（参见 [HGFS15]）。例如，如果 Client 的签名密钥被泄露，则不应该在随后的握手中模拟任意的 Server 和 Client 进行通信。</description></item><item><title>TLS 1.3 Backward Compatibility</title><link>https://new.halfrost.com/zh/tls_1-3_backward_compatibility/</link><pubDate>Sun, 09 Dec 2018 01:02:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_backward_compatibility/</guid><description>TLS 协议为端点之间的版本协商提供了一个内置机制，让支持不同版本的 TLS 成为了可能。
TLS 1.x 和 SSL 3.0 使用兼容的 ClientHello 消息。只要 ClientHello 消息格式保持兼容并且 Client 和 Server 都至少共同能支持一个协议版本，Server 就可以尝试使用未来版本 TLS 来回应 Client。
TLS 的早期版本使用记录层版本号(TLSPlaintext.legacy_record_version 和 TLSCiphertext.legacy_record_version)用于各种目的。从 TLS 1.3 开始，此字段被废弃了。所有实现都必须忽略 TLSPlaintext.legacy_record_version 的值。TLSCiphertext.legacy_record_version 的值包含在不被保护的附加数据中，但可以忽略或者可以验证，以此匹配固定的常量值。只能使用握手版本执行版本协商(ClientHello.legacy_version 和 ServerHello.legacy_version 以及ClientHello，HelloRetryRequest 和 ServerHello 中的 &amp;ldquo;supported_versions&amp;rdquo; 扩展名)。为了最大限度地提高与旧的端点的互操作性，协商使用 TLS 1.0-1.2 的实现方应该将记录层版本号设置为协商版本，这样做是为了 ServerHello 和以后的所有记录。
为了最大限度地兼容以前的非标准行为和配置错误的部署，所有实现方都应该支持基于本文档中的期望验证认证的方法，即使在处理先前的 TLS 版本的握手时也是如此(参见 第4.4.2.2节)。
TLS 1.2 和之前版本支持 &amp;ldquo;Extended Master Secret&amp;rdquo; RFC7627 扩展，它将握手记录的大部分内容消化为主密钥。因为 TLS 1.3 总是从转录开始到 Server Finish 都在计算哈希，所以同时支持 TLS 1.3 和早期版本的实现方，无论是否使用了 TLS 1.3，都应该表明在其 API 中使用了Extended Master Secret extension。</description></item><item><title>TLS 1.3 Implementation Notes</title><link>https://new.halfrost.com/zh/tls_1-3_implementation_notes/</link><pubDate>Sun, 02 Dec 2018 00:58:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_implementation_notes/</guid><description>一、Cipher Suites 对称密码套件定义了一对 AEAD 算法和与 HKDF 一起使用的哈希算法。密码套件名称遵循 命名惯例：
CipherSuite TLS_AEAD_HASH = VALUE; +-----------+------------------------------------------------+ | Component | Contents | +-----------+------------------------------------------------+ | TLS | The string &amp;#34;TLS&amp;#34; | | | | | AEAD | The AEAD algorithm used for record protection | | | | | HASH | The hash algorithm used with HKDF | | | | | VALUE | The two-byte ID assigned for this cipher suite | +-----------+------------------------------------------------+ 此规范定义了以下用于 TLS 1.</description></item><item><title>TLS 1.3 Compliance Requirements</title><link>https://new.halfrost.com/zh/tls_1-3_compliance_requirements/</link><pubDate>Sun, 25 Nov 2018 00:49:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_compliance_requirements/</guid><description>一. Mandatory-to-Implement Cipher Suites TLS 1.3 中有一些密码套件是强制必须实现的。
在本文下面的描述中，“必须” 代表 MUST，“应该”代表 SHOULD。请读者注意措辞。
在没有应用程序配置文件标准指定的情况下，除此以外都需要满足以下要求：
符合 TLS 标准的应用程序必须实现 TLS_AES_128_GCM_SHA256 [GCM] 密码套件，应该实现TLS_AES_256_GCM_SHA384 [GCM] 和 TLS_CHACHA20_POLY1305_SHA256 [RFC8439] 密码套件（请参阅 附录 B.4）
符合 TLS 标准的应用程序必须支持数字签名 rsa_pkcs1_sha256(用于证书)，rsa_pss_rsae_sha256（用于 CertificateVerify 和 证书）和ecdsa_secp256r1_sha256。一个符合 TLS 标准的应用程序必须支持与 secp256r1 的密钥交换(NIST P-256) 并且应该支持与 X25519 [RFC7748] 的密钥交换。
二. Mandatory-to-Implement Extensions TLS 1.3 中有一些扩展是强制必须实现的。
如果没有另外指定的应用程序配置文件标准，符合 TLS 标准的应用程序必须实现以下 TLS 扩展：
支持的版本（&amp;ldquo;supported_versions&amp;rdquo;; 第 4.2.1 节）
Cookie（&amp;ldquo;cookie&amp;rdquo;;第 4.2.2 节）
签名算法（&amp;ldquo;signature_algorithms&amp;rdquo;; 第 4.2.3 节）</description></item><item><title>TLS 1.3 0-RTT and Anti-Replay</title><link>https://new.halfrost.com/zh/tls_1-3_0-rtt/</link><pubDate>Sun, 18 Nov 2018 00:46:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_0-rtt/</guid><description>如 第2.3节 和 附录 E.5 所述，TLS不为 0-RTT 数据提供固有的重放保护。有两个潜在的威胁值得关注:
通过简单地复制 0-RTT 数据并发送来进行重放攻击的网络攻击者
网络攻击者利用 Client 重试行为使 Server 接收多个应用程序消息的副本。这种威胁在某种程度上已经存在，因为重视健壮性的 Client 通过尝试重试请求来响应网络错误。但是，0-RTT 为任何不维护全局一致服务器状态的 Server 系统添加了额外的维度。具体来说，如果服务器系统有多个 zone，zone B 中不接受来自 zone A 的 ticket，则攻击者可以将 A 中的 ClientHello 和 early data 复制到 A 和 B。对于 A，数据将在 0-RTT 内被接收，但对于 B，Server 将拒绝 0-RTT 数据，而是强制进行完全握手。如果攻击者 block 了 A 的 ServerHello，那么 Client 将会与 B 完成握手并且很可能重试一次请求，从而导致整个服务器系统上出现重复。
通过共享状态可以防止第一类攻击，以保证最多接受一次 0-RTT 数据。Server 应该通过实现本文中描述的方法之一或通过等效方法提供一定级别的重放安全性。但是，据了解，由于操作问题，并非所有部署都将维持该级别的状态。因此，在正常操作中，Client 并不知道这些 Server 实际实现了哪些机制(如果有的话)，因此必须只发送他们认为可以安全重放的 early data。
除了重放的直接影响之外，还存在一类攻击，即使通常被认为是幂等的操作也会被大量重放(定时攻击，资源限制耗尽等，如 附录 E.</description></item><item><title>TLS 1.3 Cryptographic Computations</title><link>https://new.halfrost.com/zh/tls_1-3_cryptographic_computations/</link><pubDate>Sun, 11 Nov 2018 00:44:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_cryptographic_computations/</guid><description>TLS 握手建立一个或多个输入的 secrets，如下文所述，将这些 secrets 组合起来以创建实际工作密钥材料。密钥派生过程包含输入 secrets 和握手记录。请注意，由于握手记录包含来自 Hello 消息的随机值，因此即使使用相同的输入 secrets，任何给定的握手都将具有不同的流量 secrets，就像将相同的 PSK 用于多个连接的情况一样。
一. Key Schedule 密钥派生过程使用 HKDF [RFC5869] 定义的 HKDF-Extract 和 HKDF-Expand 函数，以及下面定义的函数:
HKDF-Expand-Label(Secret, Label, Context, Length) = HKDF-Expand(Secret, HkdfLabel, Length) Where HkdfLabel is specified as: struct { uint16 length = Length; opaque label&amp;lt;7..255&amp;gt; = &amp;#34;tls13 &amp;#34; + Label; opaque context&amp;lt;0..255&amp;gt; = Context; } HkdfLabel; Derive-Secret(Secret, Label, Messages) = HKDF-Expand-Label(Secret, Label, Transcript-Hash(Messages), Hash.length) Transcript-Hash 和 HKDF 使用的 Hash 函数是密码套件哈希算法。Hash.length 是其输出长度(以字节为单位)。消息是表示的握手消息的串联，包括握手消息类型和长度字段，但不包括记录层头。请注意，在某些情况下，零长度 context（由 &amp;quot;&amp;rdquo; 表示）传递给 HKDF-Expand-Label。本文档中指定的 labels 都是 ASCII 字符串，不包括尾随 NUL 字节。</description></item><item><title>TLS 1.3 Alert Protocol</title><link>https://new.halfrost.com/zh/tls_1-3_alert_protocol/</link><pubDate>Sun, 04 Nov 2018 00:35:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_alert_protocol/</guid><description>TLS 提供 alert 内容类型用来表示关闭信息和错误。与其他消息一样，alert 消息也会根据当前连接状态的进行加密。
Alert 消息传达警报的描述以及在先前版本的 TLS 中传达消息严重性级别的遗留字段。警报分为两类：关闭警报和错误警报。在 TLS 1.3 中，错误的严重性隐含在正在发送的警报类型中，并且可以安全地忽略 &amp;ldquo;level&amp;rdquo; 字段。&amp;ldquo;close_notify&amp;rdquo; alert 用于表示连接从一个方向开始有序的关闭。收到这样的警报后，TLS 实现方应该表明应用程序的数据结束。
错误警报表示关闭连接中断(参见第6.2节)。收到错误警报后，TLS 实现方应该向应用程序表示出现了错误，并且不允许在连接上发送或接收任何其他数据。Server 和 Client 必须忘记在失败的连接中建立的秘密值和密钥，但是与会话 ticket 关联的 PSK 除外，如果可能，应该丢弃它们。
第 6.2 节中列出的所有警报必须与 AlertLevel = fatal 一起发送，并且在收到时必须将其视为错误警报，而不管消息中的 AlertLevel 如何。未知的警报类型必须都应该被视为错误警报。
注意：TLS 定义了两个通用警报(请参阅第6节)，以便在解析消息失败时使用。对端接收到了语法无法解析的消息(例如，消息具有超出消息边界的长度或包含超出范围的长度)必须以 &amp;ldquo;decode_error&amp;rdquo; 警报终止连接。对端接收到了语法正确，但是语义无效的消息(例如，p-1 的 DHE 共享或无效的枚举)必须使用 &amp;ldquo;illegal_parameter&amp;rdquo; 警报终止连接。
enum { warning(1), fatal(2), (255) } AlertLevel; enum { close_notify(0), unexpected_message(10), bad_record_mac(20), record_overflow(22), handshake_failure(40), bad_certificate(42), unsupported_certificate(43), certificate_revoked(44), certificate_expired(45), certificate_unknown(46), illegal_parameter(47), unknown_ca(48), access_denied(49), decode_error(50), decrypt_error(51), protocol_version(70), insufficient_security(71), internal_error(80), inappropriate_fallback(86), user_canceled(90), missing_extension(109), unsupported_extension(110), unrecognized_name(112), bad_certificate_status_response(113), unknown_psk_identity(115), certificate_required(116), no_application_protocol(120), (255) } AlertDescription; struct { AlertLevel level; AlertDescription description; } Alert; 一.</description></item><item><title>TLS 1.3 Record Protocol</title><link>https://new.halfrost.com/zh/tls_1-3_record_protocol/</link><pubDate>Sun, 28 Oct 2018 00:22:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_record_protocol/</guid><description>TLS 记录协议接收要传输的消息，将数据分段为可管理的块，保护记录并传输结果。收到的数据经过验证，解密，重新组装，然后交付给更上层的协议。
TLS 记录允许同一层记录层上复用多个更高层的协议。本文档指定了 4 种内容类型：handshake，application_data，alert 和 change_cipher_spec。change_cipher_spec 记录仅用于兼容性目的。
实现方可能会在发送或接收第一个 ClientHello 消息之后，和，在接收到对等方的 Finished 消息之前的任何时间接收由单字节值 0x01 组成的未加密的类型 change_cipher_spec 的记录，如果接收到了这种记录，则必须简单地丢弃它而不进行进一步处理。请注意，此记录可能出现在握手中，这时候实现方是期望保护记录的，因此有必要在尝试对记录进行去除保护之前检测此情况。接收到任何其他 change_cipher_spec 值或接收到受保护的 change_cipher_spec 记录的实现方必须使用 &amp;ldquo;unexpected_message&amp;rdquo; alert 消息中止握手。如果实现方检测到在第一个 ClientHello 消息之前或在对等方的 Finished 消息之后收到的 change_cipher_spec 记录，则必须将其视为意外记录类型(尽管无状态的 Server 可能无法将这些情况与允许的情况区分开)
除非协商了某些扩展，否则实现方绝不能发送本文档中未定义的记录类型。如果 TLS 实现方收到意外的记录类型，它必须使用 &amp;ldquo;unexpected_message&amp;rdquo; alert 消息终止连接。新记录内容类型值由 IANA 在 TLS ContentType 注册表中分配，具体见第 11 节。
一. Record Layer 记录层将信息块分段为 TLSPlaintext 记录，TLSPlaintext 中包含 2^14 字节或更少字节块的数据。根据底层 ContentType 的不同，消息边界的处理方式也不同。任何未来的新增的内容类型必须指定适当的规则。请注意，这些规则比 TLS 1.2 中强制执行的规则更加严格。
握手消息可以合并为单个 TLSPlaintext 记录，或者在几个记录中分段，前提是：
握手消息不得与其他记录类型交错。也就是说，如果握手消息被分成两个或多个记录，则它们之间不能有任何其他记录。
握手消息绝不能跨越密钥更改。实现方必须验证密钥更改之前的所有消息是否与记录边界对齐; 如果没有，那么他们必须用 &amp;ldquo;unexpected_message&amp;rdquo; alert 消息终止连接。因为 ClientHello，EndOfEarlyData，ServerHello，Finished 和 KeyUpdate 消息可以在密钥更改之前立即发生，所以实现方必须将这些消息与记录边界对齐。</description></item><item><title>TLS 1.3 Handshake Protocol</title><link>https://new.halfrost.com/zh/tls_1-3_handshake_protocol/</link><pubDate>Sun, 21 Oct 2018 00:15:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_handshake_protocol/</guid><description>握手协议用于协商连接的安全参数。握手消息被提供给 TLS 记录层，在记录层它们被封装到一个或多个 TLSPlaintext 或 TLSCiphertext 中，它们按照当前活动连接状态进行处理和传输。
enum { client_hello(1), server_hello(2), new_session_ticket(4), end_of_early_data(5), encrypted_extensions(8), certificate(11), certificate_request(13), certificate_verify(15), finished(20), key_update(24), message_hash(254), (255) } HandshakeType; struct { HandshakeType msg_type; /* handshake type */ uint24 length; /* remaining bytes in message */ select (Handshake.msg_type) { case client_hello: ClientHello; case server_hello: ServerHello; case end_of_early_data: EndOfEarlyData; case encrypted_extensions: EncryptedExtensions; case certificate_request: CertificateRequest; case certificate: Certificate; case certificate_verify: CertificateVerify; case finished: Finished; case new_session_ticket: NewSessionTicket; case key_update: KeyUpdate; }; } Handshake; 协议消息必须按照一定顺序发送(顺序见下文)。如果对端发现收到的握手消息顺序不对，必须使用 “unexpected_message” alert 消息来中止握手。</description></item><item><title>TLS 1.3 Introduction</title><link>https://new.halfrost.com/zh/tls_1-3_introduction/</link><pubDate>Sat, 13 Oct 2018 23:58:00 +0000</pubDate><guid>https://new.halfrost.com/zh/tls_1-3_introduction/</guid><description>一、TLS 协议的目的 TLS 的主要目标是为通信的双方提供一个安全的通道。对下层传输的唯一要求是一个可靠的有序的数据流。
认证： 通道的 Server 端应该总是被认证的；Client 端是可选的被认证。认证可以通过非对称算法（例如，RSA, 椭圆曲线数字签名算法(ECDSA)，或 Edwards 曲线数字签名算法(EdDSA)）完成，或通过一个对称的预共享密钥（PSK)。
机密性：在建立完成的通道上发送的数据只能对终端是可见的。TLS 协议并不能隐藏它传输的数据的长度，但是终端能够通过填充 TLS 记录来隐藏长度，以此来提升针对流量分析技术的防护。
完整性：在建立完成的通道上面发送数据，不可能存在数据被篡改还没有发现的情况。即数据一旦被修改，对端会立即发现这个篡改。
以上 3 点是必须要保证的，即使网络攻击者已经完全掌握了网络，发生了 RFC 3552 中发生的情况。关于 TLS 安全问题，下面有单独的文章专门再讨论。
二、TLS 协议的组成 TLS 协议主要由 2 大组件组成：
握手协议
握手协议主要需要处理在通信双方之间进行认证的所有流程。包括密钥协商，参数协商，建立共享密钥。握手协议被设计用来抵抗篡改；如果连接未受到攻击，则活动攻击者不应该强制对等方协商不同的参数。
记录协议
使用由握手协议建立的参数来保护通信双方的流量。记录协议将流量分为一系列记录，每个记录独立地使用密钥来保护机密性。
TLS 是一个独立的协议；高层协议可以透明地位于 TLS 之上。然而，TLS 标准并未指定协议如何增强 TLS 的安全，如何发起 TLS 握手以及如何理解认证证书交换，这些都留给运行在 TLS 之上的协议的设计者和实现者来判断。
本文档定义了 TLS 1.3 版。虽然 TLS 1.3 不是直接的与之前的版本兼容，所有版本的TLS都包含一个版本控制机制，即允许客户端和服务器通过协商，选出通信过程中采用的 TLS 版本。</description></item><item><title>秘密的实质——密钥</title><link>https://new.halfrost.com/zh/cipherkey/</link><pubDate>Sun, 07 Oct 2018 05:04:00 +0000</pubDate><guid>https://new.halfrost.com/zh/cipherkey/</guid><description>一、为什么需要密钥？ 密码的本质就是将较长的秘密——消息——变成较短的秘密——密钥。
—————布鲁斯 ● 施耐尔《网络信息安全的真相》
在前面几篇文章中，我们知道对称密码，公钥密码，消息认证码，数字签名，公钥证书，这些密码技术都需要一个密钥。密钥保护了信息的机密性。密钥最重要的是密钥空间的大下。密钥的长度决定了密钥空间的大小。密钥空间越大，暴力破解越困难。
二、什么是密钥？ 密钥仅仅是一个比特序列，但是它所具有的价值和明文等价。密钥的种类主要分为以下几种：
1. 对称密码的密钥和公钥密码的密钥 在对称加密中，加密和解密都用同一个密钥，也被称为共享密钥密码。
在公钥密码中，加密和解密都是不同的密钥。用于加密且能公开的密钥称为公钥。用于解密且不能公开的密钥称为私钥。
2. 消息认证码的密钥和数字签名的密钥 在消息认证码中，发送者和接收者使用共享的密钥来进行认证。消息认证码只有持有合法密钥的人才能计算出来。通过对比消息认证码就可以识别消息是否被篡改或者伪装。
在数字签名中，签名的生成和验证使用不同的密钥。只有持有私钥的本人才能够生成签名，但由于验证签名使用的是公钥，因此任何人都能够验证签名。
3. 用于保密的密钥和用于认证的密钥 对称密钥和公钥密码的密钥都是用于确保机密性的密钥。如果不知道用于解密的合法密钥，就可以达到保密明文的效果。
消息认证码和数字签名所使用的密钥是用于认证的密钥。如果不知道合法的密钥，就无法篡改数据，也无法伪装。
4. 会话密钥和主密钥 在 HTTPS 中 TLS 握手中仅限于本次通信的一次性密钥，下次就不能使用了。这种每次通信只能使用一次的密钥叫会话密钥(session key)。
由于每次会话都会产生新的会话密钥，即使密钥被窃听了，也只会影响本次会话。如果每次都使用相同的密钥叫主密钥(master key)。
5. 用于加密内容的密钥和用于加密密钥的密钥 加密的对象是用户直接使用的信息(内容)，这个时候密钥被称为CEK(Contents Encrypting Key)。用于加密密钥的密钥被称为KEK(Key Encrypting Key)。
会话密钥被作为 CEK 使用。主密钥被作为 KEK 使用的。
三、生成、配送、更新密钥 1. 生成密钥 用随机数生成密钥。生成密钥的最好办法就是使用随机数。 用口令生成密钥。通常为了防止字典攻击，需要在口令上附加一串称为盐(salt)的随机数。这种方法称为基于口令的密码。 2. 配送密钥 事先共享密钥 使用密钥分配中心 使用公钥密码 Diffie-Hellman 密钥交换 3. 更新密钥 这种技术通常被用在共享密钥中。在共享密钥进行通信的过程中，定期(例如，每发送 1000 个字)改变密钥。当然，发送者和接收者改变的步调要一致。</description></item><item><title>无法预测的根源——随机数</title><link>https://new.halfrost.com/zh/random_number/</link><pubDate>Sun, 23 Sep 2018 04:30:01 +0000</pubDate><guid>https://new.halfrost.com/zh/random_number/</guid><description>一、为什么需要随机数？ 在之前文章说提到了好多密码学技术，在这些技术中，都会看见随机数的身影。
生成密钥 用于对称密码和消息认证码 生成公钥密码 用于生成公钥密码和数字签名 生成初始化向量 IV 用于分组密码中的 CBC、CFB、OFB 模式 生成 nonce 用于防御重放攻击和分组密码中的 CTR 模式 生成盐
用于基于口令密码的 PBE 等 用随机数的目的是为了提高密文的不可预测性，让攻击者无法一眼看穿。
二、什么是随机数？ 给随机数下一个严密的定义很难。只能从性质去区分一些随机数的种类。
随机性 —— 不存在统计学偏差，是完全杂乱的数列 不可预测性 —— 不能从过去的数列推测出下一个出现的数 不可重现性 —— 除非将数列本身保存下来，否则不能重现相同的数列 随机性 不可预测性 不可重现性 备注 生成器 弱伪随机数 ✅ ❌ ❌ 只具备随机性 不可用于密码技术❌ 伪随机数生成器 PRNG (Preudo Random Number Generator) 强伪随机数 ✅ ✅ ❌ 具备不可预测性 可用于密码技术✅ 密码学伪随机数生成器 CPRNG (Cryptography secure Preudo Random Number Generator) 真随机数 ✅ ✅ ✅ 具备不可重现性 可用于密码技术✅ 真随机数生成器 TRNG (True Random Number Generator) 密码技术上使用到的随机数至少要达到不可预测性这一等级，即至少是强伪随机数，最好是真随机数。</description></item><item><title>随处可见的公钥证书</title><link>https://new.halfrost.com/zh/digital_certificate/</link><pubDate>Sat, 15 Sep 2018 09:01:00 +0000</pubDate><guid>https://new.halfrost.com/zh/digital_certificate/</guid><description>一、为什么需要公钥证书？ 在上一篇文章中我们谈到了数字签名，数字签名可以识别篡改或者发送者身份是否被伪装，也就是验证消息的完整性，还可以对消息进行认证。还可以防止抵赖。看似一切完美，但是他的弱点也在他的优点上，数字签名需要用公钥来确认发送者的身份。
我们需要从一个没有被伪装的发送者那里得到没有被篡改的公钥才行，为了验证得到的公钥是否合法，必须使用公钥证书。证书是将公钥当做一条消息，由一个可信的第三方对其签名后所得到的公钥。
二、什么是公钥证书？ 公钥证书(Public-Key Certificate，PKC)记录着个人信息(姓名、组织、邮箱地址等个人信息)和个人公钥，并由认证机构(Certification Authority、Certifying Authority，CA)施加数字签名。公钥证书也简称为证书(certificate)。
三、公钥证书标准规范 目前使用最广泛的是 ITU(International Telecommunication Union，国际电信联盟) 和 ISO(International Organization for Standardization，国际标准化组织) 制定的 X.509 规范(RFC3280)。基本上大多程序都是遵循这种证书生成和交换的标准规范。
四、公钥证书应用场景 用一个例子来展现证书的应用场景。下图是 Alice 向 Bob 发送密文的场景，在生成密文时所使用的 Bob 的公钥是通过认证机构获取的。
上图中步骤 1 - 7 是按照顺序来标识的。针对特殊步骤增加一些说明：
第一步中，Bob 的密钥可以是自己生成的，也可以由认证机构代为生成。 第三步中，认证机构在拿到 Bob 的公钥以后会开始认证这个公钥是否是 Bob 的。有三种验证等级，Class 1 通过邮箱中的邮件进行确认本人身份；Class 2 通过第三方数据库来确认本人身份；Class 3 通过当面认证和身份来确认本人身份。等级越高，身份认证越严格。 第五步中，Alice 使用认证机构 Trent 的公钥对证书中的数字签名进行验证，如果验证成功，就确认了证书中所包含的公钥是 Bob 的。 第六步中，图上虽然标识的是“公钥加密”的方式，但实际上这一步用混合加密的方式也是可以的。 上图中的步骤 1、2、3、4 并不是每次都需要这样请求。1、2、3 步只需要在注册新的公钥的时候才会进行。第四步仅在第一次需要使用公钥密码的时候需要，之后保存到了电脑中，就不用每次都请求公钥了。
五、什么是公钥基础设施 PKI？ 公钥基础设施(Public-Key Infrastructure)是为了能够更有效的运用公钥而制定的一系列规范和规格的总称。英文缩写 PKI。
PKI 是一个总称，并非指某一个单独的规范或规格。RSA 公司制定的 PKCS(Public-Key Cryptography Standards，公钥密码标准)系列规范也是 PKI 的一种，互联网规格 RFC(Request for Comments)也是 PKI 的一种，X.</description></item><item><title>消息认证码是怎么一回事？</title><link>https://new.halfrost.com/zh/message_authentication_code/</link><pubDate>Sat, 01 Sep 2018 12:01:00 +0000</pubDate><guid>https://new.halfrost.com/zh/message_authentication_code/</guid><description>一、为什么需要消息认证码？ 还是举一个银行汇钱的例子：A 向 B 汇钱 100 万元。如果攻击者从中攻击，篡改这条消息，就可能变成 A 向攻击者汇钱 1000 万元。这里针对汇款消息，需要注意两个问题：消息的 “完整性” 和 “认证” 。
消息的完整性，就叫消息的一致性，这个可以用上一篇文章中讲的消息指纹来判断，通过对比单向散列函数的 hash 值来判断这条消息的完整性，有没有被篡改。
消息的认证，指的是，消息是否来自正确的发送者。如果确认汇款请求确实来自 A，就相当于对消息进行了认证，代表消息没有被伪装。
如果同时需要识别出篡改和伪装，即要确认消息的完整性，又要对消息进行认证，这种情况下就需要消息认证码。
二、什么是消息认证码？ 消息认证码(Message Authentication Code) 是一种确认完整性并进行认证的技术，简称 MAC。
使用消息认证码可以确认自己收到的消息是否就是发送者的本意，也就是说可以判断消息是否被篡改，是否有人伪装成发送者发送了这条消息。
消息认证码也是密码学家工具箱中的 6 大工具之一：对称密码、公钥密码、单向散列函数、消息认证码、数字签名和伪随机数生成器。
消息认证码的输入包括任意长度的消息和一个发送者与接收者之间的共享密钥。输出固定长度的数据，输出的数据就是 MAC 值。
消息认证码和单向散列函数的区别就在有没有这个共享密钥上了。所以消息认证码就是利用共享密钥进行认证的。消息认证码和单向散列函数的散列值一样，如果消息发生了 1 比特的变化，MAC 值也会发生变化。所以消息认证码正是用这个性质来进行完整性的。
所以消息认证码可以理解为消息认证码是一种与密钥相关联的单向散列函数。
三、消息认证码的使用步骤 如果银行之间汇款采用消息认证码，流程会如下：
大体流程和验证单向散列函数基本一致，只不过消息认证码需要共享密钥来解出 MAC 值。
不过消息认证码的共享密钥存在密钥配送问题。密钥在配送中不能被窃听者窃取。解决密钥配送问题需要用到上上篇文章中讲的公钥密码、Diffie-Hellman 密钥交换等其他安全的方式配送密钥。
四、消息认证码使用现状 SWIFT（Society for Worldwide Interbank Financial Telecommunications&amp;mdash;环球同业银行金融电讯协会) 是一个目的为国际银行间的交易保驾护航的协会。银行和银行间通过 SWIFT 来传递交易消息，SWIFT 会利用消息认证码校验消息的完整性和对消息的验证。消息认证码的共享密钥是由人进行配送的。
IPsec 是对 IP 协议增加安全性的一种方式，在 IPsec 中，对消息的认证和完整性校验也是用消息认证码的方式。
SSL/TLS 对通信内容的认证和完整性校验也用了消息认证码。</description></item><item><title>消息的“指纹”是什么？</title><link>https://new.halfrost.com/zh/one_way_hash/</link><pubDate>Sun, 26 Aug 2018 02:49:00 +0000</pubDate><guid>https://new.halfrost.com/zh/one_way_hash/</guid><description>一、为什么需要“指纹”？ 在警察破案的时候，会经常接触到犯人的指纹。指纹能从生物的角度上判断它是不是某一个人。这么看来，指纹相当于一个人独一无二的东西，通过他就能找到对应唯一的一个人。
在网络传输过程中，可能存在中间人。那人们就有了这样的想法：能不能找到消息的“指纹”？这样就可以知道消息是谁发送的，从而避免中间人的攻击。
二、单向散列函数 开发者日常工作中会使用 git 命令。git diff 命令可以比对 2 次 commit，展示出两者不同的地方。那么相同的文件不会展示。那么 git diff 是如何对比两个文件的呢？如果一个文件巨大，能否有一个简单快捷的方式能判断文件是否被更改了呢？
这个时候文件的“指纹”的作用就凸显出来了。从一一比对 2 个文件的每一行，到现在只需要比对文件的“指纹”信息，如果一个指纹信息就能检查文件完整性，该多么方便啊！
单向散列函数就是一种采集文件“指纹”的技术。单向散列函数生成的散列值，就相当于消息的“指纹”。单向散列函数(one-way hash function)有一个输入和一个输出，其中输入成为消息(message)，输出成为散列值(hash value)。单向散列函数可以根据消息的内容计算散列值，而散列值就可以被用来检查消息的完整性。
这个的消息可以是更加广义的消息，可以是图片，也可以是声音，单向散列函数并不需要关心消息实际代表的含义。在单向散列函数的眼里只有 0、1、0、1 比特流。
单向散列函数计算出来的散列值的长度和消息的长短没有关系。以 SHA-256 为例，它计算出来的散列值永远都是 256 比特(32 字节)。
单向散列函数有以下几点性质：
1. 根据任意长度的消息计算出固定长度的散列值 2. 能够快速计算出散列值 3. 消息不同，散列值也不同 最后一点性质是最关键的。如果 2 个文件不同，算出的散列值却是相同的，那么单向散列函数的意义也就不存在了。实际上，两个不同的消息产生同一个散列值的情况称为**“碰撞(collision)”**。散列函数需要确保在不人为干涉的情况下，不存在碰撞的情况。密码学中所使用的单向散列函数，都需要具备抗碰撞性质。
单向散列函数必须要确保要找到和该条消息具有相同散列值的另外一条消息是非常困难的，这一性质称为弱抗碰撞性，单向散列函数都必须具备弱抗碰撞性。
要找到具有相同散列值但互不相同的两条消息是非常困难的，这一性质称为强抗碰撞性。这里的散列值可以是任意值。
密码技术中所使用的单向散列函数，不仅要具备弱抗碰撞性，还必须具备强抗碰撞性。
这里的弱抗碰撞性和强抗碰撞性是相对的概念，并不是说“很弱而不具备抗碰撞性”！
4. 单向性 单向散列函数必须具备单向性，单向性指的是无法通过散列值反算出消息的性质。
如上图所示，反算出消息的路是不通的。这也就是单向散列函数，单向两个字的来源。需要特别注意的一点是，单向散列函数并不是一种加密，所以它是无法通过解密的方法得到原消息的。
单向散列函数也称为消息摘要函数(message digest function)、哈希函数、杂凑函数。输入单向函数的消息也称为原像(pre-image)。单向散列函数输出的散列值也称为消息摘要(message digest)或者指纹(fingerprint)。完整性也被称为一致性。
对于攻击者来说，Hash 算法的破解难度是，强抗碰撞性&amp;lt;弱抗碰撞性&amp;lt;单向性。
三、单向散列函数的实际应用 检测软件是否被篡改 基于口令的加密 单向散列函数也被用于基于口令的加密(Password Based Encryption，PBE)。PBE 的原理是将口令和盐(salt，通过伪随机数生成器产生的随机值)混合后计算其散列值，然后将这个散列值用作加密的密钥。通过这样的方法能够防御针对口令的字典攻击。</description></item><item><title>翱游公钥密码算法</title><link>https://new.halfrost.com/zh/asymmetric_encryption/</link><pubDate>Sun, 19 Aug 2018 00:22:00 +0000</pubDate><guid>https://new.halfrost.com/zh/asymmetric_encryption/</guid><description>一、引子 在对称加密中，例如一次性密码本，就存在密钥配送的问题。在 DES、AES 中也存在这个问题。由于加密和解密的密钥是相同的，所以必须向接收者配送密钥。如果使用公钥密钥，则无需向接收者配送用于解密的密钥，这样就解决了密钥配送的问题，可以说公钥密码是密码学历史上最伟大的发明。
二、配送密钥问题 为了防止中间人截获密钥，安全的把密钥传递给通信对方。有以下 4 种方式：
1. 事先共享密钥 这种方法虽然有效，但是具有局限性。在一次性密码本中，我们说过，大国之间的热线是用这种方式加密的，但是密钥是靠特工押送过去的。如果通讯对方在附近，提前共享密钥还比较方便。如果通讯对方在世界各地，这种方式也就存在局限性了。
另外通讯量增大以后，密钥个数也会陡增。n 个人两两通讯，需要 n * (n-1) /2 个密钥。这点来看，也不现实。
2. 密钥分配中心 为了解决事先共享密钥的密钥增多的问题。于是有人想出了密钥分配中心(Key Distribution Center, KDC)的办法。每次加密的密钥由密钥中心进行分配，每个人只要和密钥中心事先共享密钥就可以了。
虽然这个方法解决了密钥增多的问题，但是又带来了新的问题。
密钥中心存储和记录了所有的密钥，一旦它出现故障或者被攻击破坏，那么所有的加密都会瘫痪。这也是集中式管理的缺点。
3. Diffie-Hellman 密钥交换 为了解决集中式管理的缺点，那么应该密钥的配送还是不能用集中式。于是有人想出了 Diffie-Hellman 密钥交换的方法。
在 Diffie-Hellman 密钥交换中，加密通信双方需要交换一些信息，而这些信息即便被窃听者窃听，也不会有任何问题。
根据交换的信息，双方各自生成相同的密钥。而窃听者无法生成相同的密钥。这种方式可行。不过这种方式不算是非对称加密，在本文中不详细讨论。
4. 公钥密码 非对称加密有一个公钥和一个私钥。公钥可以在网上传播，被窃听者拿到也没有关系，由于没有私钥，他也无法解开密文。私钥只要掌握在接收者手上就不会导致密文被窃听。
举个例子：超市里面的存包处，所有顾客有硬币就可以存包。硬币就是“公钥”，顾客把包放进箱子里，（明文加密），箱子锁上以后就没人能打开。这个时候窃听者也拿不走存进去的包。这个明文（包），只有私钥才能打开。客户存完包以后会生成一个私钥，只要这个钥匙在手，就可以随时开箱拿包。
三、非对称加密 非对称加密一般指的是具有公钥密钥(public-key cryptography)的加密算法。密钥分为加密密钥和解密密钥两种。发送者用加密密钥对信息进行加密，接收者用解密密钥对密文进行解密。可以公开出去的叫公钥(public key)，保存在自己手上不公开的叫私钥(private key)。
公钥和私钥是一一对应的。一对公钥和私钥统称为密钥对(key pair)。在数学的关系上，这两者不能单独生成。
四、非对称加密存在的问题 公钥密码虽然解决了密钥配送的问题，但是并不意味着它解决了所有问题。公钥密码存在以下几个问题：
公钥认证 处理速度不到对称加密的十分之一 五、RSA 算法流程 RSA 是一种公钥密码算法，它的名字是由它的三位开发者，即 Ron Rivest、Adi Shamir 和 Leonard Adleman 的姓氏的首字母组成的 (Rivest-Shamir-Adleman)。1983 年，RSA 公司为 RSA 算法在美国取得了权利，但是现在该专利已经过期了。
RSA 可以被用于公钥密码和数字签名。</description></item><item><title>漫游对称加密算法</title><link>https://new.halfrost.com/zh/symmetric_encryption/</link><pubDate>Sat, 11 Aug 2018 17:06:00 +0000</pubDate><guid>https://new.halfrost.com/zh/symmetric_encryption/</guid><description>一、引子 在引出对称加密之前，有必要先介绍一种位运算，XOR。XOR 的全称是 exclusive or，中文翻译是异或。
0 XOR 0 = 0 0 XOR 1 = 1 1 XOR 0 = 1 1 XOR 1 = 0 XOR 可以看成是“两个数相同，异或为 0 ，不同则异或为 1”。
异或也叫半加运算，其运算法则相当于不带进位的二进制加法：二进制下用1表示真，0表示假，则异或的运算法则为：
0 ⊕ 0 = 0 1 ⊕ 0 = 1 0 ⊕ 1 = 1 1 ⊕ 1 = 0 这些法则与加法是相同的，只是不带进位，所以异或常被认作不进位加法。由异或的这种特点，也就引出了它的一个常用特性，两个相同的数进行 XOR 运算的结果一定为 0。
对应的，我们也可以得到如下的运算法则：
1. a ⊕ a = 0 2. a ⊕ b = b ⊕ a 交换率 3.</description></item><item><title>密码学概述</title><link>https://new.halfrost.com/zh/cryptography_overview/</link><pubDate>Sat, 04 Aug 2018 17:01:00 +0000</pubDate><guid>https://new.halfrost.com/zh/cryptography_overview/</guid><description>一、为什么需要加密 每个人都有自己的秘密，如果不加密，在网上传输很容易被监听。如果涉及到金钱相关，密码泄露以后很容易造成损失。所以都会利用加密 cryptography 技术，保证信息的机密性 confidentiality。
信息被加密以后变成了密文在网上传播，接收者拿到密文进行解密 cryptanalysis，解密以后就可以看到明文。
进行破译密码的人叫破译者，破译者不一定都是坏人，密码学研究者为了研究密码强度，也会需要对密码进行破译，研究者在这种情况下也是破译者。
加密与压缩的顺序？
压缩一定在加密之前。因为加密以后，比特序列的冗余性消失，基本上无法再压缩了。在加密前进行压缩的做法不仅仅限于混合密码系统，而是对所有密码都适用。
二、对称加密 对称密码 (symmetric cryptography)是指在加密和解密时使用同一密钥的方式。对应的加密方式是对称加密。目前广泛使用 AES。
对称密码有多种别名，公共密钥密码(common-key cryptography)，传统密码(conventional cryptography)，私钥密码(secret-key cryptography)，共享密钥密码(shared-key cryptography)等。
对称密码需要解决将解密密钥配送给接收者的密钥配送问题。
三、非对称加密 公钥密码 (public-key cryptography)则是指在加密和解密时使用不同密钥的方式。对应的加密方式是非对称加密。目前广泛使用 RSA。(RSA、ElGamal、Rabin、DH、ECDH)
公钥密码解决了密钥配送的问题，但是存在通过中间人攻击被伪装的风险，因此需要对带有数字签名的公钥进行认证。
四、单向散列函数 网上很多免费的软件，为了防止软件被篡改，有安全意识的软件发布者会在发布软件的同时会发布这个版本软件的散列值 hash。散列值是用单向散列函数(one-way hash function)计算出来的数值。目前广泛使用 SHA-2(SHA-224、SHA-356、SHA-384、SHA-512) 和 具有全新结构的 SHA-3(Keccak 算法)
散列值 hash，又被称为哈希值，密码校验和(cryptographic checksum)，指纹(fingerprint)，消息摘要(message digest)。
单向散列函数并不是为了保证消息的机密性，而是完整性(integrity)。完整性指的是，数据是正确的，而不是伪造的。单向散列函数是保证信息的完整性的密码技术，它会检测数据是否被篡改。
单向散列函数可以单独使用，也可以作为消息认证码、数字签名以及伪随机数生成器等技术的组成元素使用。
五、消息认证码 为了确认消息是否来自期望的通信对象，可以通过使用消息认证码(message authentication code)。消息认证码主要是提供了认证(authentication)机制，与此同时它也能保证消息的完整性。
消息认证码中最常用的单向散列函数是 HMAC。HMAC 的构成不依赖于某一种具体的单向散列函数算法。
消息认证码能对通信对象进行认证，但无法对第三方进行认证。它也无法防止否认。消息认证码可以用来实现认证加密。
六、数字签名 试想有这样一种情况，A 欠 B 100 万美刀，于是 A 向 B 打了一张欠条。一周以后，A 拿到钱以后就不承认那张欠条是自己写的，抵赖借钱了。
这个时候就牵扯到密码学里面的防抵赖的技术 —— 数字签名。数字签名类似现实世界中的签名和盖章，数字签名是一种能防止用户抵赖，伪装，篡改和否认的密码技术。目前广泛使用的数字签名算法包括 RSA、ElGamal、DSA、椭圆曲线 DSA(ECDSA)、爱德华兹曲线 DSA(EDDSA)等。</description></item><item><title>如何快速给自己构建一个温馨的"家"——用 Jekyll 搭建静态博客</title><link>https://new.halfrost.com/zh/jekyll/</link><pubDate>Mon, 20 Jun 2016 10:17:00 +0000</pubDate><guid>https://new.halfrost.com/zh/jekyll/</guid><description>前言 我相信，每个程序员都有一个愿望，都想有一个属于自己的&amp;quot;家&amp;rdquo;——属于自己的博客，专属的网站。在自己的“家”中，可以和志同道合的兄弟一起分享和讨论任何技术，谈天说地。更重要的是可以当做自己的技术积累，提升自己实力。那么接下来就来说说我博客搭建过程。
目录： 本地搭建Jekyll 开发或者选择Jekyll主题 使用Github Pages服务 申请个人域名 给博客增加访客评论功能 申请&amp;quot;小绿锁&amp;quot;HTTPS 日后维护 一.本地搭建Kekyll Jekyll是什么？它是一个简单静态博客生成工具，相对于动态博客。
简单。因为它是不需要数据库的，通过markdown编写静态文件，生成Html页面，它的优点是提升了页面的响应速度，并且让博主可以只专注于写文章，不用再去考虑如何排版。 静态。Markdown（或 Textile）、Liquid 和 HTML &amp;amp; CSS 构建可发布的静态网站。 博客支持。支持自定义地址、博客分类、页面、文章以及自定义的布局设计。 //使用gem安装Jekyllgem install jekyll//使用Jekyll创建你的博客站点jekyll new blog #创建你的站点//开启Jekyll服务//进入blog目录,记得一定要进入创建的目录，否则服务无法开启cd blog jekyll serve #启动你的http服务 本地服务开启后，Jekyll服务默认端口是4000，所以我打开浏览器，输入：http://localhost:4000 即可访问
到这里一个简单的博客页面就会显示出来了。
关于jekyll其他一些命令的用法如下:
$ jekyll build# =&amp;gt; 当前文件夹中的内容将会生成到 ./_site 文件夹中。$ jekyll build --destination &amp;lt;destination&amp;gt;# =&amp;gt; 当前文件夹中的内容将会生成到目标文件夹&amp;lt;destination&amp;gt;中。$ jekyll build --source &amp;lt;source&amp;gt; --destination &amp;lt;destination&amp;gt;# =&amp;gt; 指定源文件夹&amp;lt;source&amp;gt;中的内容将会生成到目标文件夹&amp;lt;destination&amp;gt;中。$ jekyll build --watch# =&amp;gt; 当前文件夹中的内容将会生成到 ./_site 文件夹中，# 查看改变，并且自动再生成。$ jekyll serve# =&amp;gt; 一个开发服务器将会运行在 http://localhost:4000/# Auto-regeneration（自动再生成文件）: 开启。使用 `--no-watch` 来关闭。$ jekyll serve --detach# =&amp;gt; 功能和`jekyll serve`命令相同，但是会脱离终端在后台运行。# 如果你想关闭服务器，可以使用`kill -9 1234`命令，&amp;#34;1234&amp;#34; 是进程号（PID）。# 如果你找不到进程号，那么就用`ps aux | grep jekyll`命令来查看，然后关闭服务器。[更多](http://unixhelp.</description></item></channel></rss>