2009-09-18 43 views
10

我有一个byte[] testKey = new byte[8];递增一个byte []

这显然与所有字节为0。我想通过1要经过的所有字节,并增加对循环的每次迭代开始所以最终我通过各种可能性的字节数组。我也想尽可能做到这一点。是的,我正在努力写一篇蛮力文章。

更新我得到了不安全的方法工作,它是最快的。但是,根据我的计算,使用.Net DESCryptoServiceProvider对每个密钥执行DES加密需要花费76,000,000年。 10,000次加密需要1.3秒。感谢所有关于最无用问题的真棒答案!

+6

要测试所有2^64组合将需要很长时间。 – 2009-09-18 12:15:18

+0

如果你真的对每个组合进行了一些处理,它将花费大约七年的时间来循环组合。蛮力似乎不是正确的方法... – Guffa 2009-09-18 13:25:55

+0

是的,除非你拥有政府机构或大公司的计算资源,否则你没有机会彻底地测试2^64大小的搜索空间。即使每个测试只用一个周期来运行现代CPU,也需要71万年时间才能完成整个搜索空间的测试。 – 2009-09-18 14:08:38

回答

11

btw;它需要很多处理的检查2^64个选项...

好了,最快方式,可能是只使用一个Int64(又名long)或UInt64ulong),并使用++?你真的需要byte[]吗?

作为一个哈克替代,怎么样:

Array.Clear(data, 0, data.Length); 
while (true) 
{ 
    // use data here 
    if (++data[7] == 0) if (++data[6] == 0) 
    if (++data[5] == 0) if (++data[4] == 0) 
     if (++data[3] == 0) if (++data[2] == 0) 
     if (++data[1] == 0) if (++data[0] == 0) break; 
} 

唯一的其他方法,我能想到的是使用不安全的代码去跟一个数组仿佛这是一个Int64 ...凌乱。

unsafe static void Test() { 
    byte[] data = new byte[8]; 
    fixed (byte* first = data) { 
     ulong* value = (ulong*)first; 
     do { 
      // use data here 
      *value = *value + 1; 
     } while (*value != 0); 
    } 
} 
+0

+1:是的。八个字节是一个Int64。 :-) – 2009-09-18 11:59:56

+0

我认为固定数组在内存中使用它在不安全的代码中的开销将超过能够将它视为int64的好处... – Guffa 2009-09-18 12:14:46

+0

您应该在不安全的代码中使用ulong *,而不是uint *。尽管你在固定语句内部循环,但它令人惊讶地很慢。我的托管代码增加了阵列约200倍... – Guffa 2009-09-18 12:33:16

-1

BitConverter.ToInt64/BitConverter.GetBytes - 8字节转换为准确长,增加它。 几乎完成时转换回字节。 它是系统以最快的方式

+0

当*几乎*完成? – 2009-09-18 12:04:35

+4

'BitConverter'?最快的?每次调用**创建一个新的'byte []'** **不是任何延伸最快的**。 – 2009-09-18 12:08:28

+0

想法是使一些逻辑括号 - 开始您将(ONCE!)字节转换为长。最后多次增加(当完成和一次!)转换回字节 – Dewfy 2009-09-18 12:40:30

1
for (UInt64 i = 0; i < UInt64.MaxValue; i++) 
{ 
    byte[] data = BitConverter.GetBytes(i) 
} 
+0

这为每个调用创建了一个新的'byte []',这为分配和垃圾收集做了大量的工作;有更快的方法使用固定的数组 – 2009-09-18 12:09:05

+0

这个循环将在任何时候或在7854年的春天完成。 – 2009-09-18 12:14:02

+0

只需循环使用组合将花费大约七年在我的答案中使用更快的方法。使用BitConverter需要大约10000年... – Guffa 2009-09-18 12:39:01

3

字节[8]本质上是一个ULONG但如果你真的需要它字节[8]您可以使用

byte[] bytes = new byte[8]; 
ulong i = 0; 
bytes = BitConverter.GetBytes(i); 
6

这是你如何增加数组中的值:

