美文网首页
实践作业

实践作业

作者: myvio | 来源:发表于2018-03-28 20:15 被阅读0次

    作业要求如下:

    1. 使用Python或者Sage语言;
    2. 上交电子版,用MD书写,提交网络链接即可;比如,使用jianshu、github、作业部落或者CSDN等;
    3. 代码需具有可读性和可验证性(比如,可容易让审阅者知道所生成的S-box的正确性。)

    任务一:

    任意给定两个素数p和q,p!= q,记 N = p * q ,构造Zn*.

    问题(编程解决):

    1. 是否每个元素都有inverse?是否成群?
    2. 这个集合有多少元素?

    Python源代码

    • 判断是否为素数
    def isprime():
        count = 1
        while (count):
            n = int(input("输入一个质数:"))
            for i in range(2, n):
               if n % i == 0:
                    print(" %d 这不是一个质数!" % n)
                    break
            else:
                return n
    
    • 生成一个与N互素的列表
    def CommonFactor(a,b):
        if a<b:
            t = a
            a = b
            b = t
        while(a%b):
            t = b
            b = a % b
            a = t
        return b
    
    • 判断是否存在逆元
    def is_inverse(list,n):
        mark=1
        for i in range(0,len(list)):
            count=1
            for j in range(0,len(list)):
                if((list[i]*list[j])%n==1):
                    count = 0
                    print("%s存在逆元%s"%(list[i],list[j]),end="   ")
            if count:
                print("%s不存在逆元"%(list[i]),end="   ")
                mark=0
        print()
        if(mark):
            print("任何元素都有逆元")
        return mark
    
    • 判断运算是否封闭
    def is_closed(list,n):
        mark=1
        for i in range(0, len(list)):
            for j in range(0, len(list)):
                count=0
                for k in range(0, len(list)):
                    if((list[i]*list[j])%n == list[k]):
                        count=1
                        num=list[k]
                if count:
                    print("%s*%s封闭值为%s"%(list[i],list[j],num))
                else:
                    print("%s*%s不封闭"%(list[i],list[j]))
                    mark=0
        return mark
    
    • 主函数
    def main():
        p=isprime()
        count=1
        while(count):
            q=isprime()
            if not q==p:
                count=0
            else:
                print("与第一个质数相同,请重新输入")
        n=p*q
        list=[]
        for i in range(1,n):
            k=CommonFactor(i,n)
            if k==1:
                list.append(i)
        for i in range(0,len(list)):
            print(list[i],end="  ")
        print()
        a=is_inverse(list,n)
        b=is_closed(list,n)
        if a==1 and b==1:
            print("任意元素都有逆元且运算封闭,成群")
            print("群元素有%s个"%(len(list)))
        elif a==0:
            print("存在元素没有逆元,不成群")
        elif b==0:
            print("运算不封闭,不成群")
    
    main()
    

    任务二

    写一个程序,实现AES的S-box的构造。


    整体实现思路

    1. 初始化S-box,使第x行第y列的元素为{xy}。
      (代码实现时这一步和第二步合在一个initialize()函数中完成)
    2. 对S-box中的每个元素求乘法逆元
      (求乘法逆元用到扩展欧几里得算法,所以必须要实现GF( 2^8 )中的乘法运算)
    3. 对S-box中的公式运用一下公式得到最终的S-box。


      公式

    源代码

    #include<iostream>
    #include<fstream>
    #include <iomanip>
    using namespace std;
    unsigned char exp[256], log[256], inv[256];
    unsigned char GFmul(unsigned char a, unsigned char b){
        //GF(2^8) 乘法
        unsigned char result = 0;
        if((b&1) == 1)result = a;
        b >>= 1;
        for(int i = 1; i < 8; i ++){
            if(a > 127){
                a = (a << 1) ^ 0x1b;
            }
            else{
                a <<= 1;
            }
            if((b&1) == 1){
                result ^= a;
            }
            b >>= 1;
        }
        return result;
    }
    void generateMulTab(){
        //选择生成元3作为构造乘法表的基础
        const int N = 3;
        exp[1] = N;
        log[N] = 1;
        unsigned char tmp = N;
        for(int i = 2; i < 256; i ++){
            tmp = GFmul(tmp, N);
            exp[i] = tmp;
            log[tmp] = i;
        }
    }
    void generateMulInverse(){
        //利用exp来构造乘法逆元
        inv[0] = 0;
        inv[1] = 1;
        //若3^m * 3^n = 1 = 3^255,则 m + n = 255
        for(int i = 1; i < 255; i ++){
            inv[exp[i]] = exp[255-i];
        }
    }
    unsigned char SBoxValue(unsigned char x){
        //返回SBOX对应的值
        bool xb[8];
        unsigned char y = inv[x];
        //AES规定的常数项
        const bool N[8][8] = {1, 0, 0, 0, 1, 1, 1, 1,
                              1, 1, 0, 0, 0, 1, 1, 1,
                              1, 1, 1, 0, 0, 0, 1, 1,
                              1, 1, 1, 1, 0, 0, 0, 1,
                              1, 1, 1, 1, 1, 0, 0, 0,
                              0, 1, 1, 1, 1, 1, 0, 0,
                              0, 0, 1, 1, 1, 1, 1, 0,
                              0, 0, 0, 1, 1, 1, 1, 1};
        const bool C[8] = {1, 1, 0, 0, 0, 1, 1, 0};
        //将y转化为数组用作矩阵运算
        for(int i = 0; i < 8; i ++){
            xb[i] = (y&1);
            y >>= 1;
        }
        //矩阵乘法
        bool tmp[8];
        for(int i = 0; i < 8; i ++)tmp[i] = 0;
        for(int i = 0; i < 8; i ++){
            for(int j = 0; j < 8; j ++){
                tmp[i] ^= (N[i][j] & xb[j]);
            }
            tmp[i] ^= C[i];
        }
        //将数组结果转化为数值
        unsigned char result = 0;
        result |= tmp[7];
        for(int i = 6; i >= 0; i --){
            result <<= 1;
            if(tmp[i])result |= 1;
        }
        return result;
    }
    int main(){
        //单元测试,输出SBOX的全部值
        generateMulTab();
        generateMulInverse();
        unsigned char SBox[16][16];
        for(int i = 0; i < 16; i ++){
            for(int j = 0; j < 16; j ++){
                unsigned char tmp = i*16 + j;
                SBox[i][j] = SBoxValue(tmp);
            }
        }
        ofstream write("Test.txt");
        for(int i = 0; i < 16; i ++){
            for(int j = 0; j < 16; j ++){
                write<<setiosflags(ios::left)<<setw(4)<<hex<<(int)SBox[i][j];
            }
            write<<endl;
        }
        write.close();
        return 0;
    }
    

    运行结果

    运行结果.png

    相关文章

      网友评论

          本文标题:实践作业

          本文链接:https://www.haomeiwen.com/subject/xgpucftx.html