安全协议系列(二)----CCM与CCMP

CCMP(CTR with CBC-MAC Protocol) 是 IEEE 802.11i 中推出使用基于 AES 的 CCM 模式的安全加密协议。
与原来脆弱的 WEP 算法及临时补救措施 TKIP 协议相比,它具有更好的安全性,在 WiFi 中得到广泛的应用。

CCM(Counter with CBC-MAC) 定义在 RFC 3610 中,它是一种使用分组算法(例如 AES)进行数据认证和加密的通用模式。

下面是 RFC 3610 中重要部分的中文注释说明

1.  Introduction

   Counter with CBC-MAC (CCM) is a generic authenticated encryption block cipher mode.
CCM 对明文数据(记为 m,其长度记为 l(m))进行分组加密和认证,处理结果同时包括密文和认证字段

   CCM is defined for use with 128-bit block ciphers, such as the Advanced Encryption Standard (AES).
专门用于 block size 为 128 位的分组加密算法,如 AES

2.  CCM Mode Specification

   For the generic CCM mode there are two parameter choices.
CCM 有 2 个参数选项

   The first choice is M, the size of the authentication field.
Valid values are 4, 6, 8, 10, 12, 14, and 16 octets.
第 1 个选项: M -- 输出的认证字段长度(单位:字节),取值范围:4, 6, 8, 10, 12, 14, and 16

   The second choice is L, the size of the length field.
Valid values of L range between 2 octets and 8 octets.
第 2 个选项: L -- 表示 l(m) 值的字节数( l(m) < 2^(8L) ),取值范围:2-8

   将 M 和 L 转换为 M' 和 L'(以便容纳在一个字节中),转换关系如下
Name  Description                               Size    Encoding
----  ----------------------------------------  ------  --------
M'    Number of octets in authentication field  3 bits  (M-2)/2
L'    Number of octets in length field          3 bits  L-1

   CCMP 协议规定:M = 8 L = 2, 即 m 最长为 65535 字节,认证字段为 8 字节

2.1.  Inputs -- 认证加密 m 所需的参数

   1.  An encryption key K suitable for the block cipher.
分组密钥 K

   2.  A nonce N of 15-L octets.  Within the scope of any encryption key K,
the nonce value MUST be unique.
随机数 N,15-L 字节长,在 K 的生命过程中要确保 N 不被重复使用

   3.  The message m, consisting of a string of l(m) octets where 0 <=
l(m) < 2^(8L).  The length restriction ensures that l(m) can be
encoded in a field of L octets.
此段内容上面已讲得很清楚

   4.  Additional authenticated data a, consisting of a string of l(a)
octets where 0 <= l(a) < 2^64.  This additional data is
authenticated but not encrypted, and is not included in the
output of this mode.  It can be used to authenticate plaintext
packet headers, or contextual information that affects the
interpretation of the message.  Users who do not wish to
authenticate additional data can provide a string of length zero.
附加认证数据 a,用于数据的完整性校验(不参与加密运算),可选
       通常用于认证 报文头的明文字段 或 对消息理解有影响的上下文

   The inputs are summarized as:

      Name  Description                                 Size
----  -----------------------------------         -----------------------
K     Block cipher key/分组加密密钥                 Depends on block cipher
N     Nonce/随机数                                 15-L octets
m     Message to authenticate and encrypt         l(m) octets
a     Additional authenticated data/附加认证数据    l(a) octets

2.2.  Authentication -- 生成认证字段

   The first step is to compute the authentication field T.  This is
done using CBC-MAC [MAC].  We first define a sequence of blocks B_0,
B_1, ..., B_n and then apply CBC-MAC to these blocks.
第一步计算认证字段 T,使用 CBC-MAC 算法,该算法涉及输入分组 B_0,B_1, ..., B_n

   The first block B_0 is formatted as follows, where l(m) is encoded in
most-significant-byte first order:
第一个数据分组 B_0 构成如下
Octet Number   Contents
------------   ---------
0              Flags          1    字节
1 ... 15-L     Nonce N        15-L 字节
16-L ... 15    l(m)           L    字节(L 的值见 Flags 字节)

   Within the first block B_0, the Flags field is formatted as follows:
