Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

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

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

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

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

r""" 

Cryptosystems 

 

This module contains base classes for various cryptosystems, including 

symmetric key and public-key cryptosystems. The classes defined in this 

module should not be called directly. It is the responsibility of child 

classes to implement specific cryptosystems. Take for example the 

Hill or matrix cryptosystem as implemented in 

:class:`HillCryptosystem <sage.crypto.classical.HillCryptosystem>`. It is a 

symmetric key cipher so 

:class:`HillCryptosystem <sage.crypto.classical.HillCryptosystem>` is a child 

class of 

:class:`SymmetricKeyCryptosystem <sage.crypto.cryptosystem.SymmetricKeyCryptosystem>`, 

which in turn is a child class of 

:class:`Cryptosystem <sage.crypto.cryptosystem.Cryptosystem>`. The following 

diagram shows the inheritance relationship of particular cryptosystems:: 

 

Cryptosystem 

+ SymmetricKeyCryptosystem 

| + HillCryptosystem 

| + LFSRCryptosystem 

| + ShiftCryptosystem 

| + ShrinkingGeneratorCryptosystem 

| + SubstitutionCryptosystem 

| + TranspositionCryptosystem 

| + VigenereCryptosystem 

+ PublicKeyCryptosystem 

""" 

 

#***************************************************************************** 

# Copyright (C) 2007 David Kohel <kohel@maths.usyd.edu.au> 

# 

# Distributed under the terms of the GNU General Public License (GPL) 

# 

# http://www.gnu.org/licenses/ 

#***************************************************************************** 

 

import sage.structure.parent_old as parent_old 

from sage.sets.set import Set_generic 

 

class Cryptosystem(parent_old.Parent, Set_generic): 

r""" 

A base cryptosystem class. This is meant to be extended by other 

specialized child classes that implement specific cryptosystems. 

A cryptosystem is a pair of maps 

 

.. MATH:: 

 

E : {\mathcal K} \rightarrow {\rm Hom}({\mathcal M},{\mathcal C}) 

 

.. MATH:: 

 

D : {\mathcal K} \rightarrow {\rm Hom}({\mathcal C},{\mathcal M}) 

 

where `{\mathcal K}` is the key space, 

`{\mathcal M}` is the plaintext or message space, and 

`{\mathcal C}` is the ciphertext space. In many instances 

`{\mathcal M} = {\mathcal C}` and the images will lie in 

`{\rm Aut}({\mathcal M})`. An element of the image of 

`E` is called a cipher. 

 

We may assume that `E` and `D` are injective, hence 

identify a key `K` in `{\mathcal K}` with its image 

`E_K := E(K)` in 

`\mathrm{Hom}({\mathcal M},{\mathcal C})`. 

 

The cryptosystem has the property that for every encryption key 

`K_1` there is a decryption key `K_2` such that 

`D_{K_2} \circ E_{K_1}`. A cryptosystem with the 

property that `K := K_2 = K_1`, is called a symmetric 

cryptosystem. Otherwise, if the key `K_2 \ne K_1`, nor is 

`K_2` easily derived from `K_1`, we call the 

cryptosystem asymmetric or public key. In that case, `K_1` 

is called the public key and `K_2` is called the private 

key. 

 

INPUT: 

 

- ``plaintext_space`` -- the plaintext alphabet. 

 

- ``ciphertext_space`` -- the ciphertext alphabet. 

 

- ``key_space`` -- the key alphabet. 

 

- ``block_length`` -- (default: 1) the block length. 

 

- ``period`` -- (default: ``None``) the period. 

 

EXAMPLES: 

 

Various classical cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()) 

Shift cryptosystem on Free alphabetic string monoid on A-Z 

sage: SubstitutionCryptosystem(HexadecimalStrings()) 

Substitution cryptosystem on Free hexadecimal string monoid 

sage: HillCryptosystem(BinaryStrings(), 3) 

Hill cryptosystem on Free binary string monoid of block length 3 

sage: TranspositionCryptosystem(OctalStrings(), 5) 

Transposition cryptosystem on Free octal string monoid of block length 5 

sage: VigenereCryptosystem(Radix64Strings(), 7) 

Vigenere cryptosystem on Free radix 64 string monoid of period 7 

""" 

def __init__(self, plaintext_space, ciphertext_space, key_space, 

block_length=1, period=None): 

