1. 主算法:
import copy
import multi_Num
import AES_sbox
sbox = AES_sbox.s_box()
RC = [1, 2, 4, 8, 16, 32, 64, 128, 27, 54]          # 将RC以十进制表示


def rowmix(rowMix_s):                               # rowmix_s是一个矩阵
    for i in range(0, 4):
        temp = copy.deepcopy(rowMix_s[i])           # 深拷贝数组
        for j in range(0, 4):
            if i > 0:
                rowMix_s[i][j - i] = temp[j]
    return rowMix_s


def colunmix(columMix):                             # columMix是一个整型矩阵
    a = [[1 for i in range(0, 4)] for i in range(0, 4)]
    for i in range(0, 4):
        a[i][i] = 2
        a[i][(i + 1) % 4] = 3                       # 生成列混淆的左乘矩阵
    b = copy.deepcopy(columMix)                     # 深拷贝,a,b指向内存中的不同单元
    for i in range(0, 4):
        for j in range(0, 4):
            temp1 = 0
            for k in range(0, 4):
                temp = multi_Num.multi_multiplication(b[k][j], a[i][k])[0]
                if temp > 255:                      # 最左边移位是一的时要去掉,再与27异或
                    temp = int(bin(temp)[-8:], 2) ^ 27
                temp1 ^= temp
            columMix[i][j] = temp1
    return columMix


def g(w, j):                                        # w是一组密钥,j是对应的轮数
    w_1 = w[1:] + w[:1]
    for i in range(0, 4):                           # 当w下标%4=0时产生w'
        x = int('{:08b}'.format(w_1[i])[:4], 2)     # sbox寻址的x,高四位
        y = int('{:08b}'.format(w_1[i])[4:8], 2)    # sbox寻址的y,低四位
        g_list.append(sbox[x][y])                   # g_list便于检验经过g函数的s盒置换是否正确,打印即可
        w_1[i] = int(sbox[x][y], 16)
    w_1[0] ^= RC[j]                                 # 第一个数与对应RC中的元素异或
    return w_1


def sbox_change(w):                                 # w是整型矩阵
    for i in range(0, 4):                           # 当w下标%4=0时产生w'
        for j in range(0, 4):
            x = int('{:08b}'.format(w[i][j])[:4], 2)
            y = int('{:08b}'.format(w[i][j])[4:8], 2)
            # print("明文的s置换", sbox[x][y]) s盒置换验证
            w[i][j] = int(sbox[x][y], 16)
    return w


def key_plus(w_1, w_4):                             # w_1,w_4为整型列表
    w4 = copy.deepcopy(w_4)
    for i in range(0, 4):
        w4[i] = w_1[i] ^ w4[i]                      # 当w下标%4!=0时产生w'
    return w4