分组 B_0 中的首字节 Flags 构成如下
Bit Number   Contents
----------   ----------------------
7            Reserved (always zero)
6            Adata
5 ... 3      M' (1--7) = (M-2)/2  (M:4--16)
2 ... 0      L' (1--7) = L-1      (L:2--8)
Another way say the same thing is:  Flags = 64*Adata + 8*M' + L'.

   B_0 构成如下
    长度   1      15-L           L
   +----+-----+-----------+------------+
   |字节 |  0  | 1 .. 15-L | 16-L .. 15 |
   +----+-----+-----------+------------+
   |内容 |Flags|  Nonce N  |  m 的长度  |
   +----+-----+-----------+------------+
       /      \                  ^
      /        \                 |
     /          \     L -- m 的长度表示范围
    /            \     (L 越大,m 可以越长)
   / Flags 展开后  \              |
   +----+-+-----+-+-+-+-+-+-+    |L'(L) 决定
   |位  |7|  6  |5|4|3|2|1|0|    |Nonce 的长度
   +----+-+-----+-+-+-+-+-+-+    |
   |内容 |0|Adata| M'  | L'  | ---+
   +----+-+-----+-+-+-+-+-+-+

   The Adata bit is set to zero if l(a)=0, and set to one if l(a)>0.
如果 Bit6(Adata 位)=0,表示要生成附加认证数据 a,否则表示没有

   If l(a)>0 (as indicated by the Adata field), then one or more blocks
of authentication data are added.  These blocks contain l(a) and a
encoded in a reversible manner.  We first construct a string that
encodes l(a).
生成附加认证数据 a,需要构造认证数据块(一个或多个),数据块编码如下

   If 0 < l(a) < (2^16 - 2^8), then the length field is encoded as two
octets which contain the value l(a) in most-significant-byte first
order.
a 长度 < 65536-256,此情况比较普遍

   The length encoding conventions are summarized in the following
table.  Note that all fields are interpreted in most-significant-byte
first order.

    First two octets   Followed by       Comment
-----------------  ----------------  -------------------------------
0x0000             Nothing           Reserved
0x0001 ... 0xFEFF  Nothing           For 0 < l(a) < (2^16 - 2^8)
0xFF00 ... 0xFFFD  Nothing           Reserved
0xFFFE             4 octets of l(a)  For (2^16 - 2^8) <= l(a) < 2^32
0xFFFF             8 octets of l(a)  For 2^32 <= l(a) < 2^64

   The blocks encoding a are formed by concatenating this string that
encodes l(a) with a itself, and splitting the result into 16-octet
blocks, and then padding the last block with zeroes if necessary.
These blocks are appended to the first block B0.
将 l(a)||a 分成 16 字节长的分组,必要时最后一个分组添加 0x00 补齐
   这些分组依次添加到 B_0 后面(记为 B_1、B_2……)

   After the (optional) additional authentication blocks have been
added, we add the message blocks.  The message blocks are formed by
splitting the message m into 16-octet blocks, and then padding the
last block with zeroes if necessary.  If the message m consists of
the empty string, then no blocks are added in this step.
附加认证分组添加后,我们构造明文分组,将 m 分成 16 字节长的分组
   必要时最后一个分组补 0 对齐(如果 m 为空串,则此步省略)

   The result is a sequence of blocks B0, B1, ..., Bn.  The CBC-MAC is
computed by:
最终得到 B_0||附加认证分组||明文分组,按下列公式计算 CBC-MAC

      X_1   := E( K, B_0 )
X_i+1 := E( K, X_i XOR B_i )  for i=1, ..., n
T     := first-M-bytes( X_n+1 ) -- T 作为 MAC 值

        B_0       B_1       B_2               B_n
|         |         |                 |
|         V         V                 V
|    +-->XOR   +-->XOR           +-->XOR
|    |    |    |    |            |    |
V    |    V    |    V            |    V
+----+ | +----+  | +----+          | +----+
K-->|加密 | | |加密|  | |加密 |   ...    | |加密|
+----+ | +----+  | +----+          | +----+
|    |    |    |    |            |    |
+----+    +----+    +-->      ->-+    |
|         |         |         X_n     |
V         V         V                 V
X_1       X_2       X_3               X_n+1

2.3.  Encryption -- 生成密文

   To encrypt the message data we use Counter (CTR) mode.  We first
define the key stream blocks by:
使用 Counter (CTR) 模式加密,首先计算如下密钥流
S_i := E( K, A_i )   for i=0, 1, 2, ...

   The values A_i are formatted as follows, where the Counter field i is
encoded in most-significant-byte first order:

      Octet Number   Contents