r""" 

Create a ``Cryptosystem`` object. See the class ``Cryptosystem`` 

for detailed documentation. 

 

INPUT: 

 

- ``plaintext_space`` -- the plaintext alphabet. 

 

- ``ciphertext_space`` -- the ciphertext alphabet. 

 

- ``key_space`` -- the key alphabet. 

 

- ``block_length`` -- (default: 1) the block length. 

 

- ``period`` -- (default: ``None``) the period. 

 

EXAMPLES: 

 

Various classical cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()) 

Shift cryptosystem on Free alphabetic string monoid on A-Z 

sage: SubstitutionCryptosystem(HexadecimalStrings()) 

Substitution cryptosystem on Free hexadecimal string monoid 

sage: HillCryptosystem(BinaryStrings(), 3) 

Hill cryptosystem on Free binary string monoid of block length 3 

sage: TranspositionCryptosystem(OctalStrings(), 5) 

Transposition cryptosystem on Free octal string monoid of block length 5 

sage: VigenereCryptosystem(Radix64Strings(), 7) 

Vigenere cryptosystem on Free radix 64 string monoid of period 7 

""" 

self._cipher_domain = plaintext_space 

self._cipher_codomain = ciphertext_space 

self._key_space = key_space 

self._block_length = block_length 

self._period = period 

 

def __eq__(self, right): 

r""" 

Comparing ``self`` with ``right``. Two ``Cryptosystem`` objects 

are the same if they satisfy all of these conditions: 

 

- share the same type 

- have the same cipher domain 

- have the same cipher codomain 

- share the same key space 

- share the same block length 

- have the same period 

 

INPUT: 

 

- ``right`` -- a ``Cryptosystem`` object. 

 

EXAMPLES: 

 

Pairs of equivalent classical cryptosystems:: 

 

sage: sub1 = SubstitutionCryptosystem(AlphabeticStrings()) 

sage: sub2 = SubstitutionCryptosystem(AlphabeticStrings()) 

sage: sub1 == sub2 

True 

sage: shift1 = ShiftCryptosystem(HexadecimalStrings()) 

sage: shift2 = ShiftCryptosystem(HexadecimalStrings()) 

sage: shift1 == shift2 

True 

sage: hill1 = HillCryptosystem(AlphabeticStrings(), 4) 

sage: hill2 = HillCryptosystem(AlphabeticStrings(), 4) 

sage: hill1 == hill2 

True 

sage: tran1 = TranspositionCryptosystem(HexadecimalStrings(), 5) 

sage: tran2 = TranspositionCryptosystem(HexadecimalStrings(), 5) 

sage: tran1 == tran2 

True 

sage: vig1 = VigenereCryptosystem(AlphabeticStrings(), 7) 

sage: vig2 = VigenereCryptosystem(AlphabeticStrings(), 7) 

sage: vig1 == vig2 

True 

 

Pairs of different classical cryptosystems:: 

 

sage: sub1 = SubstitutionCryptosystem(AlphabeticStrings()) 

sage: sub2 = SubstitutionCryptosystem(OctalStrings()) 

sage: sub1 == sub2 

False 

sage: shift1 = ShiftCryptosystem(HexadecimalStrings()) 

sage: shift2 = ShiftCryptosystem(BinaryStrings()) 

sage: shift1 == shift2 

False 

sage: hill1 = HillCryptosystem(Radix64Strings(), 4) 

sage: hill2 = HillCryptosystem(Radix64Strings(), 5) 

sage: hill1 == hill2 

False 

sage: tran1 = TranspositionCryptosystem(Radix64Strings(), 3) 

sage: tran2 = TranspositionCryptosystem(HexadecimalStrings(), 3) 

sage: tran1 == tran2 

False 

sage: vig1 = VigenereCryptosystem(AlphabeticStrings(), 7) 

sage: vig2 = VigenereCryptosystem(Radix64Strings(), 7) 

sage: vig1 == vig2 

False 

""" 

return (type(self) is type(right) and 

self._cipher_domain == right._cipher_domain and 

self._cipher_codomain == right._cipher_codomain and 

self._key_space == right._key_space and 

self._block_length == right._block_length and 

self._period == right._period) 

 

def plaintext_space(self): 

r""" 

Return the plaintext alphabet of this cryptosystem. 

 

EXAMPLES: 

 

The plaintext spaces of various classical cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()).plaintext_space() 

Free alphabetic string monoid on A-Z 

sage: SubstitutionCryptosystem(HexadecimalStrings()).plaintext_space() 

Free hexadecimal string monoid 

sage: HillCryptosystem(BinaryStrings(), 3).plaintext_space() 

Free binary string monoid 

sage: TranspositionCryptosystem(OctalStrings(), 5).plaintext_space() 

Free octal string monoid 

sage: VigenereCryptosystem(Radix64Strings(), 7).plaintext_space() 

Free radix 64 string monoid 

""" 

return self._cipher_domain 

 

def cipher_domain(self): 

