如何在CTR模式下寻求并解密部分流? [英] How to seek in CTR mode and decrypt part of the stream?

查看:181
本文介绍了如何在CTR模式下寻求并解密部分流?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在cryptopp中有部分解码的问题。
使用AES 256 CTR;



编码源:

  CTR_Mode< AES> ::加密e 
e.SetKeyWithIV(key,32,iv);
字符串加密;
string a =示例文本到编码;
encrypt.clear();
StringSource s(a,true,
new StreamTransformationFilter(e,
new StringSink(encrypt)

);

解码源:

  CTR_Mode< AES> :: Decryption d; 
d.SetKeyWithIV(key,32,iv);
string x;

StringSource s1(encrypt,true,
new StreamTransformationFilter(d,
new StringSink(x)

);

它工作正常。但是我不知道解密只是一部分。例如, encrypt.begin()+ 10



部分解码:

  CTR_Mode< AES> :: Decryption d; 
d.SetKeyWithIV(key,32,iv);
d.DiscardBytes(5); //位跳过
string todecrypt = encrypt.substr(5,10); //加密邮件的一部分
string x;

StringSource s1(todecrypt,true,
new StreamTransformationFilter(d,
new StringSink(x)

);


解决方案


CTR模式并解密部分流?


使用 Crypto ++管道是一个有点尴尬,因为 放弃跳过无法正常工作。在目前的实现中,您必须将 Pump data into nothing。另请参阅在源代码上跳过不按预期方式堆栈溢出。



以下是使用AES / CTR并在流中查找的示例。它需要执行两部分寻求。首先,它丢弃 Source 中称为 cipher 的字节。第二,它寻求加密对象名为 enc 的密钥流来同步计数器。一旦执行了搜索,则通过调用 PumpAll()来解密其余的密文,通过管道抽取剩余的数据。

  #includemodes.h
#includeaes.h
使用命名空间CryptoPP ;

int main(int argc,char * argv [])
{
string plain =现在是所有好男人来到他们国家的旁边的时候 ;

byte key [AES :: DEFAULT_KEYLENGTH] = {0};
byte nonce [AES :: BLOCKSIZE] = {0};

CTR_Mode< AES> ::加密enc;
enc.SetKeyWithIV(key,sizeof(key),nonce,sizeof(nonce));

string cipher;
StringSource ss1(plain,true,new StreamTransformationFilter(enc,new StringSink(cipher)));

for(size_t i = 0; i< cipher.size(); i ++)
{
CTR_Mode< AES> :: Decryption dec;
dec.SetKeyWithIV(key,sizeof(key),nonce,sizeof(nonce));

StringSource ss2(cipher,false);
ss2.Pump(i);
dec.Seek(i);

string recover;
StreamTransformationFilter stf(dec,new StringSink(recover));

//寻求
ss2.Attach(new Redirector(stf))后附加解密过滤器;
ss2.PumpAll();

cout<<< i< :<<恢复< ENDL;
}

return 0;
}

结果如下:

  $ ./test.exe 
0:现在是所有好男人来到他们国家的助手的时候
1:ow是所有好男人来到他们国家的时间的时候
2:w是所有好男人来到他们国家的旁边的时间
3:是所有好人的时间都来到他们国家的助手
4:所有好人都来到他们国家的助手的时候
5:所有好人都来的时候他们国家的助手
6:所有好男人来到他们国家的助手的时间
7:所有好男人来到他们国家的时间
8他所有的好人都要来到他们国家的助手
9:所有的好人都可以来到他们的国家的旁边
10:所有的好人都来的时候他们的国家的助手
11:所有好人的时间来到这里eir country
12:ime为所有的好男人来到他们的国家的助手
13:我所有的好男人来到他们的国家的助手
14:e为所有好男人来到他们国家的助手
15:所有的好人都来到他们的国家的助手
16:所有的好人都来到他们的国家的助手
17 :或所有的好人来到他们的国家的助手
18:所有的好人来到他们的国家的助手
19:所有的好人来到他们的国家的助手
20:所有好男人来到他们国家的助手
21:好男人来到他们的国家的助手
22:l好人来到他们国家的助手
23:好人来到他们国家的助手
24:好人来到他们的国家的助手
25:男人来到他们的国家的助手
26:od男人来到他们国家的助手
27:男人来到他们国家的助手
28:男人来到他们的国家
29:男人来到他们国家的助手
30:en来到他们国家的助手
31:n来到他们国家的助手
32:来到他们国家的助手
33:来到他们国家的助手
34:o来到他们国家的助手
35:来到他们的国家
36:来到他们的国家的助手
37:对他们国家的助手
38:我到他们国家的助手
39:e他们国家的助手
40:他们国家的助手
41:他们国家的助手
42:o他们国家的助手
43:他们的助手国家
44:他们国家的助手
45:他的国家的助手
46:他们国家的助手
47:他们国家的助手
48:他们国家的助手
49:他们国家的理想
50:他们国家的
51:他们国家的e
52:他们的国家
53:of他们的国家
54:f他们的国家
55:他们的国家
56:他们的国家
57:继承人国家
58:eir国家
59:ir国家
60:r国家
61:国家
62:country
63:ountry
64:untry
65:ntry
66:try
67:ry
68:y






现在你已经看到了一般模式,您的数据集使用范围 [5,10] 的修改。



您不必须调用 stf.MessageEnd(),因为恢复的文本在XOR执行后立即就绪。其他模式可能需要调用 MessageEnd()。另请参阅Crypto ++ wiki上的 Init-Update-Final

  StringSource ss2(cipher,false); 
ss2.Pump(5);
dec.Seek(5);

string recover;
StreamTransformationFilter stf(dec,new StringSink(recover));

//寻求
ss2.Attach(new Redirector(stf))后附加解密过滤器;
ss2.Pump(10 - 5 + 1);

cout<<< '<恢复< '< ENDL;

它产生:

  $ ./test.exe 
的'

这里还有一点:

  StringSource ss2(cipher,false) ; 
ss2.Pump(5);
dec.Seek(5);

string recover;
StreamTransformationFilter stf(dec,new StringSink(recover));

//寻求
ss2.Attach(new Redirector(stf))后附加解密过滤器;
ss2.Pump(10 - 5 + 1);

cout<<< '<恢复< '< ENDL;

ss2.Pump(1);

cout<<< '<恢复< '< ENDL;

ss2.Pump(1);

cout<<< '<恢复< '< ENDL;

它产生:

  $ ./test.exe 
''
'''
'''
' / code>






以前我说使用 Crypto ++ Pipeline 是一个有点尴尬的。这是我们要做的,但我们现在不能:

  StringSource ss(加密,错误,新的StreamTransformationFilter(dec,new StringSink(x))); 
ss.Skip(5); //丢弃字节并同步流
ss.Pump(5); // Process bytes [5,10]

cout<<< x< ENDL;






关于Rob的评论你必须解密一个整个16字节的块... - 如果您正在使用其他模式,如CBC模式,则必须处理上述明文或密文;你必须在块上操作。 CBC模式及其链接属性需要它。



然而,点击率的设计略有不同。它的设计是可寻求的,它允许你在流中跳跃。在这方面,它很像OFB模式。 (CTR模式和OFB模式在生成密钥流的方式上有所不同,但是使用纯文本或密文XOR密钥流)。


I have a question in partial decoding in cryptopp. USE AES 256 CTR;

Encode source:

CTR_Mode< AES >::Encryption e;
e.SetKeyWithIV(key, 32, iv);
string encrypt;
string a = "Example text to encoding";
encrypt.clear();
StringSource s(a, true,
    new StreamTransformationFilter(e,
        new StringSink(encrypt)
    )
);

Decode source:

CTR_Mode<AES>::Decryption d;
d.SetKeyWithIV(key, 32, iv);
string x;

StringSource s1(encrypt, true,
    new StreamTransformationFilter(d,
        new StringSink(x)
    )
);

It works fine. But I don't know how decrypt only part. For example, example encrypt.begin()+10

Part Decode:

CTR_Mode<AES>::Decryption d;
d.SetKeyWithIV(key, 32, iv);
d.DiscardBytes(5);  //bit to skip
string todecrypt = encrypt.substr(5,10); // part of encrypted message
string x;

StringSource s1(todecrypt, true,
    new StreamTransformationFilter(d,
        new StringSink(x)
    )
);

解决方案

How to seek in CTR mode and decrypt part of the stream?

Using a Crypto++ Pipeline is a tad bit awkward because Discard or Skip on a Source does not work as expected. You have to Pump data into "nothing" under the current implementation. Also see Skip'ing on a Source does not work as expected on Stack Overflow.

Below is an example of using AES/CTR and seeking in the stream. It needs to perform a "two part" seek. First, it discards bytes on the Source called cipher. Second, it seeks in the keystream on the encryption object called enc to synchronize the counter. Once the seek is performed, the remainder of the cipher text is decrypted by calling PumpAll(), which pumps the remainder of the data through the pipeline.

#include "modes.h"
#include "aes.h"
using namespace CryptoPP;

int main(int argc, char* argv[])
{
    string plain = "Now is the time for all good men to come to the aide of their country";

    byte key[AES::DEFAULT_KEYLENGTH] = {0};
    byte nonce[AES::BLOCKSIZE] = {0};

    CTR_Mode<AES>::Encryption enc;
    enc.SetKeyWithIV(key, sizeof(key), nonce, sizeof(nonce));

    string cipher;
    StringSource ss1(plain, true, new StreamTransformationFilter(enc, new StringSink(cipher)));

    for(size_t i=0; i<cipher.size(); i++)
    {   
        CTR_Mode<AES>::Decryption dec;
        dec.SetKeyWithIV(key, sizeof(key), nonce, sizeof(nonce));

        StringSource ss2(cipher, false);
        ss2.Pump(i);
        dec.Seek(i);

        string recover;
        StreamTransformationFilter stf(dec, new StringSink(recover));

        // Attach the decryption filter after seeking
        ss2.Attach(new Redirector(stf));
        ss2.PumpAll();

        cout << i << ": " << recover << endl;
    }

    return 0;
}

Here is the result:

$ ./test.exe 
0: Now is the time for all good men to come to the aide of their country
1: ow is the time for all good men to come to the aide of their country
2: w is the time for all good men to come to the aide of their country
3:  is the time for all good men to come to the aide of their country
4: is the time for all good men to come to the aide of their country
5: s the time for all good men to come to the aide of their country
6:  the time for all good men to come to the aide of their country
7: the time for all good men to come to the aide of their country
8: he time for all good men to come to the aide of their country
9: e time for all good men to come to the aide of their country
10:  time for all good men to come to the aide of their country
11: time for all good men to come to the aide of their country
12: ime for all good men to come to the aide of their country
13: me for all good men to come to the aide of their country
14: e for all good men to come to the aide of their country
15:  for all good men to come to the aide of their country
16: for all good men to come to the aide of their country
17: or all good men to come to the aide of their country
18: r all good men to come to the aide of their country
19:  all good men to come to the aide of their country
20: all good men to come to the aide of their country
21: ll good men to come to the aide of their country
22: l good men to come to the aide of their country
23:  good men to come to the aide of their country
24: good men to come to the aide of their country
25: ood men to come to the aide of their country
26: od men to come to the aide of their country
27: d men to come to the aide of their country
28:  men to come to the aide of their country
29: men to come to the aide of their country
30: en to come to the aide of their country
31: n to come to the aide of their country
32:  to come to the aide of their country
33: to come to the aide of their country
34: o come to the aide of their country
35:  come to the aide of their country
36: come to the aide of their country
37: ome to the aide of their country
38: me to the aide of their country
39: e to the aide of their country
40:  to the aide of their country
41: to the aide of their country
42: o the aide of their country
43:  the aide of their country
44: the aide of their country
45: he aide of their country
46: e aide of their country
47:  aide of their country
48: aide of their country
49: ide of their country
50: de of their country
51: e of their country
52:  of their country
53: of their country
54: f their country
55:  their country
56: their country
57: heir country
58: eir country
59: ir country
60: r country
61:  country
62: country
63: ountry
64: untry
65: ntry
66: try
67: ry
68: y


Now that you've seen the general pattern, here are the modifications for your dataset using the range [5,10].

You do not have to call stf.MessageEnd() because recovered text is ready as soon as the XOR is preformed. Others modes may need the call to MessageEnd(). Also see Init-Update-Final on the Crypto++ wiki.

StringSource ss2(cipher, false);
ss2.Pump(5);
dec.Seek(5);

string recover;
StreamTransformationFilter stf(dec, new StringSink(recover));

// Attach the decryption filter after seeking
ss2.Attach(new Redirector(stf));
ss2.Pump(10 - 5 + 1);

cout << "'" << recover << "'" << endl;

It produces:

$ ./test.exe 
's the '

And here's a little more:

StringSource ss2(cipher, false);
ss2.Pump(5);
dec.Seek(5);

string recover;
StreamTransformationFilter stf(dec, new StringSink(recover));

// Attach the decryption filter after seeking
ss2.Attach(new Redirector(stf));
ss2.Pump(10 - 5 + 1);

cout << "'" << recover << "'" << endl;

ss2.Pump(1);

cout << "'" << recover << "'" << endl;

ss2.Pump(1);

cout << "'" << recover << "'" << endl;

It produces:

$ ./test.exe 
's the '
's the t'
's the ti'


Earlier I said "Using a Crypto++ Pipeline is a tad bit awkward". Here's all we want to do, but we can't at the moment:

StringSource ss(cipher, false, new StreamTransformationFilter(dec, new StringSink(x)));
ss.Skip(5); // Discard bytes and synchronize stream
ss.Pump(5); // Process bytes [5,10]

cout << x << endl;


Regarding Rob's comment "You must decrypt an entire 16-byte block..." - If you were working with another mode, like CBC mode, then you would have to process preceding plain text or cipher text; and you would have to operate on blocks. CBC mode and its chaining properties demand it.

However, CTR is designed a little differently. Its designed to be seekable, and it allows you to jump around in the stream. In this respect, its a lot like OFB mode. (CTR mode and OFB mode differ in the way they generate the keystream. But both XOR the keystream with the plain text or cipher text).

这篇关于如何在CTR模式下寻求并解密部分流?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