int index = testKey.Length - 1; 
while (index >= 0) { 
    if (testKey[index] < 255) { 
     testKey[index]++; 
     break; 
    } else { 
     testKey[index--] = 0; 
    } 
} 

index为-1这个代码后,你已经迭代所有组合。

这比使用BitConverter稍快,因为它不会为每次迭代创建一个新数组。

编辑:
一个小的性能测试表明,这比使用BitConverter快约1400倍......

+4

为什么downvote?如果你不解释为什么,它是毫无意义的...... – Guffa 2009-09-18 14:33:57

+0

我提高了,因为我看到了这里的潜力。问题是'break'语句出错了。原因是代码不会超过1. – LamonteCristo 2012-12-18 23:41:47

+0

@ makerofthings7:感谢upvote。我认为你误解了代码。它会增加一个数组。再增加一步,再次使用代码。如果您想在循环中使用它,请将代码放入循环中。 – Guffa 2012-12-19 00:06:04

4

什么了不起的问题!这里有一个办法做到这一点没有不安全的代码:

public struct LongAndBytes 
{ 
    [FieldOffset(0)] 
    public ulong UlongValue; 
    [FieldOffset(0)] 
    public byte Byte0; 
    [FieldOffset(1)] 
    public byte Byte1; 
    [FieldOffset(2)] 
    public byte Byte2; 
    [FieldOffset(3)] 
    public byte Byte3; 
    [FieldOffset(4)] 
    public byte Byte4; 
    [FieldOffset(5)] 
    public byte Byte5; 
    [FieldOffset(6)] 
    public byte Byte6; 
    [FieldOffset(7)] 
    public byte Byte7; 

    public byte[] ToArray() 
    { 
     return new byte[8] {Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7}; 
    } 
} 


// ... 

    LongAndBytes lab = new LongAndBytes(); 

    lab.UlongValue = 0; 
    do { 
     // stuff 
     lab.UlongValue++; 
    } while (lab.ULongValue != 0); 

每个成员字节0 ...字节7重叠了ulong,分享它的成员。这不是一个数组 - 我试图用这种方法来解决问题,结果并不理想。我敢打赌,有人知道这个魔术宣言是如何实现的。我可以做一个P/Invoke,但不能在.NET中使用,因为数组是一个对象。

+1

'byte [] b =新字节[8] {Byte0,Byte1,Byte2,Byte3,Byte4,Byte5,Byte6,Byte7};' – Chris 2009-09-18 13:07:56

+0

谢谢!增加了 – plinth 2009-09-18 13:10:57

+0

+1的变化,让人称赞。我喜欢这个简单而强大的答案。 – 2009-09-18 13:22:03

2

可以使用位运算符提取字节:

byte[] bytes = new byte[8]; 
for (ulong u = 0; u < ulong.MaxValue; u++) 
{ 
    bytes[0] = (byte)(u & 0xff); 
    bytes[1] = (byte)((u >> 8) & 0xff); 
    bytes[2] = (byte)((u >> 16) & 0xff); 
    bytes[3] = (byte)((u >> 24) & 0xff); 
    bytes[4] = (byte)((u >> 32) & 0xff); 
    bytes[5] = (byte)((u >> 40) & 0xff); 
    bytes[6] = (byte)((u >> 48) & 0xff); 
    bytes[7] = (byte)((u >> 56) & 0xff); 
    // do your stuff... 
} 

这是不太“的hackish”,因为它在一个无符号的64位整数进行操作的第一和然后提取字节。但要注意CPU的永久性。

1
byte[] array = new byte[8]; 
int[] shifts = new int[] { 0, 8, 16, 24, 32, 40, 48, 56 };  
for (long index = long.MinValue; index <= long.MaxValue; index++) 
{ 
    for (int i = 0; i < 8; i++) 
    { 
     array[i] = (byte)((index >> shifts[i]) & 0xff); 
    } 
    // test array 
} 
0
for (int i = 0; i < bytes.Length & 0 == ++bytes[i]; i++); 

应尽可能快地不安全的方法,并允许任何大小的阵列。