------------   ---------
0              Flags
1 ... 15-L     Nonce N
16-L ... 15    Counter i

   The Flags field is formatted as follows:

      Bit Number   Contents
----------   ----------------------
7            Reserved (always zero)
6            Reserved (always zero)
5 ... 3      Zero
2 ... 0      L'

   Another way say the same thing is:  Flags = L'.

   A_i 构成如下
    长度   1      15-L           L
   +----+-----+-----------+------------+
   |字节 |  0  | 1 .. 15-L | 16-L .. 15 |
   +----+-----+-----------+------------+
   |内容 |Flags|  Nonce N  | Counter i  | -- Counter i 的值能够在 L 字节内表示
   +----+-----+-----------+------------+    (因为 i <= l(m))
       /      \                  ^
      /        \                 |
     /          \                |
    /            \               |
   / Flags 展开后  \              |
   +----+-+-----+-+-+-+-+-+-+    |L'(L) 决定
   |位   |7|Adata|5|4|3|2|1|0|    |Nonce 的长度
   +----+-+-----+-+-+-+-+-+-+    |
   |内容 |0|  0  |M'=0 | L'  | ---+
   +----+-+-----+-+-+-+-+-+-+
                 |
                 M' 不同于 B_0(B_0 中始终不为 0)

   The message is encrypted by XORing the octets of message m with the
first l(m) octets of the concatenation of S_1, S_2, S_3, ... .  Note
that S_0 is not used to encrypt the message.
明文与密钥流异或,得到密文,S_0 不用于加密,但参与数据校验
        A_0       A_1        A_2        A_n
         |         |          |          |
         V         V          V          V
       +----+   +----+     +----+     +----+
   K-->|加密 |   |加密|     | 加密| ... |加密|
       +----+   +----+     +----+     +----+
         |         |          |          |
         |         |S_1       |S_2       |S_n
         |         |          |          |       密钥: S_1 | S_2 | ... | S_n
         |         V          V          V       XOR
         |  M_1-->XOR  M_2-->XOR  M_n-->XOR      明文: M_1 | M_2 | ... | M_n
         |         |          |          |        |
         V         V          V          V        V
        S_0       C_1        C_2        C_n      密文: C_1 | C_2 | ... | C_n

   The authentication value U is computed by encrypting T with the key
stream block S_0 and truncating it to the desired length.
T 与 S_0 的异或结果取前 M 字节,得到认证字段
U := T XOR first-M-bytes( S_0 )

2.4.  Output -- 最终输出

       取前 l(m) 字节                        取前 M 字节
       =================================    ============
       S_1/E(K,A_1) | S_2/E(K,A_2) | ... || S_0/E(K,A_0)
   XOR m                                 || X_n+1
   -----------------------------------------------------
     = 最终输出 c

   其中 X_i 计算如下
X_1   := E( K, B_0 )
X_i+1 := E( K, X_i XOR B_i )  for i=1, ..., n

8.  Test Vectors -- 使用测试数据进行计算演示

   =============== Packet Vector #1 ==================
AES Key =  C0 C1 C2 C3  C4 C5 C6 C7  C8 C9 CA CB  CC CD CE CF
Nonce =    00 00 00 03  02 01 00 A0  A1 A2 A3 A4  A5
Total packet length = 31. [Input with 8 cleartext header octets]
扣除 8 字节明文头,只有 31-8=23 字节需要处理
00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
10 11 12 13  14 15 16 17  18 19 1A 1B  1C 1D 1E

   明文分组
   M_1 -- 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
   M_2 -- 18 19 1A 1B 1C 1D 1E

   以下计算数据认证字段
   CBC IV in: 59 00 00 00  03 02 01 00  A0 A1 A2 A3  A4 A5 00 17 -- 实际就是 B_0
              |  |                                       |     |
              |  |<--------------- Nonce --------------->|     |
              
|                                            23 字节
Flags = 0 1 0 1 1 0 0 1 (binary)
| | |---| |---|
| |   |     |
| |   |   L'=1 <--> L=2
| |  M'=3 <--> M=8
| Adata=1 表示有认证字段
Reserved (always zero)

   CBC IV out:EB 9D 55 47  73 09 55 AB  23 1E 0A 2D  FE 4B 90 D6
验证 X_1 := E( K, B_0 )
C:\>perl -e "binmode STDOUT; print pack('H*','5900000003020100A0A1A2A3A4A50017')" > B_0.txt
C:\>openssl enc -aes-128-ecb -K C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF -iv 0 -nopad -in B_0.txt > X_1.txt
C:\>od -An -tx1 -v X_1.txt

