Skip to content

Commit

Permalink
更新文章
Browse files Browse the repository at this point in the history
  • Loading branch information
ProphetHJK committed Aug 21, 2024
1 parent 2e14f82 commit cf2a87a
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 58 deletions.
21 changes: 7 additions & 14 deletions _posts/2021-06-09-tls-tech.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,24 @@ DH 算法解决了密钥在双方`不直接传递密钥`的情况下完成密钥

我们来看 DH 算法交换密钥的步骤。假设甲乙双方需要传递对称密钥,他们之间可以这么做:

甲首选选择一个素数`p`,例如`509`,底数`g`,任选,例如 5,随机数`a`,例如 123,然后计算`A=g^a mod p`,结果是 215,然后,甲发送 p = 509,g=5,A=215 给乙;
乙方收到后,也选择一个随机数`b`,例如,456,然后计算`B=g^b mod p`,结果是 181,乙再同时计算`s=A^b mod p`,结果是 121;
乙把计算的 B=181 发给甲,甲计算`s=B^a mod p`的余数,计算结果与乙算出的结果一样,都是 121。
使用整数的乘法组 modulo p,其中 p 是素数(prime),g 是 modulo p 的一个原始根(primitive root)。下面是协议的一个示例,非 secret 值用 $\textcolor{blue}{蓝色}$ 表示,secret 值用 $\textcolor{red}{红色}$ 表示。

所以最终双方协商出的密钥 s 是 121。注意到这个密钥 s 并没有在网络上传输。而通过网络传输的 p,g,A 和 B 是无法推算出 s 的,因为实际算法选择的素数是非常大的。
![alt text](/assets/img/2021-06-09-tls-tech/image.png)

注意到这个密钥 s 并没有在网络上传输。而通过网络传输的公开的 p,g,A 和 B 是很难推算出 s 的,因为实际算法选择的素数 p 是非常大的(g 不需要很大,通常就 2,3,...)。

所以,更确切地说,DH 算法是一个密钥协商算法,双方最终协商出一个共同的密钥,而这个密钥不会通过网络传输。

