分枝定界法搜索SPN结构的最优差分特征(以PRESENT64为例)

#define printf __mingw_printf
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>

#define R 10      // 定义算法轮数
#define N 16      // 定义s盒个数
#define s_in_L 4  // 定义s盒输入比特
#define s_out_L 4 // 定义s盒输出比特
#define L (1 << (s_in_L + s_out_L))
#define L1 (1 << s_in_L)
#define L2 (1 << s_out_L)
#define base (L2 - 1)

int Rr;
long double DiffP[R][N]; // 每轮的差分概率
int Alpha[R][N];         // 每轮的输入差分
int Beta[R][N];          // 每轮的输出差分
int maxAlpha[R][N];      // 每轮的最优输入差分
int maxBeta[R][N];       // 每轮的最优输出差分
long double Pestim;
int flag;
long double all_sbdiff_p[N][L]; // 所有s盒的差分概率
long double pn_sb[N];           // n个s盒的最优概率
long double Pbest[R];           // 每轮的最优概率
int actIndex[R][N];             // 活跃s盒的下标
int actIndexLength[R];          // 活跃s盒的个数
long double sboxdiffprobability[L];
int maxbacktable[N][L2];
int maxforwardtable[N][L1];
int *combian;
int *combianSize;
int combianIndex = 0;
int data[N];
long double *arr;
int decreasort[L1][L2];
int pbox[64] = {0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3, 19, 35, 51, 4, 20, 36, 52, 5, 21, 37, 53, 6, 22, 38, 54, 7, 23, 39, 55, 8, 24, 40, 56, 9, 25, 41, 57, 10, 26, 42, 58, 11, 27, 43, 59, 12, 28, 44, 60, 13, 29, 45, 61, 14, 30, 46, 62, 15, 31, 47, 63};

