在O(1)时间内转换LFSR循环?

时间:2011-02-17 18:52:25

标签: big-o

我想知道是否有办法将两个概念结合起来:LFSR和Barrel Shifters

我正在寻找一种方法,在O(1)时间内,将LFSR循环移位一定数量的班次。

我希望找到的是一个简单的过程,其中我具有LFSR的当前状态以及我希望从该状态转换为参数的快速/简单过程的次数。

起初我只是想看看所有的水龙头,然后将水龙头移动1并再次看着它们,每次都找到位移位并将其追加到最后但当然这不是O( 1)如果我想移动很多次以使得水龙头“滑落”原来的LFSR状态,它会变得复杂。

如果不在O(1)时间内,是否有更有效的方法进行多次轮班而不是单独进行每次轮班?

4 个答案:

答案 0 :(得分:3)

总的来说,我倾向于说答案是否定的。原因是如果存在这样的算法,那么我们可以在O(1)时间内计算由LFSR生成的序列中的任何给定位。这似乎不太可能是可行的。

但是,您可以进行一些预计算以加快速度。注意,在任何固定步数之后,LFSR中每个单元的状态是来自初始状态的位的线性组合。因此,如果您为每个单元格预先计算1个步骤,2个步骤,4个步骤,8个步骤等的线性组合中的系数,那么您应该能够在相对较短的时间内跳过许多步骤。当然,这实际上只会让你在之前提到的“滑落”情况下获得有用的加速。

答案 1 :(得分:2)

对我来说,如果抽头占据寄存器的一个小区域,你可以使用表查找一次做一位或多位。

例如,如果寄存器是8位,从左到右编号为7到0,抽头是位0和2.低位3位可以从8项表中获取新位7。

类似地,低位4位可以从16条表中获取新的7,6位。低位5位可用于从32项表中获取新位7,6,5,依此类推。

只是一个想法。

答案 2 :(得分:1)

基于LFSR的加密算法的密码分析基本上是这样做的,但是相反(即,它们解决了[current-N]迭代(通常是初始状态)的条件而不是[current + N]。他们这样做(主要是通过创建一组线性方程,然后解决。我从来没有尝试重新排列它们前进而不是后退,但随意它似乎应该是完全可能的(它们的一部分快乐是线性的... 。)

因此,阅读基于LFSR的加密算法中的一些known attacks可能会有所帮助/有用。

答案 3 :(得分:0)

如果要以2的幂为单位调整LFSR序列,则可以。如果您采用最大长度LFSR序列并将其逐位分割成2 ^ N个部分(这样交错这些部分的结果将为您提供原始序列),这些单独序列中的每一个都与原始序列相同分阶段。

所以你基本上可以加倍反馈抽头序列并且并行运行2 ^ N个LFSR(在比原始宽2 ^ N倍的寄存器中):

#include <iostream>
using namespace ::std;

void
galois1(const unsigned int taps, const unsigned int seed)
{
  unsigned lfsr = seed;
  do {
    cout << ((lfsr & 1) ? '1' : '0');
    lfsr =
      (lfsr >> 1)
      ^ (-(lfsr & 1) & taps);
  } while (lfsr != seed);

  cout << endl;
}

void
galois2(const unsigned int taps, const unsigned int seed)
{
  unsigned lfsr = seed;
  do {
    cout << ((lfsr & 1) ? '1' : '0') << ((lfsr & 2) ? '1' : '0');
    lfsr =
      (lfsr >> 2)
      ^ (-(lfsr & 1) & taps & 0x5555)
      ^ (-(lfsr & 2) & taps & 0xaaaa);
  } while (lfsr != seed);

  cout << endl;
}

int
main(void)
{
  // Original LFSR sequence, x^5 + x^3 + 1:
  //
  // Taps:  1 0 1 0 0
  // Seed:  1 0 0 0 0

  galois1(0x0014, 0x0010);

  // "Double stepped" sequence, interleaved bits:
  //
  // Taps (even):   1   0   1   0   0
  // Taps (odd):  1   0   1   0   0
  // Seed (even):   0   0   1   0   0
  // Seed (odd):  1   1   0   0   0

  galois2(0x330, 0x290);

  return 0;
}

唯一棘手的部分是弄清楚新的种子(如果你找到一种方法,不产生序列的前2N位,我想知道: - )