密码学AES扩展欧几里得求多项式在GF8域上的逆元

做法

有限域 GF( 2 8 )上的元素满足加法交换群、线性空间,所以,是和整数有限域上的运算等价的,所以可以直接重载扩展欧几里得来计算多项式的逆元
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

/*
> Problem:main
> Author: WESTWOOD
> Mail: [email protected]
> Created Time: 2018/6/18 12:58:17
> function:多项式逆元,直接调用整数的扩展欧几里得,然后重载多项式的/*+-运算符
*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<bitset>
#pragma warning(disable : 4996)
using namespace std;
using LL = long long;
class polynomial/*多项式*/
{
public:
    LL value;
    const size_t lenght()const/*获取2进制长度*/
    {
        LL tmp = value;
        int len = 0;
        while (tmp) {
            len++;
            tmp >>= 1;
        }
        return len;
    }

    polynomial(LL value) {/*构造函数*/
        this->value = value;
    }
    polynomial operator + (const polynomial &o)/*模2加*/
    {
        return value ^ o.value;
    }
    polynomial operator - (const polynomial &o)/*模2除*/
    {
        return value ^ o.value;
    }
    polynomial operator * (const polynomial &o)/*模2乘*/
    {
        polynomial ans = polynomial(0);
        polynomial tmp = o;
        for (int i = 0;tmp.value;i++, tmp.value >>= 1) {
            if (tmp.value & 1) {
                ans = ans + polynomial(this->value << i);
            }
        }
        return ans;
    }
    polynomial operator % (const polynomial &o) {/*模2模*/
        size_t len = this->lenght(), leno = o.lenght();
        int width = int(len) - int(leno);
        polynomial remainder = *this;
        polynomial quotient = polynomial(0);
        while (width >= 0)
        {
            if (remainder.value >> (leno + width - 1))
            {
                quotient.value += (1LL << width);
                remainder = remainder - polynomial(o.value << width);
            }
            width--;
        }
        return remainder;
    }
    polynomial operator / (const polynomial &o) {/*模2除*/
        size_t len = this->lenght(), leno = o.lenght();
        int width = int(len) - int(leno);
        polynomial remainder = *this;
        polynomial quotient = polynomial(0);
        while (width >= 0)
        {
            if (remainder.value >> (leno + width - 1))
            {
                quotient.value += (1LL << width);
                remainder = remainder - polynomial(o.value << width);
            }
            width--;
        }
        return quotient;
    }
    friend ostream &operator<<(ostream &os, const polynomial&o);
};
pair <LL, LL> exgcd(LL a, LL b)/*整数的扩展扩展欧几里得*/
{
    if (b == 0)
        return { 1,0 };
    auto factor = exgcd(b, a%b);
    auto &x = factor.first, &y = factor.second;
    auto xp = y, yp = x - a / b * y;
    return { xp,yp };
}
pair <polynomial, polynomial> exgcd(polynomial a, polynomial b)/*多项式的扩展扩展欧几里得*/
{
    auto tmp = a / b;
    if (b.value == 0)
        return { polynomial(1),polynomial(0) };
    auto factor = exgcd(b, a%b);
    auto &x = factor.first, &y = factor.second;
    auto xp = y, yp = x - (a / b * y);
    return { xp,yp };
}
const polynomial GF8 = polynomial((1 << 8) + (1 << 4) + (1 << 3) + (1 << 1) + 1);

ostream &operator<<(ostream &os, const polynomial&o) {
    auto value = o.value;
    if (value == 0)
    {
        os << 0;
        return os;
    }
    bool flag = false;
    for (int i = 0;value;i++, value >>= 1) {
        if (value & 1) {
            if (flag)
                os << "+";
            flag = true;
            if (i)
                os << "x^" << i;
            else
                os << 1;
        }
    }
    return os;
}
int main()
{
    if (fopen("in.txt", "r") != NULL)
    {
        freopen("in.txt", "r", stdin);
        freopen("out.txt", "w", stdout);
    }
    cout << "3在mod11下的逆元:" << exgcd(3, 11).first << endl;
    cout << "密码学书本83页书上的样例:\n";
    cout << (polynomial((1 << 8) + (1 << 6) + (1 << 4) + (1 << 3) + (1 << 2)) % GF8).value << endl;
    cout << (polynomial((1 << 6) + (1 << 4) + (1 << 2) + (1 << 1) + 1)*polynomial((1 << 7) + (1 << 1) + 1) % GF8) << endl;
    cout << (polynomial((1 << 7) + (1 << 5) + (1 << 3) + (1 << 2) + (1 << 1)) % GF8) << endl;
    cout << (polynomial((1 << 8) + (1 << 6) + (1 << 4) + (1 << 3) + (1 << 2)) % GF8) << endl;
    cout << "0x02在GF8下的逆元:" << exgcd(polynomial(2), GF8).first << endl;
    return 0;
}

参考

XZQ的博客
这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq965194745/article/details/80724432
今日推荐