r""" 

Return the alphabet used by this cryptosystem for encoding plaintexts. 

This is the same as the plaintext space. 

 

EXAMPLES: 

 

The cipher domains, or plaintext spaces, of various classical 

cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()).cipher_domain() 

Free alphabetic string monoid on A-Z 

sage: SubstitutionCryptosystem(HexadecimalStrings()).cipher_domain() 

Free hexadecimal string monoid 

sage: HillCryptosystem(BinaryStrings(), 3).cipher_domain() 

Free binary string monoid 

sage: TranspositionCryptosystem(OctalStrings(), 5).cipher_domain() 

Free octal string monoid 

sage: VigenereCryptosystem(Radix64Strings(), 7).cipher_domain() 

Free radix 64 string monoid 

""" 

return self._cipher_domain 

 

def ciphertext_space(self): 

r""" 

Return the ciphertext alphabet of this cryptosystem. 

 

EXAMPLES: 

 

The ciphertext spaces of various classical cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()).ciphertext_space() 

Free alphabetic string monoid on A-Z 

sage: SubstitutionCryptosystem(HexadecimalStrings()).ciphertext_space() 

Free hexadecimal string monoid 

sage: HillCryptosystem(BinaryStrings(), 3).ciphertext_space() 

Free binary string monoid 

sage: TranspositionCryptosystem(OctalStrings(), 5).ciphertext_space() 

Free octal string monoid 

sage: VigenereCryptosystem(Radix64Strings(), 7).ciphertext_space() 

Free radix 64 string monoid 

""" 

return self._cipher_codomain 

 

def cipher_codomain(self): 

r""" 

Return the alphabet used by this cryptosystem for encoding ciphertexts. 

This is the same as the ciphertext space. 

 

EXAMPLES: 

 

The cipher codomains, or ciphertext spaces, of various classical 

cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()).cipher_codomain() 

Free alphabetic string monoid on A-Z 

sage: SubstitutionCryptosystem(HexadecimalStrings()).cipher_codomain() 

Free hexadecimal string monoid 

sage: HillCryptosystem(BinaryStrings(), 3).cipher_codomain() 

Free binary string monoid 

sage: TranspositionCryptosystem(OctalStrings(), 5).cipher_codomain() 

Free octal string monoid 

sage: VigenereCryptosystem(Radix64Strings(), 7).cipher_codomain() 

Free radix 64 string monoid 

""" 

return self._cipher_codomain 

 

def key_space(self): 

r""" 

Return the alphabet used by this cryptosystem for encoding keys. 

 

EXAMPLES: 

 

The key spaces of various classical cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()).key_space() 

Ring of integers modulo 26 

sage: SubstitutionCryptosystem(HexadecimalStrings()).key_space() 

Free hexadecimal string monoid 

sage: HillCryptosystem(BinaryStrings(), 3).key_space() 

Full MatrixSpace of 3 by 3 dense matrices over Ring of integers modulo 2 

sage: TranspositionCryptosystem(OctalStrings(), 5).key_space() 

Symmetric group of order 5! as a permutation group 

sage: VigenereCryptosystem(Radix64Strings(), 7).key_space() 

Free radix 64 string monoid 

""" 

return self._key_space 

 

def block_length(self): 

r""" 

Return the block length of this cryptosystem. For some cryptosystems 

this is not relevant, in which case the block length defaults to 1. 

 

EXAMPLES: 

 

The block lengths of various classical cryptosystems:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()).block_length() 

1 

sage: SubstitutionCryptosystem(HexadecimalStrings()).block_length() 

1 

sage: HillCryptosystem(BinaryStrings(), 3).block_length() 

3 

sage: TranspositionCryptosystem(OctalStrings(), 5).block_length() 

5 

sage: VigenereCryptosystem(Radix64Strings(), 7).block_length() 

1 

""" 

return self._block_length 

 

def period(self): 

if self._period is None: 

raise TypeError("Argument has no associated period.") 

return self._period 

 

class SymmetricKeyCryptosystem(Cryptosystem): 

r""" 

The base class for symmetric key, or secret key, cryptosystems. 

""" 

def alphabet_size(self): 

r""" 

Return the number of elements in the alphabet of this 

cryptosystem. This only applies to any cryptosystem whose plaintext 

and ciphertext spaces are the same alphabet. 

 

EXAMPLES:: 

 

sage: ShiftCryptosystem(AlphabeticStrings()).alphabet_size() 

26 

sage: ShiftCryptosystem(BinaryStrings()).alphabet_size() 

2 

sage: ShiftCryptosystem(HexadecimalStrings()).alphabet_size() 

16 

sage: SubstitutionCryptosystem(OctalStrings()).alphabet_size() 

8 

sage: SubstitutionCryptosystem(Radix64Strings()).alphabet_size() 

64 

""" 

return self._cipher_domain.ngens() 

 

class PublicKeyCryptosystem(Cryptosystem): 

r""" 

The base class for asymmetric or public-key cryptosystems. 

"""