eb 9d 55 47 73 09 55 ab 23 1e 0a 2d fe 4b 90 d6

   After xor: EB 95 55 46  71 0A 51 AE  25 19 0A 2D  FE 4B 90 D6   [hdr]
验证 X_1 XOR B_1 -- xor.pl 源码见后面
C:\>perl xor.pl 00080001020304050607000000000000 EB9D5547730955AB231E0A2DFE4B90D6
          00080001020304050607000000000000 B_1 附加认证数据(8 字节)
          EB9D5547730955AB231E0A2DFE4B90D6 X_1
    --------------------------------------
    XOR = EB955546710A51AE25190A2DFE4B90D6

   After AES: CD B6 41 1E  3C DC 9B 4F  5D 92 58 B6  9E E7 F0 91
验证 X_2 := E( K, X_1 XOR B_1 )
C:\>perl -e "binmode STDOUT; print pack('H*','EB955546710A51AE25190A2DFE4B90D6')" > X_1_XOR_B_1.txt
C:\>openssl enc -aes-128-ecb -K C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF -iv 0 -nopad -in X_1_XOR_B_1.txt > X_2.txt
C:\>od -An -tx1 -v X_2.txt
cd b6 41 1e 3c dc 9b 4f 5d 92 58 b6 9e e7 f0 91

   After xor: C5 BF 4B 15  30 D1 95 40  4D 83 4A A5  8A F2 E6 86   [msg]
验证 X_2 XOR B_2
C:\>perl xor.pl 08090A0B0C0D0E0F1011121314151617 CDB6411E3CDC9B4F5D9258B69EE7F091
          08090A0B0C0D0E0F1011121314151617 B_2 -- 从 B_2 开始起为明文部分
          CDB6411E3CDC9B4F5D9258B69EE7F091 X_2
    --------------------------------------
    XOR = C5BF4B1530D195404D834AA58AF2E686

   After AES: 9C 38 40 5E  A0 3C 1B C9  04 B5 8B 40  C7 6C A2 EB
验证 X_3 := E( K, X_2 XOR B_2 )
C:\>perl -e "binmode STDOUT; print pack('H*','C5BF4B1530D195404D834AA58AF2E686')" > X_2_XOR_B_2.txt
C:\>openssl enc -aes-128-ecb -K C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF -iv 0 -nopad -in X_2_XOR_B_2.txt > X_3.txt
C:\>od -An -tx1 -v X_3.txt
9c 38 40 5e a0 3c 1b c9 04 b5 8b 40 c7 6c a2 eb

   After xor: 84 21 5A 45  BC 21 05 C9  04 B5 8B 40  C7 6C A2 EB   [msg]
验证 X_3 XOR B_3
C:\>perl xor.pl 18191A1B1C1D1E000000000000000000 9C38405EA03C1BC904B58B40C76CA2EB
          18191A1B1C1D1E000000000000000000 B_3 -- B_3 作为明文最后一个分组,以 0 字节补齐
          9C38405EA03C1BC904B58B40C76CA2EB X_3
    --------------------------------------
    XOR = 84215A45BC2105C904B58B40C76CA2EB

   After AES: 2D C6 97 E4  11 CA 83 A8  60 C2 C4 06  CC AA 54 2F
验证 X_4 := E( K, X_3 XOR B_3 )
C:\>perl -e "binmode STDOUT; print pack('H*','84215A45BC2105C904B58B40C76CA2EB')" > X_3_XOR_B_3.txt
C:\>openssl enc -aes-128-ecb -K C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF -iv 0 -nopad -in X_3_XOR_B_3.txt > X_4.txt
C:\>od -An -tx1 -v X_4.txt
2d c6 97 e4 11 ca 83 a8 60 c2 c4 06 cc aa 54 2f

   CBC-MAC  : 2D C6 97 E4  11 CA 83 A8 -- 取前 8 字节

   以下计算密钥流
   S_i := E( K, A_i )   for i=0, 1, 2, ...
   A_i 是 L、Nonce、i 的函数,格式如下
       01 00 00 00  03 02 01 00  A0 A1 A2 A3  A4 A5 00 00
       |  |                                       |     |
       |  |<--------------- Nonce --------------->|     |
       |                                            Counter(0000、0001、0002...)
       Flags = 0 0 0 0 0 0 0 1 (binary)
               | | |---| |---|
               | |   |     |
               | |   |   L'=1 <--> L=2
               | |  Zero
               | 相当于 Adata=0
           Reserved (always zero)

   CTR Start: 01 00 00 00  03 02 01 00  A0 A1 A2 A3  A4 A5 00 01 -- A_1
