class.md 11.4 KB
Newer Older
F
feilong 已提交
1 2 3 4
# Alice、Bob 和他们的朋友们

密码学家 Rivest、Shamir、Adleman 于1977年4月撰写了一篇论文《数字签名与公钥密码学》(On Digital Signatures and Public-Key Cryptosystems),并投稿至了一个期刊上,不过很遗憾这篇论文被拒稿了。随后他们修改了论文,并将论文重新命名为《一种实现数字签名和公钥密码系统的方法》(A Method of Obtaining Digital Signatures and Public-Key Cryptosystems),最终于1978年2月成功发表于顶级期刊《ACM通信》(Communications of the ACM)。在这篇论文中,三位密码学家嫌弃使用A、B两个字母代表角色太无聊,就用Alice和Bob来代替A和B。

F
fix bug  
feilong 已提交
5
在随后的几十年里密码学界又新增了很多著名人物。布鲁斯·施奈尔所著的《应用密码学》(Applied Cryptography)里详细列举了这些人物,下面是一些例子:
F
feilong 已提交
6 7 8 9 10 11 12

```python
crypto_roles = [
    '爱丽丝(Alice)是信息发送者。',
    '与鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。',
    '卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。',
    '戴夫(Dave)是通信中的第四位参加者。',
F
fix bug  
feilong 已提交
13
    '伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,伊夫也可以指环境(environment)。'
F
feilong 已提交
14 15 16 17 18 19 20 21
]
```

Python 是一门多范式编程语言,其中包括面向对象编程。

首先,我们用 `Python 类(class)` 定义一个密码城邦人物类型:

```python
F
feilong 已提交
22
# -*- coding: UTF-8 -*-
F
feilong 已提交
23 24 25 26 27 28 29 30 31 32 33
class CryptographyPeople:
    def __init__(self, name_cn, name_en, role, desc):
        self.name_cn = name_cn
        self.name_en = name_en
        self.role = role
        self.desc = desc
```

其次,我们添加一个简易的密码城邦人物解析器,它的作用是将类似`'马提尔达(Matilda)是一位商人(merchant),用于电子商务。',`这样的`人物剧本`解析成`CryptographyPeople`,创建一个密码城邦人物:

```python
F
feilong 已提交
34
# -*- coding: UTF-8 -*-
F
feilong 已提交
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
class SimpleCryptographyPeopleParser:
    def __init__(self, text) -> None:
        self.text = text

    def parse(self, desc):
        # 解析名字部分
        name_cn, name_en, rest = self.parse_name(desc)

        # 解析角色部分
        role, rest = self.parse_role(rest)

        # 解析描述不符
        desc = self.parse_desc(rest)

        # 创建密码城邦人物
        people = CryptographyPeople(name_cn, name_en, role, desc)

        return people

    def parse_name(self, text):
        # 解析名字部分
        index = text.find('是')
        name, rest = text[0:index], text[index+1:]

        # 解析中英文名字
        start = name.find('(')
        end = name.find(')')
        name_cn = name[0:start]
        name_en = name[start+1:end]

        return name_cn.strip(), name_en.strip(), rest

    def parse_role(self, text):
        index1 = text.find('。')
        index2 = text.find(',')

        index = 0
        if index1 > 0 and index2 > 0:
            index = min(index1, index2)
        else:
            index = max(index1, index2)

        role, rest = text[0:index], text[index+1:len(text)-1]

        # 去除冗余量词
        counts = ['一名', '一位', '一个']
        for count in counts:
            role = role.replace(count, '')
        return role.strip(), rest.strip()

    def parse_desc(self, name_cn, name_en, role, rest):
        desc = rest
        if desc:
            # 识别自我主语
            self_list = [name_cn, '他', '她']
            for self_item in self_list:
                desc = desc.replace(self_item, '我')
        else:
            # 补充默认描述
            desc = '很高兴认识你'
```

最后,我们希望创建一个密码城邦,它包含 `add``introduce` 两个方法:

```python
F
feilong 已提交
100
# -*- coding: UTF-8 -*-
F
feilong 已提交
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
class CryptographyCity:
    def __init__(self):
        self.peoples = []

    def add(self, text):
        parser = SimpleCryptographyPeopleParser(text)
        people = parser.parse(text)
        self.peoples.append(people)

    # TODO(YOU): 请在此实现 introduce 方法
```

最终,我们可以构建起密码城邦,并让市民们全部自报家门:

```python
F
feilong 已提交
116
# -*- coding: UTF-8 -*-
F
feilong 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129 130
if __name__ == '__main__':
    crypto_roles = ...

    city = CryptographyCity()
    for crypto_role in crypto_roles:
        city.add(crypto_role)
    city.introduce()
```

密码城邦人物的自我介绍如下:

```bash
爱丽丝(Alice): 密码学家说我是一位信息发送者,很高兴认识你。
鲍伯(Bob): 密码学家说我是一位信息接受者,通例上,爱丽丝希望把一条消息发送给我。
F
fix bug  
feilong 已提交
131
...
F
feilong 已提交
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
```

请找出以下对类`CryptographyCity`的方法`introduce`的实现中,<span style="color:red">不正确</span>的选项。

## template

