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 HillCryptosystem. It is a symmetric key cipher so HillCryptosystem is a child class of SymmetricKeyCryptosystem, which in turn is a child class of Cryptosystem. The following diagram shows the inheritance relationship of particular cryptosystems:

Cryptosystem
+ SymmetricKeyCryptosystem
| + HillCryptosystem
| + LFSRCryptosystem
| + ShiftCryptosystem
| + ShrinkingGeneratorCryptosystem
| + SubstitutionCryptosystem
| + TranspositionCryptosystem
| + VigenereCryptosystem
+ PublicKeyCryptosystem
class sage.crypto.cryptosystem.Cryptosystem(plaintext_space, ciphertext_space, key_space, block_length=1, period=None)[source]

Bases: Set_generic

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

\[E : {\mathcal K} \rightarrow {\rm Hom}({\mathcal M},{\mathcal C})\]
\[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)                              # needs sage.groups
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
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings())
Shift cryptosystem on Free alphabetic string monoid on A-Z
>>> SubstitutionCryptosystem(HexadecimalStrings())
Substitution cryptosystem on Free hexadecimal string monoid
>>> HillCryptosystem(BinaryStrings(), Integer(3))
Hill cryptosystem on Free binary string monoid of block length 3
>>> TranspositionCryptosystem(OctalStrings(), Integer(5))                              # needs sage.groups
Transposition cryptosystem on Free octal string monoid of block length 5
>>> VigenereCryptosystem(Radix64Strings(), Integer(7))
Vigenere cryptosystem on Free radix 64 string monoid of period 7
block_length()[source]

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()           # needs sage.groups
5
sage: VigenereCryptosystem(Radix64Strings(), 7).block_length()
1
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings()).block_length()
1
>>> SubstitutionCryptosystem(HexadecimalStrings()).block_length()
1
>>> HillCryptosystem(BinaryStrings(), Integer(3)).block_length()
3
>>> TranspositionCryptosystem(OctalStrings(), Integer(5)).block_length()           # needs sage.groups
5
>>> VigenereCryptosystem(Radix64Strings(), Integer(7)).block_length()
1
cipher_codomain()[source]

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()        # needs sage.groups
Free octal string monoid
sage: VigenereCryptosystem(Radix64Strings(), 7).cipher_codomain()
Free radix 64 string monoid
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings()).cipher_codomain()
Free alphabetic string monoid on A-Z
>>> SubstitutionCryptosystem(HexadecimalStrings()).cipher_codomain()
Free hexadecimal string monoid
>>> HillCryptosystem(BinaryStrings(), Integer(3)).cipher_codomain()
Free binary string monoid
>>> TranspositionCryptosystem(OctalStrings(), Integer(5)).cipher_codomain()        # needs sage.groups
Free octal string monoid
>>> VigenereCryptosystem(Radix64Strings(), Integer(7)).cipher_codomain()
Free radix 64 string monoid
cipher_domain()[source]

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()          # needs sage.groups
Free octal string monoid
sage: VigenereCryptosystem(Radix64Strings(), 7).cipher_domain()
Free radix 64 string monoid
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings()).cipher_domain()
Free alphabetic string monoid on A-Z
>>> SubstitutionCryptosystem(HexadecimalStrings()).cipher_domain()
Free hexadecimal string monoid
>>> HillCryptosystem(BinaryStrings(), Integer(3)).cipher_domain()
Free binary string monoid
>>> TranspositionCryptosystem(OctalStrings(), Integer(5)).cipher_domain()          # needs sage.groups
Free octal string monoid
>>> VigenereCryptosystem(Radix64Strings(), Integer(7)).cipher_domain()
Free radix 64 string monoid
ciphertext_space()[source]

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()       # needs sage.groups
Free octal string monoid
sage: VigenereCryptosystem(Radix64Strings(), 7).ciphertext_space()
Free radix 64 string monoid
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings()).ciphertext_space()
Free alphabetic string monoid on A-Z
>>> SubstitutionCryptosystem(HexadecimalStrings()).ciphertext_space()
Free hexadecimal string monoid
>>> HillCryptosystem(BinaryStrings(), Integer(3)).ciphertext_space()
Free binary string monoid
>>> TranspositionCryptosystem(OctalStrings(), Integer(5)).ciphertext_space()       # needs sage.groups
Free octal string monoid
>>> VigenereCryptosystem(Radix64Strings(), Integer(7)).ciphertext_space()
Free radix 64 string monoid
key_space()[source]

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()              # needs sage.groups
Symmetric group of order 5! as a permutation group
sage: VigenereCryptosystem(Radix64Strings(), 7).key_space()
Free radix 64 string monoid
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings()).key_space()
Ring of integers modulo 26
>>> SubstitutionCryptosystem(HexadecimalStrings()).key_space()
Free hexadecimal string monoid
>>> HillCryptosystem(BinaryStrings(), Integer(3)).key_space()
Full MatrixSpace of 3 by 3 dense matrices over Ring of integers modulo 2
>>> TranspositionCryptosystem(OctalStrings(), Integer(5)).key_space()              # needs sage.groups
Symmetric group of order 5! as a permutation group
>>> VigenereCryptosystem(Radix64Strings(), Integer(7)).key_space()
Free radix 64 string monoid
period()[source]
plaintext_space()[source]

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()        # needs sage.groups
Free octal string monoid
sage: VigenereCryptosystem(Radix64Strings(), 7).plaintext_space()
Free radix 64 string monoid
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings()).plaintext_space()
Free alphabetic string monoid on A-Z
>>> SubstitutionCryptosystem(HexadecimalStrings()).plaintext_space()
Free hexadecimal string monoid
>>> HillCryptosystem(BinaryStrings(), Integer(3)).plaintext_space()
Free binary string monoid
>>> TranspositionCryptosystem(OctalStrings(), Integer(5)).plaintext_space()        # needs sage.groups
Free octal string monoid
>>> VigenereCryptosystem(Radix64Strings(), Integer(7)).plaintext_space()
Free radix 64 string monoid
class sage.crypto.cryptosystem.PublicKeyCryptosystem(plaintext_space, ciphertext_space, key_space, block_length=1, period=None)[source]

Bases: Cryptosystem

The base class for asymmetric or public-key cryptosystems.

class sage.crypto.cryptosystem.SymmetricKeyCryptosystem(plaintext_space, ciphertext_space, key_space, block_length=1, period=None)[source]

Bases: Cryptosystem

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

alphabet_size()[source]

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
>>> from sage.all import *
>>> ShiftCryptosystem(AlphabeticStrings()).alphabet_size()
26
>>> ShiftCryptosystem(BinaryStrings()).alphabet_size()
2
>>> ShiftCryptosystem(HexadecimalStrings()).alphabet_size()
16
>>> SubstitutionCryptosystem(OctalStrings()).alphabet_size()
8
>>> SubstitutionCryptosystem(Radix64Strings()).alphabet_size()
64