CTR[0001]: 50 85 9D 91  6D CB 6D DD  E0 77 C2 D1  D4 EC 9F 97 -- S_1
CTR[0002]: 75 46 71 7A  C6 DE 9A FF  64 0C 9C 06  DE 6D 0D 8F -- S_2
CTR[MAC ]: 3A 2E 46 C8  EC 33 A5 48                           -- S_0 取前 M 字节
C:\>od -An -tx1 -v A_.txt
    01 00 00 00 03 02 01 00 a0 a1 a2 a3 a4 a5 00 00 -- A_0
    01 00 00 00 03 02 01 00 a0 a1 a2 a3 a4 a5 00 01 -- A_1
    01 00 00 00 03 02 01 00 a0 a1 a2 a3 a4 a5 00 02 -- A_2
   C:\>openssl enc -aes-128-ecb -K C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF -iv 0 -nopad -in A_.txt > key.txt
   C:\>od -An -tx1 -v key.txt
    3a 2e 46 c8 ec 33 a5 48 56 20 54 2c 02 2c c0 7d -- S_0
    50 85 9d 91 6d cb 6d dd e0 77 c2 d1 d4 ec 9f 97 -- S_1
    75 46 71 7a c6 de 9a ff 64 0c 9c 06 de 6d 0d 8f -- S_2

   Total packet length = 39. [Authenticated and Encrypted Output]
00 01 02 03  04 05 06 07  58 8C 97 9A  61 C6 63 D2
F0 66 D0 C2  C0 F9 89 80  6D 5F 6B 61  DA C3 84 17
E8 D1 2C FD  F9 26 E0
注意
m                                             T
----------------------------------------------================
08090A0B0C0D0E0F101112131415161718191A1B1C1D1E2DC697E411CA83A8

S_1                             S_2           S_0
--------------------------------==============----------------

50859d916dcb6ddde077c2d1d4ec9f977546717ac6de9a3a2e46c8ec33a548

C:\>perl xor.pl 08090A0B0C0D0E0F101112131415161718191A1B1C1D1E2DC697E411CA83A8 50859d916dcb6ddde077c2d1d4ec9f977546717ac6de9a3a2e46c8ec33a548
          08090A0B0C0D0E0F101112131415161718191A1B1C1D1E2DC697E411CA83A8
          50859d916dcb6ddde077c2d1d4ec9f977546717ac6de9a3a2e46c8ec33a548
    --------------------------------------------------------------------
    XOR = 588C979A61C663D2F066D0C2C0F989806D5F6B61DAC38417E8D12CFDF926E0 正确

在 CCMP 中,对称密钥 K 同时对明文数据进行加密和认证,C(Confidentiality) 和 I(Integrality) 都得到了保证
而 S(Signature) 和 A(Authentication) 是否达标,则取决于对称密钥 K 的安全性
从 IEEE 802.11i 中我们知道,K 是由著名的 EAPOL-Key 四次握手衍生得到,其安全性又取决于 PMK
PMK 又来自哪里?

IEEE 802.11i 标准中有两种工作模式:PSK 和 802.1X。
在 PSK 模式中,AP 和所有 STA 预先共享同一个密钥,该共享密钥经过简单的变换得到 PMK(后面将给出公式)
原则上 AP 无法区别不同的 STA -- 排除其他方式比如 MAC 地址过滤 -- 所以做不到 A(Authentication)
因为 AP 只知道有一个掌握了预共享密钥的家伙连上我了
至于这个家伙是谁?他的预共享密钥是不是偷来的?AP 一概不知
PSK 模式下 STA 反过来也无法认证 AP,这有点类似 GSM 网络中的伪基站

在 802.1X 模式中,安全性得到了增强,认证协议为 EAP,包含的认证子协议有 EAP-TLS/EAP-TTLS/EAP-PEAP 等
上述三种子协议都采用 TLS 隧道加密,天然支持 STA 对 AP 的认证
如果是 EAP-TLS 协议,还需要部署 STA 证书,因而可以做到相互认证,在这种情况下 SCIA,安全特性一个也不少

