1

我正在实现一个使用 RC4 流密码进行加密和解密的自定义 iostream(即,具有读取、写入、查找和关闭功能)。该流的一个约定是它是双向的,调用代码需要能够在进行任何实际读取或写入之前任意寻找到流中的任何位置。

现在因为 RC4 使用的密钥依赖于所有先前的交换操作,直到给定的“告诉”位置,我如何才能结合任意寻找任何位置的能力?

显然,在执行实际的异或转换过程之前,我可以查找到给定查找偏移的位置(在以下示例中由THIS BIT标记),例如:

/**
 * @brief called from a stream's read or write function
 * @param in the input buffer
 * @param out the output buffer
 * @param startPosition the current stream position (obtained via the streams
 * tellg or tellp functions for read and write respectively)
 * @param length the number of bytes to transform
 */
void transform(char *in, char *out,
               std::ios_base::streamoff startPosition,
               long length)
{

    // need to reset sbox from member s_box each time this
    // function is called
    long sbox[256];
    for (int i = 0; i<256; ++i) {
        sbox[i]=m_sbox[i];
    }

    // ***THIS BIT***
    // need to run the swap operation startPosition times
    // to get sbox integer sequence in order
    int i = 0, j = 0, k = 0;
    for (int a=0; a < startPosition; ++a) {
        i = (i + 1) % 256;
        j = (j + sbox[i]) % 256;
        swapints(sbox, i, j);
    }

    // now do the actual xoring process up to the length
    // of how many bytes are being read or written
    for (int a=0; a < length; ++a) {
        i = (i + 1) % 256;
        j = (j + sbox[i]) % 256;
        swapints(sbox, i, j);
        k = sbox[(sbox[i] + sbox[j]) % 256];
        out[a] = in[a] ^ k;
    }

}

然后将从流实现的读取或写入中调用转换,例如:

MyStream&
MyStream::read(char * const buf, std::streamsize const n)
{
    std::ios_base::streamoff start = m_stream.tellg();
    std::vector<char> in;
    in.resize(n);
    (void)m_stream.read(&in.front(), n);
    m_byteTransformer->transform(&in.front(), buf, start, n);
    return *this;
}    

编辑:流应该不知道转换函数是如何工作的。转换功能是完全独立的,我应该能够在不同的转换实现中自由交换。

编辑:函数 swapints 看起来像这样:

void swapints(long *array, long ndx1, long ndx2)
{
    int temp = array[ndx1];
    array[ndx1] = array[ndx2];
    array[ndx2] = temp;
}

上述变换函数的真正问题在于它的速度很慢,因为它必须在执行异或变换之前执行 startPosition 初始交换操作。当执行许多查找操作时,这是非常有问题的。现在我听说 RC4 是为了快速,但我的(可能是糟糕的实现)建议在初始交换操作集的情况下使用其他方式。

所以我真正的问题是:如何优化上述代码以减少所需操作的数量?理想情况下,我想消除交换操作的初始(“ THIS BIT ”)集

编辑:优化初始 sbox 设置可能是微不足道的(例如,使用 egur 建议的 memcpy)。我认为重要的优化是如何优化THIS BIT标记的循环。也许所有这些交换整数都可以更简洁地编程,而无需 for 循环。

谢谢,

4

2 回答 2

0

将所有更改% 255& 0xff,更快:

i = (i + 1) % 256;

至:

i = (i + 1) & 0xFF;

编辑:

您正在浪费大量时间初始化sbox. 您应该将sbox作为参数传递给转换函数,以便在调用之间更新原始副本。你现在正在做的是一次又一次地初始化它,每次它都需要更长的时间,因为 startPosition 增长。

void transform(char *in, char *out,
           long length,
           unsigned char* sbox)

临时的sbox应该是MyStream类的成员。读取功能应该是:

MyStream&
MyStream::read(char * const buf, std::streamsize const n)
{
    std::ios_base::streamoff start = m_stream.tellg();
    std::vector<char> in;
    in.resize(n);
    (void)m_stream.read(&in.front(), n);

    // init m_TempSbox on first call
    if (m_FirstCall) {
        initTempSbox();
    }

    m_byteTransformer->transform(&in.front(), buf, n, m_TempSbox);
    return *this;
}    
于 2014-01-14T11:52:37.760 回答
0

经过一番研究,事实证明随机访问 RC4 的密钥流是不可能的。请参阅此链接的讨论:crypto.stackexchange。一个更好的选择(正如 Rossum 在他的评论中指出的那样)是在计数器模式下使用分组密码。

您在计数器模式下所做的是加密一系列数字。这个序列是增量的,是整​​个数据流的长度。因此,假设您想使用 64 位(8 字节)分组密码加密从原始数据流的“16”位置开始的 8 字节数据。

由于您一次操作超过 8 个字节的纯文本,因此需要对 8 个字节进行加密。由于我们想要随机偏移到的位置是 16,我们基本上加密了这个数字序列的“块 3”(字节 0 到 7 == 块 1,字节 8 到 15 == 块 2,字节 16 到 23 == 块 3等等...)

例如,使用 XTEA 算法使用 128 位密钥加密 8 字节块,我们将执行以下操作:

区块 3:

// create a plain text number sequence 
uint8_t plainText[8];
plainText[0] = 16;
plainText[1] = 17;
.
.
.
plainText[7] = 23;

// encrypt the number sequence
uint8_t cipherText[8];
applyXTEATransformation(plainText, cipherText, keyOfLength128Bit);

// use the encrypted number sequence as a 
// key stream on the data to be encrypted
transformedData[16] = dataToBeEncrypted[16] ^ cipherText[0];
transformedData[17] = dataToBeEncrypted[17] ^ cipherText[1];
.
. 
.
transformedData[23] = dataToBeEncrypted[23] ^ cipherText[7];

tldr:我想在 RC4 上进行随机访问,但发现这是不可能的,所以在 XTEA 块密码上使用了计数器模式。

于 2014-01-20T10:59:21.457 回答