使用Crypto+解密时,原始文本末尾的Gargage冗余字符+; 我使用Cito T++,CTR模式,对C++中的文本进行加密和解密。一切似乎都运转了99%。加密成功后,解密也会返回原始文本,但我在解密文本的末尾提供了一些额外的随机垃圾冗余文本,如“ð”。每次我运行代码时,都会随机生成这个额外的部分。我的代码有问题吗

使用Crypto+解密时,原始文本末尾的Gargage冗余字符+; 我使用Cito T++,CTR模式,对C++中的文本进行加密和解密。一切似乎都运转了99%。加密成功后,解密也会返回原始文本,但我在解密文本的末尾提供了一些额外的随机垃圾冗余文本,如“ð”。每次我运行代码时,都会随机生成这个额外的部分。我的代码有问题吗,c++,encryption,crypto++,C++,Encryption,Crypto++,将字符串加密为字符串 string encryptString(string plain, byte key[], int sizeKey, byte iv[], int sizeIV){ string cipher; try{ CTR_Mode< AES >::Encryption e; e.SetKeyWithIV(key, sizeKey, iv, sizeIV); // The StreamTransform


将字符串加密为字符串

string  encryptString(string plain, byte key[], int sizeKey, byte iv[], int sizeIV){
    string cipher;
    try{
        CTR_Mode< AES >::Encryption e;
        e.SetKeyWithIV(key, sizeKey, iv, sizeIV);

        // The StreamTransformationFilter removes
        //  padding as required.
        StringSource s(plain, true,
            new StreamTransformationFilter(e,
                new StringSink(cipher)
                ) 
            ); 

#if 0
        StreamTransformationFilter filter(e);
        filter.Put((const byte*)plain.data(), plain.size());
        filter.MessageEnd();

        const size_t ret = filter.MaxRetrievable();
        cipher.resize(ret);
        filter.Get((byte*)cipher.data(), cipher.size());
#endif
        return cipher;
    }
    catch (const CryptoPP::Exception& e)
    {
        cerr << e.what() << endl;
        return NULL;
    }
}
string  decryptString(string cipher, byte key[], int sizeKey, byte iv[], int sizeIV){
    string reco ="";
    try{
        CTR_Mode< AES >::Decryption d;
        d.SetKeyWithIV(key, sizeKey, iv, sizeIV);

        StringSource s(cipher, true,
            new StreamTransformationFilter(d,
                new StringSink(reco)
                ) 
            ); 

    }
    catch (const CryptoPP::Exception& e)
    {
        cerr << e.what() << endl;
    }
    return reco;

}
上面的换行解密字符串函数

char* encrypt(char * plainText, byte key[], int sizeKey, byte iv[], int sizeIV, long &len){
    string cipher = encryptString(plainText, key, sizeKey, iv, sizeIV);
    len = cipher.size() + 1;
    char * writable = new  char[len];
    std::copy(cipher.begin(), cipher.end(), writable);
    writable[len] = '\0'; // don't forget the terminating 0
    return writable;
 }
char* decrypt(char * cipher,  byte key[], int sizeKey, byte iv[], int sizeIV, long len){
    string ss(cipher, len);
    long lengSS = ss.length();
    string recovered = decryptString(ss, key, sizeKey, iv, sizeIV);
    char * writable = new char[recovered.size() + 1];
    std::copy(recovered.begin(), recovered.end(), writable);
    writable[recovered.size()] = '\0'; // don't forget the terminating 0
    return writable;
}
我的测试脚本很简单。阅读some.txt内容(“我爱你”),将其写入s1.txt以检查阅读是否正确。加密、解密,然后将恢复的文本写入另一个文件(d1.txt)


只需分配writeable的长度=密码的长度。将终止符设置为
writeble[len]

,这在出现缓冲区溢出和未终止字符串等情况时很容易发生。如果我们查看您的
encrypt
函数,就会发现缓冲区溢出:

len = cipher.size() + 1;
char * writable = new  char[len];
std::copy(cipher.begin(), cipher.end(), writable);
writable[len] = '\0';
请参见此处分配的
len
字节,其中
len
cipher
大一个。但是当您终止字符串时,您正在使用
len
来索引超出范围的内容


应该使用
len-1
cipher.size()
作为终止符索引。

当出现缓冲区溢出和未终止字符串等情况时,往往会发生这种情况。如果我们查看您的
encrypt
函数,就会发现缓冲区溢出:

len = cipher.size() + 1;
char * writable = new  char[len];
std::copy(cipher.begin(), cipher.end(), writable);
writable[len] = '\0';
请参见此处分配的
len
字节,其中
len
cipher
大一个。但是当您终止字符串时,您正在使用
len
来索引超出范围的内容

您应该使用
len-1
cipher.size()
作为终止符索引

您还可以避免
加密字符串
解密字符串
以及额外的副本。我将向您展示
加密
解密
类似

char* encrypt(char * plainText, byte key[], int sizeKey, byte iv[], int sizeIV, long &len)
{
    const unsigned long plainTextLen = len; len = 0;
    const unsigned long extraLen = plainTextLen+16;

    ArraySource source(plainText, plainTextLen, false);
    unique_ptr<char[]> writable(new char[extraLen]);
    ArraySink sink(writable, extraLen);

    CTR_Mode< AES >::Encryption enc;
    enc.SetKeyWithIV(key, sizeKey, iv, sizeIV);

    source.Detach(new StreamTransformationFilter(enc, new Redirector(sink)));
    source.PumpAll();

    len = sink.TotalPutLength();
    return writable.release();
}
char*加密(char*明文、字节密钥[]、int-sizeKey、byte-iv[]、int-sizeIV、long&len)
{
常量无符号长明文len=len;len=0;
const unsigned long extraLen=plainTextLen+16;
ArraySource源(纯文本、纯文本、假);
唯一可写(新字符[extraLen]);
阵列链路接收器(可写,外部);
CTR_模式::加密enc;
enc.SetKeyWithIV(键,sizeKey,iv,sizeIV);
分离(新的StreamTransformationFilter(enc,新的重定向器(接收器));
source.PumpAll();
len=sink.TotalPutLength();
返回writable.release();
}
我没有编译并运行它,因此您必须清除上面代码中的编译器问题。它们都应该是次要的,比如转换和转换

您通常不需要担心
NULL
;只需使用
ptr
len
。您可以使用
string recovered=string(ptr,len)从解密的密文创建
std::string
<需要时,code>std::string
将生成一个
NULL
,但通常不需要

Detach
不是打字错误。您可以使用它来
附加
新过滤器和
删除
以前的过滤器。您可以使用它来避免内存泄漏

您还可以避免
加密字符串
解密字符串
以及额外的副本。我将向您展示
加密
解密
类似

char* encrypt(char * plainText, byte key[], int sizeKey, byte iv[], int sizeIV, long &len)
{
    const unsigned long plainTextLen = len; len = 0;
    const unsigned long extraLen = plainTextLen+16;

    ArraySource source(plainText, plainTextLen, false);
    unique_ptr<char[]> writable(new char[extraLen]);
    ArraySink sink(writable, extraLen);

    CTR_Mode< AES >::Encryption enc;
    enc.SetKeyWithIV(key, sizeKey, iv, sizeIV);

    source.Detach(new StreamTransformationFilter(enc, new Redirector(sink)));
    source.PumpAll();

    len = sink.TotalPutLength();
    return writable.release();
}
char*加密(char*明文、字节密钥[]、int-sizeKey、byte-iv[]、int-sizeIV、long&len)
{
常量无符号长明文len=len;len=0;
const unsigned long extraLen=plainTextLen+16;
ArraySource源(纯文本、纯文本、假);
唯一可写(新字符[extraLen]);
阵列链路接收器(可写,外部);
CTR_模式::加密enc;
enc.SetKeyWithIV(键,sizeKey,iv,sizeIV);
分离(新的StreamTransformationFilter(enc,新的重定向器(接收器));
source.PumpAll();
len=sink.TotalPutLength();
返回writable.release();
}
我没有编译并运行它,因此您必须清除上面代码中的编译器问题。它们都应该是次要的,比如转换和转换

您通常不需要担心
NULL
;只需使用
ptr
len
。您可以使用
string recovered=string(ptr,len)从解密的密文创建
std::string
<需要时,code>std::string
将生成一个
NULL
,但通常不需要


Detach
不是打字错误。您可以使用它来
附加
新过滤器和
删除
以前的过滤器。您可以使用它来避免内存泄漏。

谢谢您的回答。我做了两个更改:第一,allocate writeable=new char[len];第二,可写[len]='\0'。它现在起作用了:)谢谢你的回答。我做了两个更改:第一,allocate writeable=new char[len];第二,可写[len]='\0'。它现在工作:)我用Visual C++测试你的加密()函数,在AraySink接收器(可写,Exelaln)中出现语法错误;因为可写是char[],当sink()需要字节*type@Andiana-“我没有编译并运行它,因此您必须清除上面代码中的编译器问题。它们都应该是次要的,比如转换和强制转换”。将
字符*
转换为
字节*
;然后将
const char*
转换为
const byte*
。我对unique\u ptr有点困惑,它似乎是最好的解决方案,而不是char*或string,但我不知道在这种情况下如何使用它。我是否使用writeble.get()获取了它的数据?@Andiana-我很抱歉,我一直试图提供的帮助没有帮助。在继续使用加密+库之前,也许你应该了解更多关于C++的内容。我用VisualC++来测试你的加密()函数,在AraySink接收器(可写,Exelaln)中出现语法错误;因为可写是char[],当sink()需要字节*type@Andia
char* encrypt(char * plainText, byte key[], int sizeKey, byte iv[], int sizeIV, long &len)
{
    const unsigned long plainTextLen = len; len = 0;
    const unsigned long extraLen = plainTextLen+16;

    ArraySource source(plainText, plainTextLen, false);
    unique_ptr<char[]> writable(new char[extraLen]);
    ArraySink sink(writable, extraLen);

    CTR_Mode< AES >::Encryption enc;
    enc.SetKeyWithIV(key, sizeKey, iv, sizeIV);

    source.Detach(new StreamTransformationFilter(enc, new Redirector(sink)));
    source.PumpAll();

    len = sink.TotalPutLength();
    return writable.release();
}