最后附上 xor.pl 源代码

引用 http://www.cnblogs.com/efzju/p/3199330.html

安全协议系列(一)----WEP详解

WEP加密报文如下,其加密密钥为ASCII字符串:12345
08204330-93d17f4cccae4d89b9fe7a04e3dd42d7
将报文以十六进制显示,红色表示加密部分
0010  00 11 22 33 44 55 10 00  00 00 3C FC BF 00 9A 6E
0020  50 1D C4 2D 3D 6B B1 55  FD DB D9 2F 9F EB 81 5F
0030  A0 53 E2 DD CD E5 25 83  E9 87 98 D1 70 2E 55 8A
0040  9D A9 21 35 FF 09 E8 03  0E 77 DD F9 8D 5C 0A 78
0050  E8 C6 08 76 99 BD 6F BF  75 48 4F BD 5D 76 C5 F9
0060  3D A5 5D BA EE DD
具体加密过程见下图 -- 引用自 Wikipedia(加上评注)
08205429-0498f4ba7c564d12a015dda95f344a2e

上图说明,将报文中的 Initialization Vector 字段和 WEP 密钥(连接后)作为 RC4 算法的密钥种子,生成密钥码流,再逐个与明文异或,就得到密文
现在已知报文密钥,剩下就是利用工具对其解密得到明文—这里我们继续利用 OpenSSL

OpenSSL 的 enc 命令支持 rc4 算法,其 -K 选项后跟 RC4 密钥种子,对应上图中的 seed
不过在使用前,需要改动一点代码,因为 enc 命令强制使用固定长度的 seed(实际 RC4 允许变长的 seed),具体为
rc4                128 bit
rc4-40             40 bit

如果 -K 选项指定的 seed 长度不足,则会用零补齐,凑够固定长度,如下

如果 seed 超出固定长度,则截短为固定长度

以上使用 -P 选项打印实际的 key(其实是 seed)

这里 RC4 密钥种子为 Initialization Vector||WEP Key = 0x3cfcbf3132333435,为 64 位,会被补零,造成解密错误

怎么改呢?只要修改文件 crypto\evp\e_rc4.c,如下,将 EVP_CIPHER_CTX_key_length(ctx) 改为 strlen(key)

需要指出,这只是临时的 Workaround,它会影响 -k(小写) 选项:OpenSSL 内部会先调用 EVP_BytesToKey 函数进行 Key Derivation
随后在 rc4_init_key 函数中,RC4_set_key 的入参会发生变化。感兴趣可以调试跟踪一下
顺带说下,EVP_BytesToKey 不兼容标准的 PBKDF2(参见 RFC2898)

运行修改版本的 OpenSSL

wep_cipher.txt 文件内容如下
00000000h: 9A 6E 50 1D C4 2D 3D 6B B1 55 FD DB D9 2F 9F EB
00000010h: 81 5F A0 53 E2 DD CD E5 25 83 E9 87 98 D1 70 2E
00000020h: 55 8A 9D A9 21 35 FF 09 E8 03 0E 77 DD F9 8D 5C
00000030h: 0A 78 E8 C6 08 76 99 BD 6F BF 75 48 4F BD 5D 76
00000040h: C5 F9 3D A5 5D BA EE DD

wep_plain.txt 文件内容如下
00000000h: AA AA 03 00 00 00 08 00 45 00 00 3C 7A 8C 00 00
00000010h: 80 01 3C CC C0 A8 01 16 C0 A8 01 02 00 00 86 56
00000020h: 02 00 CD 05 61 62 63 64 65 66 67 68 69 6A 6B 6C
00000030h: 6D 6E 6F 70 71 72 73 74 75 76 77 61 62 63 64 65
00000040h: 66 67 68 69 42 74 BA 61

究竟明文是什么报文呢?我们可以使用 wireshark(本例为版本 1.8.6)查看,前提是添加解密密钥,如下
菜单【Edit】-->【Preferences】,选 IEEE 802.11 --> Edit
08210552-bf8b02256d414fb5a452f741fd0167d6

下图为 wiresharek 显示的明文
08210740-78afe85832fb4a2585291d3de6ca8a78

原来是 ICMP ping 报文