void Round(int r);
void SubRound(int r, int n);
void FirstRound(int M[], int n);
void init();
void calculateDifferential();
void all_sbdiff_pfun();
void Decreasesort();
void maxback();
void maxforward();
void pn_sbfun();
void calculateCombianAndCombianSize();
void generateCombinations(int n, int start, int *buffer, int bufferIndex);
int sumcombian(int n);
void activesbox(int begin, int end);
void update(int begin, int end);
long double product(int begin, int end);
long double fmaxfun(long double data[], int begin, int end);
void sortDoubleArray(long double array[], int size);
void sort_indices(long double *array, int *indices, int n);
int compare1(const void *a, const void *b);
int compare2(const void *a, const void *b);
void pboxfun(int *data);
long double LastRound();
int OptTrailSearch(long double Pestim);
long double OptTrail();
int compare1(const void *a, const void *b)
{
    int index1 = *(int *)a;
    int index2 = *(int *)b;
    if (arr[index1] < arr[index2])
        return 1;
    if (arr[index1] > arr[index2])
        return -1;
    return 0;
}
int compare2(const void *a, const void *b)
{
    long double arg1 = *(const long double *)a;
    long double arg2 = *(const long double *)b;
    if (arg1 < arg2)
        return -1;
    if (arg1 > arg2)
        return 1;
    return 0;
}
void sortDoubleArray(long double array[], int size)
{
    qsort(array, size, sizeof(long double), compare2);
}
long double fmaxfun(long double data[], int begin, int end)
{
    long double max = data[begin];
    for (int i = begin; i <= end; i++)
    {
        if (data[i] > max)
        {
            max = data[i];
        }
    }
    return max;
}
void sort_indices(long double *array, int *indices, int n)
{
    arr = array; // 设置全局变量
    for (int i = 0; i < n; i++)
    {
        indices[i] = i;
    }
    qsort(indices, n, sizeof(int), compare1);
}
void generateCombinations(int n, int start, int *buffer, int bufferIndex)
{
    if (bufferIndex == n)
    {
        for (int i = 0; i < n; i++)
        {
            combian[combianIndex++] = buffer[i];
        }
        return;
    }
    for (int i = start; i < N; i++)
    {
        buffer[bufferIndex] = i;
        generateCombinations(n, i + 1, buffer, bufferIndex + 1);
    }
}
void calculateCombianAndCombianSize()
{
    int totalSize = N * (1 << (N - 1));        // 计算combian的总大小
    combian = malloc(totalSize * sizeof(int)); // 分配combian的大小
    combianSize = malloc(N * sizeof(int));     // 存储每个n的组合数
    int prevIndex = 0;                         // 用于计算每个n的组合数
    for (int n = 1; n <= N; n++)
    {
        int *buffer = malloc(n * sizeof(int));
        generateCombinations(n, 0, buffer, 0);
        combianSize[n - 1] = (combianIndex - prevIndex) / n; // 存储n的组合数
        prevIndex = combianIndex;                            // 更新prevIndex
        free(buffer);
    }
}
int sumcombian(int n)
{
    int sum = 0;
    if (n == 1)
    {
        return 0;
    }
    for (int i = 0; i < n - 1; i++)
    {
        sum = sum + (i + 1) * combianSize[i];
    }
    return sum;
}
void init()
{
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < N; j++)
        {
            Alpha[i][j] = 0;
            Beta[i][j] = 0;
            DiffP[i][j] = 1.0;
            actIndex[i][j] = j;
        }
        actIndexLength[i] = N;
    }
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < L; j++)
        {
            all_sbdiff_p[i][j] = 0.0;
        }
    }
}
int sbox[L1] = {0xC, 0x5, 0x6, 0xB, 0x9, 0x0, 0xA, 0xD, 0x3, 0xE, 0xF, 0x8, 0x4, 0x7, 0x1, 0x2};
void sboxfun(int *data)
{
    for (int i = 0; i < (1 << L1); i++)
    {
        data[i] = sbox[data[i]];
    }
}
long double calculateDifferentialProbability(int inputDiff, int outputDiff)
{
    int count = 0;
    for (int x = 0; x < L1; x++)
    {
        int y = x ^ inputDiff;
        if (outputDiff == (sbox[x] ^ sbox[y]))
            count++;
    }
    long double probability = (long double)count / L1;
    return probability;
}
void calculateDifferential()
{
    for (int i = 0; i < L1; i++)
    {
        for (int j = 0; j < L2; j++)
        {
            sboxdiffprobability[i * L1 + j] = calculateDifferentialProbability(i, j);
        }
    }
}
void all_sbdiff_pfun()
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < L; j++)
        {
            all_sbdiff_p[i][j] = sboxdiffprobability[j];
        }
    }
}
long double product(int begin, int end)
{
    long double p = 1.0;
    for (int i = begin - 1; i < end; i++)
    {
        for (int j = 0; j < actIndexLength[i]; j++)
        {
            p = p * DiffP[i][actIndex[i][j]];
        }
    }
    return p;
}
void update(int begin, int end)
{
    int index1, index2;
    for (int r = begin - 1; r < end; r++)
    {
        for (int i = 0; i < actIndexLength[r]; i++)
        {
            index1 = actIndex[r][i];
            index2 = Beta[r][index1] + Alpha[r][index1] * L2;
            DiffP[r][index1] = all_sbdiff_p[index1][index2];
        }
    }
}
void activesbox(int begin, int end)
{
    for (int r = begin - 1; r < end; r++)
    {
        int count = 0;
        for (int i = 0; i < N; i++)
        {
            if (Alpha[r][i] != 0)
            {
                actIndex[r][count] = i;
                count++;
            }
        }
        actIndexLength[r] = count;
    }
}
void Decreasesort()
{
    long double array[L2];
    int *indices = malloc(L2 * sizeof(int)); // 索引数组
    for (int i = 0; i < L1; i++)
    {
        for (int j = 0; j < L2; j++)
        {
            array[j] = sboxdiffprobability[i * L1 + j];
        }
        sort_indices(array, indices, L2);
        for (int k = 0; k < L2; k++)
        {
            decreasort[i][k] = indices[k];
        }
    }
    free(indices);
}
void pn_sbfun()
{
    long double temp[N];
    for (int i = 0; i < N; i++)
    {
        temp[i] = fmaxfun(sboxdiffprobability, (1 << s_out_L), L - 1);
    }
    sortDoubleArray(temp, N);
    pn_sb[0] = temp[N - 1];
    for (int i = 1; i < N; i++)
    {
        pn_sb[i] = pn_sb[i - 1] * temp[N - i - 1];
    }
}
void maxback()
{
    for (int sbox_index = 0; sbox_index < N; sbox_index++)
    {
        for (int beta = 0; beta < L2; beta++)
        {
            int alpha = 0;
            long double pmax = 0;
            for (int i = 0; i < L1; i++)
            {
                if (all_sbdiff_p[sbox_index][i * L2 + beta] >= pmax)
                {
                    alpha = i;
                    pmax = all_sbdiff_p[sbox_index][beta + i * L2];
                }
            }
            maxbacktable[sbox_index][beta] = alpha;
        }
    }
    return;
}
void maxforward()
{
    for (int sbox_index = 0; sbox_index < N; sbox_index++)
    {
        for (int alpha = 0; alpha < L1; alpha++)
        {
            int beta = 0;
            long double pmax = 0;
            for (int i = 0; i < (1 << s_out_L); i++)
            {
                if (all_sbdiff_p[sbox_index][i + alpha * L1] >= pmax)
                {
                    beta = i;
                    pmax = all_sbdiff_p[sbox_index][i + alpha * L1];
                }
            }
            maxforwardtable[sbox_index][alpha] = beta;
        }
    }
    return;
}
void pboxfun(int *data)
{
    int bits[64];
    for (int i = 0; i < 16; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            bits[i * 4 + j] = (data[i] >> (3 - j)) & 1;
        }
    }
    int temp[64];
    for (int i = 0; i < 64; i++)
    {
        temp[i] = bits[i];
    }
    for (int i = 0; i < 64; i++)
    {
        bits[pbox[i]] = temp[i];
    }
    for (int i = 0; i < 16; i++)
    {
        data[i] = 0;
        for (int j = 0; j < 4; j++)
        {
            data[i] |= bits[i * 4 + j] << (3 - j);
        }
    }
}
long double LastRound()
{
    if (actIndexLength[Rr - 1] > 0)
    {
        int index1 = 0, index2 = 0;
        for (int i = 0; i < N; i++)
        {
            Beta[Rr - 1][i] = 0;
        }
        for (int i = 0; i < actIndexLength[Rr - 1]; i++)
        {
            index1 = actIndex[Rr - 1][i];
            Beta[Rr - 1][index1] = maxforwardtable[index1][Alpha[Rr - 1][index1]];
        }
        long double p = 1.0;
        int m;
        for (int i = 0; i < Rr; i++)
        {
            for (int j = 0; j < actIndexLength[i]; j++)
            {
                index1 = actIndex[i][j];
                index2 = Beta[i][index1] + Alpha[i][index1] * L2;
                p = p * all_sbdiff_p[index1][index2];
            }
        }
        if (p >= Pestim)
        {
            flag = 0;
            Pestim = p;
            activesbox(1, Rr);
            for (int i = 0; i < Rr; i++)
            {
                for (int j = 0; j < N; j++)
                {
                    maxAlpha[i][j] = Alpha[i][j];
                    maxBeta[i][j] = Beta[i][j];
                }
            }
        }
    }
    else
    {
        printf("全0 error\n");
    }
}
void Round(int r)
{
    for (int i = 0; i < N; i++)
    {
        Beta[r - 1][i] = 0;
    }
    activesbox(1, r);
    SubRound(r, 1);
}
void SubRound(int r, int n)
{
    if (n > actIndexLength[r - 1])
    {

        // 这里不用像论文一样把概率赋值,因为在每次改变值时都已经更新了概率
        int data[N];
        for (int i = 0; i < N; i++)
        {
            data[i] = Beta[r - 1][i];
        }
        pboxfun(data); // 线性变换
        for (int i = 0; i < N; i++)
        {
            Alpha[r][i] = data[i];
        }
        activesbox(1, r + 1);
        update(1, r + 1);

        if (r + 1 < Rr)
        {
            Round(r + 1);
        }
        else
        {
            LastRound();
        }
    }
    else
    {
        for (int i = 0; i < L2; i++)
        {
            Beta[r - 1][actIndex[r - 1][n - 1]] = decreasort[Alpha[r - 1][actIndex[r - 1][n - 1]]][i];
            long double p = 1;
            for (int j = 0; j < n; j++)
            {
                p = p * all_sbdiff_p[actIndex[r - 1][j]][Beta[r - 1][actIndex[r - 1][j]] + Alpha[r - 1][actIndex[r - 1][j]] * L2];
            }
            for (int i = 0; i < r - 1; i++)
            {
                for (int j = 0; j < actIndexLength[i]; j++)
                {
                    p = p * all_sbdiff_p[actIndex[i][j]][Beta[i][actIndex[i][j]] + Alpha[i][actIndex[i][j]] * L2];
                }
            }
            p = p * Pbest[Rr - r - 1];
            if (actIndexLength[r - 1] > n)
            {
                p = p * pn_sb[actIndexLength[r - 1] - n - 1];
            }
            if (p < Pestim)
            {
                break;
            }
            int data[N];
            for (int i = 0; i < N; i++)
            {
                data[i] = Beta[r - 1][i];
            }
            pboxfun(data); // 线性变换
            int sum = 0;
            for (int i = 0; i < 16; i++)
            {
                if (data[i] != 0)
                {
                    sum++;
                }
            }
            p = p * pn_sb[sum - 1];
            if (Rr > r + 1)
            {
                p = p * Pbest[Rr - r - 2];
            }
            if (p < Pbest[Rr - r - 1] * Pestim)
            {
                break;
            }

            else
            {
                update(r, r);
                activesbox(1, r);
                SubRound(r, n + 1);
            }
        }
    }
    return;
}
void FirstRound(int M[], int n)
{
    int sbox_index;
    for (int i = 0; i < n; i++)
    {
        sbox_index = M[i];
        Alpha[0][sbox_index] = maxbacktable[sbox_index][Beta[0][sbox_index]];
    }
    for (int i = 0; i < N; i++)
    {
        data[i] = Beta[0][i];
    }
    pboxfun(data); // 线性变换
    for (int i = 0; i < N; i++)
    {
        Alpha[1][i] = data[i];
    }
    if (Rr > 2)
    {
        activesbox(1, 2);
        update(1, 1);
        Round(2);
    }
    else
    {
        for (int i = 0; i < N; i++)
        {
            Beta[Rr - 1][i] = 0;
        }
        activesbox(1, Rr);
        LastRound();
    }
    return;
}
int OptTrailSearch(long double Pestim) // r大于等于2
{
    int begin;
    long limit;
    long temp;
    for (int n = 1; n < N + 1; n++)
    {
        if (pn_sb[n - 1] * Pbest[Rr - 2] < Pestim)
        {
            break;
        }
        else
        {
            for (int i = 0; i < N; i++)
            {
                Beta[0][i] = 0;
                Alpha[0][i] = 0;
            }
            begin = sumcombian(n);
            int M[n];
            for (int i = 0; i < combianSize[n - 1]; i++)
            {
                for (int j = 0; j < n; j++)
                    M[j] = combian[begin + n * i + j];
            }
            limit = powl(base, n);
            for (long k = 0; k < limit; k++)
            {
                temp = k;
                for (int index = 0; index < n; index++)
                {
                    Beta[0][M[index]] = temp % base + 1;
                    temp = temp / base;
                }
                FirstRound(M, n);
            }
        }
    }
    return flag;
}
long double OptTrail()
{
    Pestim = Pbest[Rr - 2] * pn_sb[0];
    flag = -1;
    flag = OptTrailSearch(Pestim);
    while (1)
    {
        if (~flag)
        {
            break;
        }
        else
        {
            Pestim = Pestim / 2;
            OptTrailSearch(Pestim);
        }
    }
    return Pestim;
}
int main()
{
    init();
    calculateDifferential();
    all_sbdiff_pfun();
    Decreasesort();
    maxback();
    maxforward();
    calculateCombianAndCombianSize();
    pn_sbfun();
    Pbest[0] = pn_sb[0];

    clock_t start, end;
    double cpu_time_used = 0;

    for (Rr = 2; Rr < R + 1; Rr++)
    {
        start = clock();
        Pbest[Rr - 1] = OptTrail();
        end = clock();
        cpu_time_used = cpu_time_used + ((double)(end - start)) / (CLOCKS_PER_SEC / 1000);
        printf("%d轮 最优差分特征:\n", Rr);
        for (int i = 0; i < Rr; i++)
        {
            for (int j = 0; j < N; j++)
            {
                printf("%d ", maxAlpha[i][j]);
            }
            printf("\n");
            for (int j = 0; j < N; j++)
            {
                printf("%d ", maxBeta[i][j]);
            }
            printf("\n");
        }
    }
    // 输出Pbest
    printf("最优差分转移概率:\n");
    for (int i = 1; i < R; i++)
    {
        printf("%Le ", Pbest[i]);
    }
    printf("\n%d轮程序运行时间: %g ms\n", R, cpu_time_used);
    free(combian);
    free(combianSize);
    return 0;
}

上述算法原理参考自论文《Automatic Search for a Maximum Probability Differential Characteristic in a Substitution-Permutation Network》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦想花终开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值