使用关键字

时间:2015-12-03 08:40:27

标签: c algorithm permutation cryptanalysis

我必须实现以下算法,该算法将通过爬山在特定密码的密码分析中运行几十亿次。 该算法产生标准字母{A,B,C,...,Y,Z}的排列,其中K为7个相同字母的字母,如下所示:

  • 假设K = INGXNDM = {9,14,7,24,14,4,13}
  • 从右到左,数字K1 =字母表上的9个位置。达到了R,所以置换的第一个元素是R:P = {R,...}
  • 使用Mark R,我们必须跳过'过了之后。
  • 从R开始,计数K2 =左侧的14个位置,我们到达D并将其标记为已使用。 P = {R,d,...}
  • 下一个计数是7,当达到A时我们循环并认为Z跟随A,所以我们到达W:将其标记为使用,P = {R,D,W,...}
  • 下一个计数是24,所以我们到达V是因为我们跳过R,D和W.
  • 等......当使用K7 = 13时,我们以K1 = 9
  • 重新启动
  • 获得的换位字母是:RDWVGBL ZHUKNFI PJSAMXT CQOYE

实际上我需要在解密代码中进行逆置换。 我的代码实现了一个链接列表,用于跳过使用过的字母。 它在基数0,所以A = 0,... Z = 25并返回逆置换Pinv(i)= j意味着字母i在位置j。

#define ALPHALEN 26
void KeyToPermut(int *K, int * Pinv);
int previnit[ALPHALEN], prev[ALPHALEN], nextinit[ALPHALEN], next[ALPHALEN];

int main() {
    int l, Pinv[ALPHALEN], K[7] = { 8, 13, 6, 23, 13, 3, 12 }, P[ALPHALEN];
    // precalculate links between letters, ordered right to left , from Z to A
    for (l = 0; l < ALPHALEN; l++) {
        previnit[l] = l + 1;  // prev[A] = B
        if (previnit[l] >= ALPHALEN) previnit[l] -= ALPHALEN;  // prev[Z] = A
        nextinit[l] = l - 1; // next[B] = A
        if (nextinit[l] < 0) nextinit[l] += ALPHALEN; // next[A] = Z
    }

    KeyToPermut(K, Pinv); // this is the code to be optimized

    for (l = 0; l < ALPHALEN; l++) P[Pinv[l]] = l;  // calculate direct permutation
    for (l = 0; l < ALPHALEN; l++)  printf("%c", P[l] + 65);
    printf("\n");
}

void KeyToPermut(int *K, int * Permut) {
    int l, keyptr=0, cnt=0, p=0;
    // copy prev[] and next[] from precalculated arrays previnit[] and nextinit[]
    for (l = 0; l < ALPHALEN; l++) {
        prev[l] = previnit[l];
        next[l] = nextinit[l];
    }

    while (1) {
        for (l = 0; l <= K[keyptr] % (ALPHALEN-cnt); l++) p = next[p];

        Permut[p] = cnt++;
        if (cnt < ALPHALEN)
        {
            prev[next[p]] = prev[p];      // link previous and next positions
            next[prev[p]] = next[p];
            keyptr++;
            if (keyptr >= 7) keyptr = 0;  // re-use K1 after K7
        }
        else
            break;
    }
}

我有两个问题:

  1. 如何优化KeyToPermut中的代码?分析器显然表明链接中的for循环是瓶颈。可能有一种避免链表的方法......?
  2. 显然关键空间不是26!但要小得多:26 ^ 7,所以只有26个子集!可以生成。你知道生成的排列有多具体吗?它们属于一类已知的排列吗?例如,我无法识别(到目前为止)这些排列周期中的任何模式。
  3. 我使用的是VS2013和C,项目的其他部分都是CUDA代码。 (x64平台)

    感谢您的关注。

    背景信息:密码使用的加密方案使用长度为7的4个密钥K.因此,用于查找纯文本的理论密钥空间是26 ^ 28,即131位。该方法可以使用其他密钥长度:1到25之间的任何值都可以使用。

1 个答案:

答案 0 :(得分:0)

  

如何优化KeyToPermut中的代码?剖析器显然   表示链接中的for循环是瓶颈。   可能有一种避免链表的方法......?

我没有找到一个更好的方法来避免链表,但我们可以单独使用而不是双重链接,因为所需的先前位置可以从for循环的最后一次迭代中获得。

void KeyToPermut(int *K, int *Permut)
{
    int l, keyptr=0, cnt=0, p=0, prev;
    // copy next[] from precalculated array nextinit[]
    for (l = 0; l < ALPHALEN; l++) next[l] = nextinit[l];
    while (1)
    {
        for (l = 0; l <= K[keyptr] % (ALPHALEN-cnt); l++) prev = p, p = next[p];
        Permut[p] = cnt++;
        if (cnt < ALPHALEN)
        {
            next[prev] = next[p];         // link previous to next position
            p = prev;
            keyptr++;
            if (keyptr >= 7) keyptr = 0;  // re-use K1 after K7
        }
        else
            break;
    }
}

这节省了约10%的函数运行时间。