有两个地方需要注意
1、wireshark 显示明文长度为 68 字节,少了 wep_plain.txt 后面的 4 个字节(见上面蓝色4字节),原因是 WEP 使用 CRC32 来校验明文的完整性
实际上 CRC 结果是明文的一部分,只是没有显示在解密窗口中
可以利用 perl 自带的 crc32.bat 脚本(位于 perl\bin 目录)进行验证,命令结果为 61ba7442(字节序恰好与 42 74 BA 61 相反)
2、在IP层下方还有一层 Logical-Link Control,与常见的以太报文相比,这是 WiFi 报文的特殊之处

另外,较新版本(>=1.8.6)的 wiresharek 提供了工程文件 wireshark.vcproj,这样就可以直接在 VC 中进行编译、调试

最后考虑一下 WEP 的安全性,这里用 4 个字母缩写表示主要考虑的安全指标:SCIA,后续对安全协议将使用这些指标进行衡量,解释如下
Signature —— 签名(即对方不能否认发出的消息)
Confidentiality —— 机密(数据被加密)
Integrality —— 完整(加密数据解密后,可以知道是否受到有意无意的损坏)
Authentication —— 认证(能够识别对方的真实身份)
其他还有一些安全指标,比如授权、可用/可靠性、行为审计等,不再考虑,本文聚焦在密码学意义上的安全指标