def key_extneds(key):                               # key为二维列表即矩阵
    w = [[0 for i in range(0, 4)]for i in range(0, 44)]
    for i in range(0, 4):
        for j in range(0, 4):
            w[i][j] = key[j][i]                     # 输入密钥被直接赋值给扩展密钥数组的前四个字
    for i in range(4, 44):
        if i % 4 == 0:
            w[i] = key_plus(w[i-4], g(w[i-1], i//4-1))   # i//4是对应RC的下标
        else:
            w[i] = key_plus(w[i-1], w[i-4])
    for i in range(0, 4):
        for j in range(0, 4):
            w[i][j] = key[i][j]                     # 输入密钥被直接赋值给扩展密钥数组的前四个字
    w_temp = [n for a in w for n in a]              # 用w_temp列表存放所有的密钥,顺序为从左到右
    for i in range(4, 44):                          # 对行列进行转化
        for j in range(0, 4):
            if i % 4 == 0:
                w[i][j] = w_temp[4*(i+j)]
            else:
                w[i][j] = w_temp[4*(i+j)-3*(i % 4)]     # 通过观察总结出公式
    print("密钥空间:", w)
    return w


def toMatrix(a):                                    # 将十六进制字符数组转化成二维整型数组
    tomatrix = [[0 for i in range(0, 4)] for i in range(0, 4)]
    if a == 0:
        print("明文示例:", "01 23 45 67 89 ab cd ef fe dc ba 98 76 54 32 10")
        list = input("输入明文!(十六进制,空格隔开)\n").split()  # 用list存放输入的明文或密钥
    else:
        print("密钥示例:", "0f 15 71 c9 47 d9 e8 59 0c b7 ad d6 af 7f 67 98")
        list = input("输入密钥!(十六进制,空格隔开)\n").split()
    for i in range(0, 16):
        list[i] = int(list[i], 16)                  # 将list中的字符转换成十进制整数
    for i in range(0, 4):
        k = i
        for j in range(0, 4):
            tomatrix[i][j] = list[k]                # 由于输入的时候是按顺序从左到右输入,所以要将其转化成对应的行和列
            k += 4
    return tomatrix                                 # 输入密钥,以空格隔开


def display_w(w):                                   # 以十六进制展示密钥空间,需要直接调用即可
    for i in range(0, 44):
        for j in range(0, 4):
            print('{:02x}'.format(w[i][j]))
        print(w[i])


def tohex(matrix):                                  # 将每一轮结束列表以十六进制展示
    hex16 = []
    for i in range(0, 4):
        for j in range(0, 4):
            hex16.append("{:02x}".format(matrix[i][j]))
    return ''.join(hex16)


def AES_single(plain, w_time):                      # 单轮aes加密
    for i in range(0, 4):                           # 轮密钥加
        for j in  range(0, 4):
            plain[i][j] ^= w[i+w_time][j]
            # plain[i][j] = '{:02x}'.format(plain[i][j]),检验每次轮开始前是否正确
    print(w_time//4, "轮开始: ", tohex(plain))
    s_plain = sbox_change(plain)                    # sbox置换
    if w_time // 4 < 10:                            # 控制第9轮的显示
        print("字节代替后:", tohex(s_plain))
        row_plain = rowmix(s_plain)                 # 行变换
        print("行移位后: ", tohex(row_plain))
    if w_time // 4 < 9:                             # 控制第十轮的显示
        plain = colunmix(row_plain)                 # 列混淆
        print("列混淆后: ", tohex(plain))
    return plain


def start():                                        # 算法开始
    w_time = 0
    for i in range(0, 11):
        AES_single(plain, w_time)
        w_time += 4


if __name__ == '__main__':
    g_list = []
    plain = toMatrix(0)   # 明文转化成矩阵 0代表输入明文
    key = toMatrix(1)     # 1代表输入密钥
    w = key_extneds(key)  # 密钥拓展
    start()



# 本AES算法主要使用列表处理输入的明文和密钥,及进行行移位,列混淆,密钥扩展等操作,其中密钥扩展和明文输入时,采用十六进制+空格的方式输入,
# 由于顺序输入的原因,起初行列和书本上的行列有差异,后来使用列表存储,然后再观察结构,利用第77~88行代码将行列互换,达到了要求
# 本AES算法涉及到的知识点有:函数定义、参数传递、列表浅拷贝与深拷贝、for循环、列表解析、二维列表、format置换等
  1. multi_Num基于GF(2^8)域上的运算
def multi_plus(n1, n2):                         # 多项式加法
    return n1 ^ n2


def multi_multiplication(n1, n2):               # 多项式乘法
    temp = bin(n2)[2:]
    s = 0
    while len(temp) > 0:
        if int(temp[0]) > 0:
            s ^= n1 << len(temp) - 1
        temp = temp[1:]
    return s, multi_division(s, 283)[1]


def multi_division(n1, n2, q=0):                # 多项式除法运算
    if n1 < n2:
        return 0, n1
    elif n2 == 0:
        return 0
    else:
        delta = len(bin(n1)) - len(bin(n2))
        q += 1 << delta
        r = (n2 << delta) ^ n1
        if r >= n2:
            return multi_division(r, n2, q)
        else:
            return q, r


def multi_gcd(n1, n2):                          # 多项式求最大公因式(欧几里得算法)
    if n1 == 0:
        return n2
    elif n2 == 0:
        return n1
    if n1 - n2 >= 0:
        n1 = multi_division(n1, n2)[1]
        return multi_gcd(n1, n2)
    else:                                       # s1比s2小,则将s1,s2互换,继续运算
        n1, n2 = n2, n1
        return multi_gcd(n1, n2)


def multi_niyuan(n1, n2, v1=1, v2=0, w1=0, w2=1):  # GF(2^8)域求乘法逆元,原理和整数的扩展欧几里得算法几乎一致,但是必须先定义多项式的模运算、加法运算和乘法运算
    s1, s2 = n1, n2
    if n2 == 0:
        return 0
    if multi_gcd(s1, s2) != 1:
        return "没有逆元"
    else:
        rx = multi_division(n1, n2)[1]          # multi_rx返回的是一个列表,装载着余数和商
        qx = multi_division(n1, n2)[0]
        n1, n2 = n2, rx
        v1, v2 = v2, multi_plus(v1, multi_multiplication(v2, qx)[1])
        w1, w2 = w2, multi_plus(w1, multi_multiplication(w2, qx)[1])
        if rx != 0:
            return multi_niyuan(n1, n2, v1, v2, w1, w2)
        else:
            return w1


def menu():
    n1 = int(input("请输入n1\n"))
    n2 = int(input("请输入n2\n"))
    choose = input("请选择功能:\n"
                   "1.ax+bx\n"
                   "2.ax·bx\n"
                   "3.ax/bx\n"
                   "4.求ax mod(bx)的逆元\n"
                   "5.gcd(ax,bx)\n")
    if choose == '1':
        print('和是:', multi_plus(n1, n2))
    elif choose == '2':
        print('GF(2)上乘积是:', multi_multiplication(n1, n2)[0], " GF(2^8)上乘积是:", multi_multiplication(n1, n2)[1])
    elif choose == '3':
        print('商是:', multi_division(n1, n2)[0], ' 余数是:', multi_division(n1, n2)[1])
    elif choose == '4':
        print('逆元是:', multi_niyuan(n1, n2))
    elif choose == '5':
        print('gcd是:', multi_gcd(n1, n2))
    else:
        print("输入有误,请重试!")


if __name__ == '__main__':
    while True:
        menu()
  1. 用于生成S盒的Aes_sbox
import multi_Num


def change(temp):
    c = '01100011'
    ss = ''
    for n in range(0, 8):
        ss += str(int(temp[n]) ^ int(temp[(n + 4) % 8]) ^ int(temp[(n + 3) % 8]) ^ int(temp[(n + 2) % 8]) ^
                  int(temp[(n + 1) % 8]) ^ int(c[n]))
    return ss


def change2(temp):
    c = '00000101'
    ss = ''
    for n in range(0, 8):
        ss += str(int(temp[(n + 6) % 8]) ^ int(temp[(n + 3) % 8]) ^ int(temp[(n + 1) % 8])
                  ^ int(c[n]))
    return ss


def s_box():
    sbox = [['' for i in range(0, 16)] for i in range(0, 16)]
    for i in range(0, 16):
        for j in range(0, 16):
            sbox[i][j] = '{:02x}'.format(int(change(list('{:08b}'.format(multi_Num.multi_niyuan(283, i * 16 + j)))), 2))
    return sbox


def s_box_reverse():
    rbox = [['' for i in range(0, 16)] for i in range(0, 16)]
    for i in range(0, 16):
        for j in range(0, 16):
            rbox[i][j] = '{:02x}'.format(multi_Num.multi_niyuan(283, int(change2(list('{:08b}'.format(i * 16 + j))), 2)))
    return rbox

@Nickname4th  Hainu University 2018.12.9
另,该算法已经作为课程作业上交,学弟学妹可以借鉴,但是不能照搬,否则后果自负。
创作不易,望支持。