```python
class CryptographyPeople:
    def __init__(self, name_cn, name_en, role, desc):
        self.name_cn = name_cn
        self.name_en = name_en
        self.role = role
        self.desc = desc


class SimpleCryptographyPeopleParser:
    def __init__(self, text) -> None:
        self.text = text

    def parse(self, desc):
        # 解析名字部分
        name_cn, name_en, rest = self.parse_name(desc)

        # 解析角色部分
        role, rest = self.parse_role(name_cn, name_en, rest)

        # 解析描述不符
        desc = self.parse_desc(name_cn, name_en, role, rest)

        # 创建密码城邦人物
        people = CryptographyPeople(name_cn, name_en, role, desc)

        return people

    def parse_name(self, text):
        # 解析名字部分
        index = text.find('是')
        name, rest = text[0:index], text[index+1:]

        # 解析中英文名字
        start = name.find('(')
        end = name.find(')')
        name_cn = name[0:start]
        name_en = name[start+1:end]

        return name_cn.strip(), name_en.strip(), rest

    def parse_role(self, name_cn, name_en, text):
        index1 = text.find('。')
        index2 = text.find(',')

        index = 0
        if index1 > 0 and index2 > 0:
            index = min(index1, index2)
        else:
            index = max(index1, index2)

        role, rest = text[0:index], text[index+1:len(text)-1]

        # 去除冗余量词
        counts = ['一名', '一位', '一个']
        for count in counts:
            role = role.replace(count, '')
        return role.strip(), rest.strip()

    def parse_desc(self, name_cn, name_en, role, rest):
        desc = rest
        if desc:
            # 识别自我主语
            self_list = [name_cn, '他', '她']
            for self_item in self_list:
                desc = desc.replace(self_item, '我')
        else:
            # 补充默认描述
            desc = '很高兴认识你'
        return desc


class CryptographyCity:
    def __init__(self):
        self.peoples = []

    def add(self, text):
        parser = SimpleCryptographyPeopleParser(text)
        people = parser.parse(text)
        self.peoples.append(people)

    def introduce(self):
        for people in self.peoples:
            info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role}{people.desc}。'
            print(info)


if __name__ == '__main__':
    crypto_roles = [
        '爱丽丝(Alice)是信息发送者。',
        '鲍伯(Bob)是信息接受者。通例上,爱丽丝希望把一条消息发送给鲍伯。',
        '卡罗尔或查利(Carol或Charlie)是通信中的第三位参加者。',
        '戴夫(Dave)是通信中的第四位参加者。',
        '伊夫(Eve)是一位偷听者(eavesdropper),但行为通常是被动的。她拥有偷听的技术,但不会中途篡改发送的消息。在量子密码学中,伊夫也可以指环境(environment)。',
        '艾萨克(Isaac)是互联网服务提供者 (ISP)。',
        '伊凡(Ivan)是发行人,使用于商业密码学中。',
        '贾斯汀(Justin)是司法(justice)机关。',
        '马洛里(Mallory)是一位恶意攻击者(malicious attacker)。与伊夫不同的是,马洛里会篡改发送的消息。对付马洛里所需的信息安全技术比对伊夫的高出很多。有时亦会叫作马文(Marvin)或马利特(Mallet)。',
        '马提尔达(Matilda)是一位商人(merchant),用于电子商务。',
        '奥斯卡(Oscar)是敌人,通常与马洛里一样。',
        '帕特(Pat)或佩吉(Peggy)是证明者(prover),维克托(Victor)是验证者(verifier)。两人会证实一项事件是否有实际进行,多使用于零知识证明。',
        '普特(Plod或Officer Plod)是执法官员。名称来自伊妮·布来敦所著的儿童文学《诺弟》(Noddy)中的角色“普特先生”。',
        '史蒂夫(Steve)是隐写术(Steganography)。',
        '特伦特(Trent)是一位可信赖的仲裁人(trusted arbitrator),中立的第三者,根据存在的协议而判断。',
        '特鲁迪(Trudy)是侵入者(intruder),等同马洛里。',
        '沃特(Walter)是看守人(warden),根据已存在的协议而保护爱丽丝和鲍伯。',
        '佐伊(Zoe)通常是一个安全协议中的最后参与者。'
    ]

    city = CryptographyCity()
    for crypto_role in crypto_roles:
        city.add(crypto_role)
    city.introduce()
```

## 答案

```python
class CryptographyCity:
    def __init__(self):
        self.peoples = []

    def add(self, text):
        parser = SimpleCryptographyPeopleParser(text)
        people = parser.parse(text)
        self.peoples.append(people)

    def introduce():
        for people in peoples:
            say(people)

    def say(people):
        info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role}{people.desc}。'
        print(info)
```

## 选项

### for 语句实现

```python
class CryptographyCity:
    def __init__(self):
        self.peoples = []

    def add(self, text):
        parser = SimpleCryptographyPeopleParser(text)
        people = parser.parse(text)
        self.peoples.append(people)

    def introduce(self):
        for people in self.peoples:
            self.say(people)

    def say(self, people):
        info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role}{people.desc}。'
        print(info)
```

### while语句实现

```python
class CryptographyCity:
    def __init__(self):
        self.peoples = []

    def add(self, text):
        parser = SimpleCryptographyPeopleParser(text)
        people = parser.parse(text)
        self.peoples.append(people)

    def introduce(self):
        i=0
        while i<len(self.peoples):
            people = self.peoples[i]
            self.say(people)
            i+=1

    def say(self, people):
        info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role}{people.desc}。'
        print(info)
```

### 列表表达式

```python
class CryptographyCity:
    def __init__(self):
        self.peoples = []

    def add(self, text):
        parser = SimpleCryptographyPeopleParser(text)
        people = parser.parse(text)
        self.peoples.append(people)

    def introduce(self):
        [self.say(people) for people in self.peoples]

    def say(self, people):
        info = f'{people.name_cn}({people.name_en}): 密码学家说我是一位{people.role}{people.desc}。'
        print(info)
```