WEP 提供了数据的机密和完整性保证,由于是对称算法,原则上无法识别对方身份(一个 AP 通常由多个无线终端共享一个 WEP 密钥接入,无法区分谁是谁),不可否认也谈不上。(事实上 WEP 是有认证之说的,分为 Open System 和 Shared Key 两种,但都不符合前面提到的强认证,即识别对方的真实身份)
我们要记住的是,WEP 已经不安全了(现在已经有诸多针对它的攻击工具,参见http://www.backtrack-linux.org/),尽量不要使用,
应该使用更安全的 wpa/wpa2/wpa-psk/wpa2-psk 方式

为什么不安全,由于涉及广泛,一篇文章无法覆盖完全,本文不再说明。

引用 http://www.cnblogs.com/efzju/archive/2013/06/12/3018661.html

mac上通过brew安装opencv

在Mac OSX上如果想使用OpenCV,可以通过自己手动编译源码的方式,但比较繁琐。

推荐使用Homebrew来进行安装,步骤很简单,如下:

等待几分钟,即可安装成功。

Android通过tcpdump抓包

1. 手机要有root权限

2. 下载tcpdump

http://www.strazzere.com/android/tcpdump

3.上传tcpdump到手机

如果提示

则如下操作后重试

4.给予tcpdump 执行权限

5.连接到手机的控制端,获得root权限

6.切换到tcpdump 的所在目录

7.抓包

tcpdump 命令参数:

# "-i any": listen on any network interface
# "-p": disable promiscuous mode (doesn't work anyway)
# "-s 0": capture the entire packet
# "-w": write packets to a file (rather than printing to stdout)
... do whatever you want to capture, then ^C to stop it ...

8.从手机端下载文件到电脑

9.在电脑上用wireshark打开capture.pcap即可分析log.

如果需要执行包过滤,只抓取得某些类型的报文,可以参考下面的介绍。

Execute the following if you would like to watch packets go by rather than capturing them to a file (-n skips DNS lookups. -s 0 captures the entire packet rather than just the header):

Typical tcpdump options apply. For example, if you want to see HTTP traffic:

根据以上的信息,写一个bat去执行(tcpdump文件必须在当前目录里)。

开始tcpdump

下载tcpdump文件到电脑

问题:有些机器root后通过adb shell 后,默认不是root用户,需要输入 su才能切换到root,这样在执行批处理会有问题,解决方法如下

因没有root权限导致的问题

参考链接


Android通过tcpdump抓包

WD MyCloud 4.0 deb 安装源

请注意,以下的服务仅仅针对WDMyCloud Gen1,也就是比较早期的型号,最新的Gen2已经把系统从Debian Wheezy切换到了Busybox,因此下面的源已经不适用了。

WDMyCloud Gen1与WDMyCloud Gen2的区别如下:

Gen1: Mindspeed Comcerto C2000 (2 core, 650MHz) 256 MB Ram Debian wheezy
Gen2: Marvell armada 370 (2core, 800MHz) 512MB Ram Busybox


最近由于 WD MyCloud 的固件升级到4.0 之后,新的程序是以 64K 内存对齐的方式运作的,这就导致使用 apt-get 安装的所有安装包都是不能正常运行的,安装后,执行的时候会直接提示 “Killed”,因此需要全新编译代码才能成功安装。有动手能力的,可以参考 How to successfully build packages for WD My Cloud from source 来自己编译。不过非常的折腾。

今天刚刚更新了一下 WD MyCloud 的固件到V04.01.03-421版本,发现他的apt的源列表更新了一下,变成了如下

试了一下,竟然可以安装,并且部分软件运行正常,比如 VIM,Git-Core,Subversion.但是对于 aria2,expect 等软件,建议还是用我提供的源安装,原因在于有些软件需要升级libc6,stdlibc++6等这几个库,而这几个库如果更新,基本上,系统就启动不了了!

对于想省事的人来说,可以设置我的服务器为deb 的更新服务器,里面的是我编译好的版本。

最近调整了更新服务器地址,同时,又增加了Jseeie 版本的编译,这样的话,会有最新的版本的软件,但是,使用的时候要慎重,新版本软件可能没有经过长时间的严格测试,不排除有BUG的可能,如果下载的某些包有问题,麻烦尽快邮件反馈

安装新版本的话,需要手工卸载旧版本,apt-get remove 一下即可。

安装不上软件,提示缺少依赖的,暂时注释掉 jessie 部分的源,原因在于新版本正在编译中,耗时较长,只能是编译完成就上传导致了某些模块缺失。

如下操作即可。

1.打开 WD MyCloud 的SSH 登陆功能。

2.在SHELL 里面执行如下命令

修改里面的内容如下

目前这个安装源中支持的软件可以在下面的软件列表中找到 ,后续我会根据需要编译其他的软件,并且上传的。如果有什么软件是需要的,可以邮件联系我

注意:本源目前支持HTTPS方式访问,(目前貌似HTTP会有被劫持的倾向,建议使用HTTPS方式访问(切换到HTTPS之前需要先安装apt-transport-https),切换到HTTPS之后出现问题,可以参考
"method driver /usr/lib/apt/methods/https could not be found" update error来解决):

3.执行更新

4.安装软件(以VIM 为例子)

5.目前已经编译完成的软件列表如下

wheezy

jessie

目前根据反馈,有人在使用本源的时候,存在如下的情况

base_download_att

也就是在安装任何应用的时候都提示:

这种情况发生的原因,目前初步定位为使用WDMyCloud自带的源执行过

不管成功失败,还是中途中断,可能会导致"/lib/arm-linux-gnueabihf"中的libc库被升级,从而出现下图所示的情况(左边是正常的WDMyCloud系统,右图是出现问题的WDMyCloud):

20160212140006

这个问题的目前有效的解决方法是,使用降级系统版本的方式重新刷机来还原系统:

downgrade_version

Ubuntu 12.04 Apache2 增加虚拟目录

Apache2 增加虚拟目录需要如下操作.

我们以建立一个 /deb 目录, 也就是可以通过 http://www.mobibrw.com/deb/来访问的目录为例子。

1.停止 Apache2 的服务,如果修改文件之前不停止服务,则服务重启的时候,有可能会写回以前的配置,导致我们的配置无效。

2.修改配置文件

在里面增加如下内容

如果允许用户可以通过网页来遍历目录下面的所有文件,则需要设置 Options ,把 Options None 修改为 Options Indexes

3.启动服务

建立自己的apt-get源

1.安装 dpkg-scanpackages

2.安装apache2

默认的网站内容是在/var/www目录下的,我们建立一个deb文件夹用来存放自己的deb包:

使用dpkg-scanpackages 来生成Packages.gz(存放所有包的信息,以便用户获取):

dpkg-scanpackages 第一个参数用来指定要扫描的目录(当前所在目录的相对路径),通过’|'管道使用gzip(-9c 对应最高质量的压缩)输出到Packages.gz包中。

3.在其他机子上添加源

添加一行:

由于当多个软件源都存在同一个包的时候,apt-get 只会从第一个软件源中下载,因此,如果自建的软件源中有跟其他软件源中冲突的包,则需要把我们自建的软件源增加到sources.list 的最前面。

执行:

编译vim,提示找不到tgetent()

在树莓派上面编译VIM 的时候,提示找不到 tgetent()

就总是提示错误:

解决方法

安装ncurses-dev

Raspberry Pi(树莓派)国内软件源

树莓派自带的软件源是

由于网站在国外,导致下载速度非常慢,因此需要修改为国内镜像站点即可。

Raspberry Pi(树莓派)国内软件源:

修改配置文件

推荐使用如下命令直接替换成国内源(中科大的服务器):