<jupyter_start><jupyter_text>SubBytes<jupyter_code>Z2 = Integers(2) # Z_2

# Anillo de polinomios en Z_2
R = PolynomialRing(Z2,'x')
# generador
x = R.gen() 

# Creamos el cociente isomorfo a GF(2^8)
S = R.quotient(x^8 + x^4 + x^3 + x + 1, 'x')
def build_pol(binary, grade=7):
    """
    A partir de la representación binaria construimos
    el polinomo asociado en el anillo cociente S.
    """
    pol_coefs = []
    for i in binary:
        if i == '1':
            pol_coefs.append("x^{}".format(grade))
        grade -= 1

    return S(" + ".join(pol_coefs))
a = S.gen()
p = S(a^3-a^2)
# Coefs del byte 63 de menos a mas significativo
c = list(map(Z2, [1,1,0,0,0,1,1,0]))
def SubBytes(byte):
    """
    Dado un byte xy (hex) calculamos la salida correspondiente
    según la transformación subbyte.
    """
    
    
    # Calculamos el inverso de la representacion binaria
    if byte == "00":
        inverse = list(map(Z2, [0,0,0,0,0,0,0,0]))
    else:
        polynom = build_pol(format(int(byte, 16), '#010b')[2:])
        # https://github.com/sagemath/sage/blob/develop/src/sage/rings/polynomial/polynomial_quotient_ring_element.py#L442
        inverse = polynom^-1
    
    # Almacenamos los bits de la transformación en una cadena
    new_byte_bin = ""
    
    # Obtenemos el bit i 
    for i in range(8):
        new_byte_bin += str(
            inverse[i] 
            + inverse[(i + 4)%8] 
            + inverse[(i + 5)%8] 
            + inverse[(i + 6)%8] 
            + inverse[(i + 7)%8] 
            + c[i]
        )
    
    # Invertimos el orden de los bits para cambiar cual es
    # el más significativo. El primero es el más significativo.
    new_byte_bin = new_byte_bin[::-1]
    
    # Devolvemos la expresión en hexadecimal
    return "{:02x}".format(int(new_byte_bin, 2))
    
SubBytes("53")<jupyter_output><empty_output><jupyter_text>Construimos la tabla<jupyter_code>def matprint(table):
    for row in table:
        print(row)
table = []
for x in range(16):
    row = []
    for y in range(16):
        xs = str(hex(x))[2:]
        ys = str(hex(y))[2:]
        row.append(SubBytes( xs + ys))
    table.append(row)
matprint(table)<jupyter_output>['63', '7c', '77', '7b', 'f2', '6b', '6f', 'c5', '30', '01', '67', '2b', 'fe', 'd7', 'ab', '76']
['ca', '82', 'c9', '7d', 'fa', '59', '47', 'f0', 'ad', 'd4', 'a2', 'af', '9c', 'a4', '72', 'c0']
['b7', 'fd', '93', '26', '36', '3f', 'f7', 'cc', '34', 'a5', 'e5', 'f1', '71', 'd8', '31', '15']
['04', 'c7', '23', 'c3', '18', '96', '05', '9a', '07', '12', '80', 'e2', 'eb', '27', 'b2', '75']
['09', '83', '2c', '1a', '1b', '6e', '5a', 'a0', '52', '3b', 'd6', 'b3', '29', 'e3', '2f', '84']
['53', 'd1', '00', 'ed', '20', 'fc', 'b1', '5b', '6a', 'cb', 'be', '39', '4a', '4c', '58', 'cf']
['d0', 'ef', 'aa', 'fb', '43', '4d', '33', '85', '45', 'f9', '02', '7f', '50', '3c', '9f', 'a8']
['51', 'a3', '40', '8f', '92', '9d', '38', 'f5', 'bc', 'b6', 'da', '21', '10', 'ff', 'f3', 'd2']
['cd', '0c', '13', 'ec', '5f', '97', '44', '17', 'c4', 'a7', '7e', '3d', '64', '5d', '19', '73']
['60', '81', '4f', 'dc', '22', '2a', '90', '88', '46', 'ee', 'b8', '14', 'de', '5e', '0b', 'db']
['e0', '32', '3a', '0a', '49',[...]
StarcoderdataJupyterStructuredCleanDedup