如何增量迭代大小为 n 的字节数组的所有可能值?
How to incrementally iterate through all possible values of a byte array of size n?
对于我的问题 n=16,但也将不胜感激。
所以我有一个字节数组:
byte[] key;
我的问题是我想遍历此数组中每个元素的所有可能值,并将其组合。我知道这需要很长时间,而且我并不打算真正完成这个循环,只是为了制作一个至少会尝试这个的循环。
例如:
第一次迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
}
第二次迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
}
第三次迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
}
最终迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
}
显然我刚刚对上面的数组进行了硬编码。我需要一种以适当方式执行此操作的方法。同样,我知道有许多 种不同的组合。我所需要的只是一种开始遍历所有可能值的方法。我如何在我的循环中执行此操作?
即我应该用什么替换循环体,以便遍历大小为 16 的字节数组的所有可能值。
我试过的:
在循环体中,我尝试了以下操作:
key = new byte[16] { (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i };
显然是错误的,只会测试可能值的一小部分。只会尝试 i= 0,...,255 然后在 i=256 时重新开始 --> (byte)i = 0.
我怀疑我需要更多嵌套。可能多达 16 个嵌套循环,这听起来很疯狂而且可能是错误的?我无法解决这个问题,任何帮助将不胜感激!
用途:
这个问题的目的是证明暴力密码分析在实践中是多么低效。我的程序的其余部分工作正常,我只是陷入了这个循环。
这是一个示例代码,没有任何异常处理,并且模拟您提到的计数器的效率有点低
public static void NextIteration(byte[] input)
{
if (input.All(x => x == 255))
throw new InvalidOperationException("there is no iteration left");
var converted = input.Select(x => (int) x).ToArray();
converted[0]++;
for (var i = 0; i < converted.Length; i++)
{
if (converted[i] == 256)
{
converted[i] = 0;
converted[i + 1]++;
}
}
for (var i = 0; i < input.Length; i++)
{
input[i] = (byte) converted[i];
}
}
如果您没有意识到:16 个字节是 Guid 的大小或标准加密密钥大小的大小。组合如此之多,连一个分数都数不出来。如果你在 1000 台机器上并行化并等待一年,也许你可以枚举最后 8 个字节。
您可以通过 运行 从 0 到 ulong.MaxValue
的 for 循环轻松做到这一点。我将此作为答案提交,因为这个非常简单的想法允许您开始枚举并且基本上永远不会到达您完成的地步。
for (ulong i = 0; i < ulong.MaxValue; i++) {
var bytes = new [] {
0, 0, 0, 0, 0, 0, 0, 0
, (byte)(i >> (7 * 8))
, (byte)(i >> (6 * 8))
, (byte)(i >> (5 * 8))
//...
, (byte)(i >> (0 * 8)) };
}
或者,只使用 16 个嵌套的 for 循环。我不认为这很疯狂,因为它非常简单,而且显然是正确的。
对于我的问题 n=16,但也将不胜感激。
所以我有一个字节数组:
byte[] key;
我的问题是我想遍历此数组中每个元素的所有可能值,并将其组合。我知道这需要很长时间,而且我并不打算真正完成这个循环,只是为了制作一个至少会尝试这个的循环。
例如:
第一次迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
}
第二次迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
}
第三次迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
}
最终迭代:
//Math.Pow(2,128) is the max no. of iterations right?
byte[] key;
for(int i = 0; i < Math.Pow(2,128); i++)
{
key = new byte[16] {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
}
显然我刚刚对上面的数组进行了硬编码。我需要一种以适当方式执行此操作的方法。同样,我知道有许多 种不同的组合。我所需要的只是一种开始遍历所有可能值的方法。我如何在我的循环中执行此操作?
即我应该用什么替换循环体,以便遍历大小为 16 的字节数组的所有可能值。
我试过的:
在循环体中,我尝试了以下操作:
key = new byte[16] { (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i };
显然是错误的,只会测试可能值的一小部分。只会尝试 i= 0,...,255 然后在 i=256 时重新开始 --> (byte)i = 0.
我怀疑我需要更多嵌套。可能多达 16 个嵌套循环,这听起来很疯狂而且可能是错误的?我无法解决这个问题,任何帮助将不胜感激!
用途: 这个问题的目的是证明暴力密码分析在实践中是多么低效。我的程序的其余部分工作正常,我只是陷入了这个循环。
这是一个示例代码,没有任何异常处理,并且模拟您提到的计数器的效率有点低
public static void NextIteration(byte[] input)
{
if (input.All(x => x == 255))
throw new InvalidOperationException("there is no iteration left");
var converted = input.Select(x => (int) x).ToArray();
converted[0]++;
for (var i = 0; i < converted.Length; i++)
{
if (converted[i] == 256)
{
converted[i] = 0;
converted[i + 1]++;
}
}
for (var i = 0; i < input.Length; i++)
{
input[i] = (byte) converted[i];
}
}
如果您没有意识到:16 个字节是 Guid 的大小或标准加密密钥大小的大小。组合如此之多,连一个分数都数不出来。如果你在 1000 台机器上并行化并等待一年,也许你可以枚举最后 8 个字节。
您可以通过 运行 从 0 到 ulong.MaxValue
的 for 循环轻松做到这一点。我将此作为答案提交,因为这个非常简单的想法允许您开始枚举并且基本上永远不会到达您完成的地步。
for (ulong i = 0; i < ulong.MaxValue; i++) {
var bytes = new [] {
0, 0, 0, 0, 0, 0, 0, 0
, (byte)(i >> (7 * 8))
, (byte)(i >> (6 * 8))
, (byte)(i >> (5 * 8))
//...
, (byte)(i >> (0 * 8)) };
}
或者,只使用 16 个嵌套的 for 循环。我不认为这很疯狂,因为它非常简单,而且显然是正确的。