> **DH 算法的安全性**
>
> 数字可以分为两大部分:
> 不可再分的数:prime number 质数
> 可以再分的数:composite number 和数
>
> 每个数字可以描述为一个“锁”
> 每个数字有且只有一种质因数分解,把质因数分解看做是“钥匙”,任何两个数的质因数分解都不同。
> 如果已知 g和g^a mod p,要计算出 a是困难的,这就是离散对数问题。离散对数问题被认为是困难的,没有已知的有效算法可以在合理时间内解决它。这种困难性是Diffie-Hellman协议安全性的基础。
>
> 对于锁,有一个基本的要求:朝一个方向容易,朝反方向难。one-way function 单向函数。
> 在数学中,模算术(时钟算术)就是一个单向函数 X MOD P,如果 P 选择为质数,那么其值会在时钟上(1 到 P-1 上)等可能均匀分布。
> 正向计算 3^x mod 17 = ?很容易
> 反向计算 3^? mod 17 = 12 不容易,比如说 P 选择一个数百位的质数,那么想求出?只能采用试错法
> 反向计算 3^? mod 17 = 12 不容易
>
> 在 DH 算法握手的过程中,指数不会被传递,也就是说在网络攻击中指数是需要被破解的对象,即使该密钥被暴力破解,也可以通过定期更新密钥的方式大大增加破解工作量
详见[迪菲-赫爾曼密鑰交換维基百科](https://zh.wikipedia.org/wiki/%E8%BF%AA%E8%8F%B2-%E8%B5%AB%E7%88%BE%E6%9B%BC%E5%AF%86%E9%91%B0%E4%BA%A4%E6%8F%9B)
详见[Diffie–Hellman key exchange维基百科](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)

### DHE 密钥交换

Expand Down
14 changes: 6 additions & 8 deletions _posts/2022-03-17-dlms-blue2.md
Original file line number Diff line number Diff line change
Expand Up @@ -427,17 +427,15 @@ COSEM logical devices能够在COSEM context中`使用SN引用建立AAs`,使用
|StoC->||
||<-f(StoC)加密处理后的结果|

data数据是客户端对服务端的回复

TODO:请求和回复的数据是什么

回应数据:
参数:

服务端对 f(StoC) 的处理结果

如果认证被接受,则响应(Read.confirm 原语)包含 Result == OK 和服务器对客户端质询服务器的 secret 处理结果,在 Read 的数据服务参数中 f(CtoS) 响应服务。
返回值:

data数据是服务端对客户的回复
如果认证被接受,则响应(Read.confirm 原语)包含 Result == OK 和服务器对客户端质询服务器的 secret 处理结果,在 Read 的数据服务参数中 f(CtoS) 响应服务。如果认证不被接受,则返回non-OK值,不再包含其他数据。

如果认证不被接受,则返回non-OK值,且不包括data
[G9.2.2.2 Identification and authentication](/posts/dlms-green-1/#s9222-identification-and-authentication)

- add_user (data) 向user_list添加一个用户
- remove_user (data) 从user_list移除一个用户
Expand Down
48 changes: 28 additions & 20 deletions _posts/2022-03-17-dlms-green-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -2698,7 +2698,7 @@ Server Max Receive PDU Size
- Pass 1:客户端发送一个“challenge”CtoS 信息,以及根据身份验证机制附加的信息给服务器;
- Pass 2:服务器发送一个“challenge”StoC 信息,以及根据身份验证机制附加的信息给客户端;

> 如果 StoC 与 CtoS`相同`,客户应`拒绝并中止`AA 建立过程。所以 StoC 与 CtoS 必须是独立生成的且不同的。
> 如果 StoC 与 CtoS`相同`,客户应`拒绝并中止`AA 建立过程。所以 StoC 与 CtoS 必须是独立生成的且不同的。(为了使这两个值一定不同,应该可以用 systemtitle 作为前缀,再加上随机生成的值)
{: .prompt-tip }

- Pass 3:`客户端`根据对给定 AA 有效的 HLS 身份验证机制的规则处理`StoC``其他信息`,并将结果`发送`给服务器。服务器检查`f(StoC)`是否是正确处理的结果,如果是,则`接受`客户端的身份验证
Expand All @@ -2710,6 +2710,8 @@ Server Max Receive PDU Size

pass3 和 4 依赖于 reply_to_HLS_authentication

TODO:从 [control-function](#s9412-state-definitions-of-the-server-side-control-function) 状态图来看,只要 COSEM-OPEN 服务完成即可认为 AA 建立成功,但这里在 HLS 过程中,还需要完成 pass 3和4,才算 AA 建立完成,有冲突。

##### s9.2.2.3 Security context

- `安全套件security suite`,确定可用的安全算法,参见 9.2.3.7;
Expand Down Expand Up @@ -3807,7 +3809,7 @@ COSEM-OPEN 服务的作用是在对端 COSEM 应用实体(AEs)之间建立 AA。

- Protocol_Connection_Parameters

强制。 它包含使用通信配置文件层所必需的所有信息,包括通信配置文件(协议)标识符和所需的地址。 它确定了 AA 的参与者。 该参数的元素被传递给管理低层连接的实体,并酌情传递给低层。
强制。它包含使用通信配置文件层所必需的所有信息,包括通信配置文件(协议)标识符和所需的地址。它确定了 AA 的参与者。该参数的元素被传递给管理低层连接的实体,并酌情传递给低层。

- ACSE_Protocol_Version

Expand All @@ -3817,10 +3819,12 @@ COSEM-OPEN 服务的作用是在对端 COSEM 应用实体(AEs)之间建立 AA。

强制。在请求原语中,它持有客户端`提议`的值。在响应原语中,它保存相同的值或服务器`支持`的值。(类似于 TLS 握手中的加密策略,是一个需要`协商`的值)

见 [registered-cosem-names](#s9422-registered-cosem-names)

- Called_AP_Title, Called_AE_Qualifier, Called_AP_Invocation
\_Identifier, Called_AE_Invocation_Identifier

可选
可选。本技术报告不包含

- Calling_AP_Title

Expand All @@ -3832,7 +3836,7 @@ COSEM-OPEN 服务的作用是在对端 COSEM 应用实体(AEs)之间建立 AA。

- Calling_AP_Invocation_Identifier

可选。
可选。本技术报告不包含

- Calling_AE_Invocation_Identifier

Expand All @@ -3852,7 +3856,7 @@ COSEM-OPEN 服务的作用是在对端 COSEM 应用实体(AEs)之间建立 AA。

- Responding_AP_Title

有条件的。当协商的应用程序上下文和/或协商的 HLS 认证机制要求使用服务器系统标题,并且在注册过程中尚未转移时,则 Responding_AP_Title 应携带服务器`系统标题system title`。
有条件的。当协商的应用程序上下文和/或协商的 HLS 认证机制要求使用服务器 system title,并且在注册过程中尚未转移时,则 Responding_AP_Title 应携带服务器`system title`。

- Responding_AE_Qualifier

Expand All @@ -3872,15 +3876,17 @@ COSEM-OPEN 服务的作用是在对端 COSEM 应用实体(AEs)之间建立 AA。

- Security_Mechanism_Name

有条件的。
有条件的。携带客户端的推荐值,或服务端的支持值

见 [COSEM_Authentication_Mechanism_Name](#s9422-registered-cosem-names)

- The Calling_Authentication_Value、the Responding_Authentication_Value

有条件的。
有条件的。两者分别保存客户端和服务端的 Security_Mechanism_Name 的验证值

- Implementation_Information

可选的
可选的。本技术报告不包含

- Proposed_xDLMS_Context

Expand All @@ -3896,7 +3902,7 @@ COSEM-OPEN 服务的作用是在对端 COSEM 应用实体(AEs)之间建立 AA。

- `User_Information`

> 请不要将 COSEM-OPEN 服务的`User_Information`参数与 AARQ / AARE apdu 的`user-information`字段`混淆`。
> 不要将 COSEM-OPEN 服务的`User_Information`参数与 AARQ / AARE apdu 的`user-information`字段`混淆`。
{: .prompt-tip }

- Service_Class
Expand Down Expand Up @@ -4254,9 +4260,9 @@ CF 使用收到的 APDU 参数生成 COSEM-OPEN.indication 给服务器 AP ,
>
> - 一个本地通信端口(IEC 62056-21,红外)同时仅允许打开一个 AA
> - 一个远程通信端口(IP)同时允许打开多个 AA
> - 不同通信端口同时可以分别打开 AA
> - 不同通信端口可以同时分别打开 AA
> - 如果客户端希望同时使用多个通信端口,则必须在每个通信端口分别打开对应的 AA。(比如不能在 IP 通道打开 AA 后用于红外通道的数据通信)
> - Synchronization of Internal memory access must be handled by the manufacturer.(不理解
> - Synchronization of Internal memory access must be handled by the manufacturer.(不太理解,推测是:为了实现上面几条需要的不同通信端口间的内部信息同步有厂家自行实现

##### s9.4.4.2 Repeated COSEM-OPEN service invocations

Expand Down Expand Up @@ -4681,18 +4687,20 @@ GBT APDU 字段:

最后一包管理。

- client-server services
- confirmed client-server services

客户端发送请求,LB=0,直到最后一包,LB=1。此时SQ应该空了,如果收到服务端响应,需要向SQ填充空的确认包,再发送,LB=1,如此重复。
客户端发送请求,LB=0,直到最后一包,LB=1。此时SQ应该空了,如果收到服务端响应,需要向SQ填充**空的确认包**,再发送,此时LB=1,如此重复。(如果服务端的 LB=1 这包丢了,就等超时后重复请求,直到收到 服务端 LB=1 的包)

服务端发送的LB=0,直到收到客户端LB=1的包(请求发完后以及确认包的LB都为1)且是服务端的最后一包,LB=1。也就是说在响应请求的确认包LB都为0。印证了Figure 141中空的确认包的LB可以为0或1。
服务端发送LB=0,直到收到客户端LB=1的包(请求发完后以及确认包的LB都为1)且是服务端的最后一包,发送LB=1,服务端等待超时无请求后退出 GBT
- unsolicited, confirmed service

需确认的上报
该服务类型为需确认的上报

服务端发送上报 LB=0 直到发送最后一包 LB=1,等待客户端响应 LB=1,如果没有,等待超时后重复上报,直到收到后退出 GBT。

服务端发送上报LB=0直到最后一包LB=1(因为服务端不需要对客户端的响应做确认)
客户端发送确认和响应都是LB=0,直到收到服务端LB=1且客户端已经发送完最后一包,客户端发送 LB=1,客户端等待超时未接收数据后退出 GBT。

客户端发送确认和响应都是LB=0,直到收到服务端LB=1且是客户端的最后一包
总结:谁主动发起,谁负责保证 GBT 完成。第一种情况中 client 主动发起,它负责接收到服务端的 LB=1 才能退出,否则要重发。server 端作为被动方如果一段时间没收到数据则自行退出。

> TODO:9.4.6.13.4.3.1 If the SQ is empty, an empty block is added to the SQ and Nex tBN is incremented.为什么要加入空的 block,这个空的好像是确认包 更新:9.4.6.13.4.3.2 Last block management中提到了如果客户端把请求的APDU全发完了,那发送队列就空了,这时候还需要对服务端的响应回确认,所以还需要空的block。或者当服务端在接收请求回确认时SQ也是空的,需要填充确认包
{: .prompt-warning }
Expand Down Expand Up @@ -4750,7 +4758,7 @@ GBT APDU 字段:
1. RQ为空时全部重传,Wself(接收窗口大小)设置为BTW也就是最大窗口
2. RQ不为空时检查gaps,为空时表示无需重传,BNAself(己方确认)设置为B.BN(确认最后一包);不为空时表示还有需要重传的,此时Wself应设置为小于等于要重传的第一个gap大小(比如只丢了一个包或者说第一个gap只需要重传一个包,就重传一个包,接收窗口设为1就行,这样只要提供起始序号和窗口大小,对方就知道要补几个包了),开始请求重传。

> `gap`可以理解为一个连续的丢包块
> `gap(缺口)`可以理解为一个连续的丢包块
>
> 比如1x2x3√4x5√6√7√
>
Expand All @@ -4764,7 +4772,7 @@ GBT APDU 字段:

![messages](/assets/img/2022-03-17-dlms-green-1/getwithgbt.jpg)

> TODO:图里的 GET.cnf NORMAL(FIRST-PART)是否是一种 AL 向 AP 请求 GBT 参数的机制,前提是 AL 不知道相关的参数,所以 GET.req NORMAL(COMPLETE)其实是个空的报文?结合 9.3.5 Additional service parameters,这个参数是否应该在这个原语里携带。更新:the client AP invokes a GET.request NORMAL service primitive, without additional service parameters. The client AL sends the request in a Get-Request-Normal APDU 明确提到了 GET 相关原语可以携带 Additional service parameters
> TODO:图里的 GET.cnf NORMAL(FIRST-PART)是否是一种 AL 向 AP 请求 GBT 参数的机制,前提是 AL 不知道相关的参数,所以 GET.req NORMAL(COMPLETE)其实是个空的报文?结合 9.3.5 Additional service parameters,这个参数是否应该在这个原语里携带。更新:the client AP invokes a GET.request NORMAL service primitive, without additional service parameters. The client AL sends the request in a Get-Request-Normal APDU 明确提到了 GET 相关原语可以携带 Additional service parameters。所以这里就是请求 GBT 参数,因为对方发起了 GBT ,AL 需要 AP 的许可来使用 GBT 发送。
{: .prompt-warning }

![messages](/assets/img/2022-03-17-dlms-green-1/getservicewithpartial.jpg)
Expand Down Expand Up @@ -4793,7 +4801,7 @@ GBT 终止条件:

1. 收到专用于终止命令的 GBT APDU: LB = 1, STR = FALSE, `BN = 0` and BNA = 0;
2. 开始新的 GBT 过程。收到 BN = 1 and BNA = 0;
3. 收到 APDU 而不是 GBT
3. 收到 GBT 服务以外的 APDU
4. confirmed 服务超时未收到确认

无法终止 GBT with unconfirmed DataNotification
Expand Down
46 changes: 34 additions & 12 deletions _posts/2024-01-15-eeprom-raid1.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,47 @@ tags: [eeprom]
| :----------------: | :----------------: | :-------: |
| 512pages X 64Bytes | 512pages X 64Bytes | 4096Bytes |

以上例子中实际可用的应用数据存储区为存储区 1 的大小,存储区 2 的存在同时提供了临时数据保存和备份功能
以上例子中实际可用的应用数据存储区为存储区 1 的大小,存储区 2 的存在同时提供了事务和备份功能

## 日志结构

日志由多条记录组成,新记录在上一条记录后追加写入:

- 单条记录:

| 页号 1 | 页号 2 | 新标志<br>(新 CRC) | 新数据临时区域指针<br>(可选) | 结束符 |
| :----: | :----: | :----------------: | :--------------------------: | :----: |
| 2 | 2 | 2 | 2 | 2 |
一个事务由一条记录构成

- 结束符:用于判断记录是否完整,以及分割不同记录
| | 页号1<页10> | 页号2<页23> |页号3<页12><br>(最后一页) | 最后页<br>新标志 | 新数据临时区域指针<br>(可选) | 结束符 |
| :--: | :----: | :----: |:------------------: | :--------------: | :--------------------------: | :----: |
| 字节 | 2 | 2 | 2 | 6 | 2 | 2 |

- 结束符:用于判断记录是否完整(整条记录的CRC),以及分割不同记录
- 新数据临时区域指针:指向用于单事务多次写入时存放临时数据的区域,可以为内存或持久性存储。
- 操作单元:由页号+新标志组成,一条记录可包含多个操作单元
- 页号:对应逻辑页的编号
- 新标志:(可选,仅最后一页强制)判断是否为新数据,分两种方式, CRC 或指定特征,当 CRC 相同(碰撞)时需要启用指定特征
- CRC:为了防止数据异常时 CRC 碰撞,此处可以考虑使用 CRC32,但需要考虑性能,因为这可能需要重新计算。
- 指定特征:只要能识别新数据就行,可以使用**偏移+差异值**的方式标识新数据
- 页号列表:对应逻辑页的编号,和写入顺序
- 最后页新标志:判断最后一页是否为新数据,分两种方式, CRC 或指定特征,当 CRC 相同(碰撞)时需要启用指定特征
- CRC:为了防止数据异常时 CRC 碰撞,此处可以考虑使用 CRC32,但需要考虑性能,因为这可能需要重新计算。
- 指定特征:只要能识别新数据就行,可以使用**偏移+差异值**的方式标识新数据

- 多条等长记录

一个事务由多条等长的记录组成:

|序号|记录说明|
|:---:|:---:|
|1|开始记录(事务信息)|
|2|记录1<页10>|
|3|记录2<页23>|
|4|记录3<页12>|

除了开始记录外的其他记录格式:

| | 页号 | 页新标志 |
| :--: | :--: | :------: |
| 字节 | 2 | 6 |

开始记录的作用是分隔不同的事务,以及记录事务相关信息(整个事务CRC,记录数量)

该方式原生支持多次写入,无需**新数据临时区域**,比如先写记录1和记录2,向主区写入页10和页23,此时掉电,可以根据记录数量判断事务第一阶段未完成,恢复页23和页10。既有单次写入事务时的**仅写一次日志**特性,又能支持多次写入事务。

## 写入流程

Expand All @@ -50,10 +72,10 @@ tags: [eeprom]
### 事务多次写入

1. 方案一:多次转单次
每次写入时,将数据页写入临时区域,将对应操作单元(包括页号、旧标志、临时区域指针)写入记录中,直到事务全部调用完成,为记录写入 END 标记。然后按照单次写入相同的方式将临时区域内数据写入正常数据区。
每次写入时,将数据页写入临时区域,将对应操作单元(包括页号、新标志、临时区域指针)写入记录中,直到事务全部调用完成,为记录写入 END 标记。然后按照单次写入相同的方式将临时区域内数据写入正常数据区。

2. 方案二:
每次写入时,先将操作单元写入记录,然后写入新数据,直到事务全部调用完成,为记录写入 END 标记。但上电启动时若无 END 标记则需要恢复所有页到旧数据。
每次写入时,先将操作单元写入记录,然后写入新数据,直到事务全部调用完成,为记录写入 END 标记。但上电启动时若无 END 标记则需要恢复所有页到旧数据。(TODO:旧数据很有可能全被覆盖了,怎么保证能恢复?)

## 上电恢复流程

Expand Down
Loading

0 comments on commit cf2a87a

Please sign in to comment.