2013-11-29 1 views
0

Так что я пытаюсь использовать шифрование Crypto ++ в проекте Objective-C. Проблема в том, что делать с IV? Я пытаюсь предварительно добавить его в зашифрованный текст. Но тогда у меня проблемы с его восстановлением для дешифрования.Crypto ++ что делать с IV

Вот код:

- (NSString *)encryptUsingSerpentWithPlaintext:(NSString *)plaintext andKey:(NSData *)keyData 
{ 
    std::string ptext = [plaintext UTF8String]; 
    std::string ciphertext; 

    byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ]; 

    CryptoPP::AutoSeededX917RNG<CryptoPP::Serpent> rng; 
    rng.GenerateBlock(iv, CryptoPP::Serpent::BLOCKSIZE); 

    std::string ivs(reinterpret_cast<char const *>(iv)); 
    lcl_log(lcl_cCrypto, lcl_vDebug, @"Random IV:%s",ivs.c_str()); 


    ::memcpy(key, keyData.bytes, keyData.length); 


    CryptoPP::Serpent::Encryption serpentEncryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH); 
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcSerpentEncryptor (serpentEncryptor, iv); 

    CryptoPP::StreamTransformationFilter stfSerpentEncryptor(cbcSerpentEncryptor, new CryptoPP::StringSink (ciphertext)); 
    stfSerpentEncryptor.Put(reinterpret_cast<const unsigned char*>(ptext.c_str()), ptext.length() + 1); 
    stfSerpentEncryptor.MessageEnd(); 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"Non-Encoded ciphertext [size:%lu]:%s",sizeof(ciphertext),ciphertext.c_str()); 

    std::string finalCT; 

    ciphertext = ivs + ciphertext; // add the IV before the ciphertext 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"Non-Encoded iv+ciphertext [size:%lu]:%s",sizeof(ciphertext),ciphertext.c_str()); 

    CryptoPP::StringSource base64Encoder (ciphertext, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(finalCT))); 

    // apply HMAC 
    // TO DO 

    NSString *cryptogram = [NSString stringWithUTF8String:finalCT.c_str()]; 

    return cryptogram; 
} 

- (NSString *)decryptUsingSerpentWithCiphertext:(NSString *)ciphertext andKey:(NSData *)keyData 
{ 
    std::string ctext; 
    std::string plaintext; 

    byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ]; 

    ::memcpy(key, keyData.bytes, keyData.length); 

    // decode from base64 
    std::string encoded = [ciphertext UTF8String]; 
    CryptoPP::StringSource base64Decoder (encoded, true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(ctext))); 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"Non-Encoded iv+ciphertext [size:%lu]:%s",sizeof(ctext),ctext.c_str()); 

    // get the IV from the beggining of the cryptogram 
    std::string ivs = ctext.substr(0,CryptoPP::Serpent::BLOCKSIZE+5); 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"Recovered IV:%s",ivs.c_str()); 

    ::memcpy(iv, &ivs, ivs.size()); 

    // remove the IV from the cryptogram 

    ctext.erase(0,CryptoPP::Serpent::BLOCKSIZE+5); 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"Non-Encoded ciphertext [size:%lu]:%s",sizeof(ctext),ctext.c_str()); 


    CryptoPP::Serpent::Decryption serpentDecryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH); 
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcSerpentDecryptor (serpentDecryptor, iv); 

    CryptoPP::StreamTransformationFilter stfSerpentDecryptor(cbcSerpentDecryptor, new CryptoPP::StringSink (plaintext)); 
    stfSerpentDecryptor.Put(reinterpret_cast<const unsigned char*>(ctext.c_str()), ctext.length()); 
    stfSerpentDecryptor.MessageEnd(); 

    NSString *plainText = [NSString stringWithUTF8String:plaintext.c_str()]; 

    return plainText; 
} 

Обратите внимание, мне нужно добавить 5 к ожидаемому размеру внутривенной, чтобы получить полный IV. И затем я получаю сообщение об ошибке «Недействительный номер PCKS # 7, найденный. Invalid ciphertext»

Как лучше всего управлять IV? (Я хотел бы также добавить HMAC в IV + шифротекста (шифровать-то-MAC) ...

Если бы я это сделать:

// get the IV from the beggining of the cryptogram 
std::string ivs = ctext.substr(0,CryptoPP::Serpent::BLOCKSIZE); 

lcl_log(lcl_cCrypto, lcl_vDebug, @"Recovered IV:%s",ivs.c_str()); 

::memcpy(iv, &ivs, ivs.size()); 

// remove the IV from the cryptogram 

ctext.erase(0,CryptoPP::Serpent::BLOCKSIZE); 

Журналы покажет ряд IV байтов еще в шифротексте, и создать «недопустимый шифротекст, размер не является кратным размера блока» исключение

Журналы:.

2013-12-01 17:59:37.747 App[413:70b] D Crypto:PSCryptoCore.mm:51:-[PSCryptoCore testSerpentEncryptonMechanism] Initial plaintext:Serpentine and black... 
2013-12-01 17:59:37.748 App[413:70b] D Crypto:PSCryptoCore.mm:74:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Random IV:ç©ìùËß,¬<ÎΩ9ZÑ0 Û 
2013-12-01 17:59:37.749 App[413:70b] D Crypto:PSCryptoCore.mm:87:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Non-Encoded ciphertext [size:4]:PÉò»ÓÔҥ 1æIõ¶”Áˆ™8äºBmº†c 
õ 
2013-12-01 17:59:37.749 App[413:70b] D Crypto:PSCryptoCore.mm:93:-[PSCryptoCore encryptUsingSerpentWithPlaintext:andKey:] Non-Encoded iv+ciphertext [size:4]:ç©ìùËß,¬<ÎΩ9ZÑ0 ÛPÉò»ÓÔҥ 1æIõ¶”Áˆ™8äºBmº†c 
õ 
2013-12-01 17:59:37.750 App[413:70b] D Crypto:PSCryptoCore.mm:54:-[PSCryptoCore testSerpentEncryptonMechanism] ciphertext:C42pk53opyzCPOu9FDlahDAg8wgBUIOYyO7M0/G0IDG+SZum0+f2qjiKvA4RQm28HaBjCps= 
2013-12-01 17:59:37.750 App[413:70b] D Crypto:PSCryptoCore.mm:118:-[PSCryptoCore decryptUsingSerpentWithCiphertext:andKey:] Non-Encoded iv+ciphertext [size:4]:ç©ìùËß,¬<ÎΩ9ZÑ0 ÛPÉò»ÓÔҥ 1æIõ¶”Áˆ™8äºBmº†c 
õ 
2013-12-01 17:59:37.752 App[413:70b] D Crypto:PSCryptoCore.mm:123:-[PSCryptoCore decryptUsingSerpentWithCiphertext:andKey:] Recovered IV:ç©ìùËß,¬<ÎΩ9ZÑ 
2013-12-01 17:59:37.753 App[413:70b] D Crypto:PSCryptoCore.mm:131:-[PSCryptoCore decryptUsingSerpentWithCiphertext:andKey:] Non-Encoded ciphertext [size:4]:0 ÛPÉò»ÓÔҥ 1æIõ¶”Áˆ™8äºBmº†c 
õ 
libc++abi.dylib: terminating with uncaught exception of type CryptoPP::InvalidCiphertext: StreamTransformationFilter: ciphertext length is not a multiple of block size 

Обратите внимание, что часть IV все еще впереди шифротекста после стараюсь retireve i t .. Почему это?

ответ

4

Превращение IV вправо. Почему вы добавляете 5 к блокам? Декодирование с базы-64 на данные. Вытяните первые BLOCKSIZE байты как IV. Расшифруйте остаток.

+0

Я сделал именно то, что ... не работает ... Я добавляю 5 байтов, потому что он оставляет 5 байт IV, все еще добавленных к шифру. Я обновлю вопрос – user1028028

+0

Возможно, я не делаю «вытащить первые байты BLOCKSIZE как IV» правильно ... – user1028028

+0

Лучший способ отладить это - вывести свой IV и зашифрованный текст в ваш шифр (перед тем как положить их вместе). Затем выведите их в свой дешифратор. Разумеется, они должны быть одинаковыми. Это скажет вам, запутываете ли вы кодирование/декодирование, concat, split и т. Д. Разделение этого кода на мелкие кусочки может сделать его намного проще для тестирования. –

0

Мне удалось это исправить. Это код

- (NSString *)encryptUsingSerpentWithPlaintext:(NSString *)plaintext andKey:(NSData *)keyData 
{ 
    std::string ptext = [plaintext UTF8String]; 
    std::string ciphertext; 

    byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ]; 

    CryptoPP::AutoSeededX917RNG<CryptoPP::Serpent> rng; 
    rng.GenerateBlock(iv, CryptoPP::Serpent::BLOCKSIZE); 

    std::string ivs(reinterpret_cast<char const *>(iv)); 
    lcl_log(lcl_cCrypto, lcl_vDebug, @"Random IV:%s",ivs.c_str()); 


    ::memcpy(key, keyData.bytes, keyData.length); 


    CryptoPP::Serpent::Encryption serpentEncryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH); 
    CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcSerpentEncryptor (serpentEncryptor, iv); 

    CryptoPP::StreamTransformationFilter stfSerpentEncryptor(cbcSerpentEncryptor, new CryptoPP::StringSink (ciphertext),CryptoPP::StreamTransformationFilter::BlockPaddingScheme::ONE_AND_ZEROS_PADDING); 
    stfSerpentEncryptor.Put(reinterpret_cast<const unsigned char*>(ptext.c_str()), ptext.length() + 1); 
    stfSerpentEncryptor.MessageEnd(); 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"Non-Encoded ciphertext [size:%lu]:%s",sizeof(ciphertext),ciphertext.c_str()); 

    std::string finalCT; 

    CryptoPP::StringSource base64Encoder (ciphertext, true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(finalCT))); 

    std::string ivB64; 

    CryptoPP::StringSource base64IVEncoder (ivs , true, new CryptoPP::Base64Encoder(new CryptoPP::StringSink(ivB64))); 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"IV base64[size:%lu]:%s",ivB64.length(),ivB64.c_str()); 

    finalCT = ivB64 + finalCT; 

    lcl_log(lcl_cCrypto, lcl_vDebug, @"Cryptogram:%s",finalCT.c_str()); 

    // apply HMAC 
    // TO DO 

    NSString *cryptogram = [NSString stringWithUTF8String:finalCT.c_str()]; 

    return cryptogram; 
} 

- (NSString *)decryptUsingSerpentWithCiphertext:(NSString *)ciphertext andKey:(NSData *)keyData 
{ 
    std::string ctext; 
    std::string plaintext; 

    byte key[ CryptoPP::Serpent::MAX_KEYLENGTH ], iv[ CryptoPP::Serpent::BLOCKSIZE ]; 

    ::memcpy(key, keyData.bytes, keyData.length); 

    // decode from base64 
    std::string encoded = [ciphertext UTF8String]; 

    // pull IV from ciphertext 
    std::string ivs = encoded.substr(0,29); 
    encoded.erase(0,29); 

    CryptoPP::StringSource base64Decoder (encoded, true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(ctext))); 

    std::string iv_tmp; 
    CryptoPP::StringSource base64IVDecoder (ivs, true, new CryptoPP::Base64Decoder(new CryptoPP::StringSink(iv_tmp))); 



    lcl_log(lcl_cCrypto, lcl_vDebug, @"Recovered IV[encoded]:%s",ivs.c_str()); 

    ::memcpy(iv, iv_tmp.data(), CryptoPP::Serpent::BLOCKSIZE); 



    CryptoPP::Serpent::Decryption serpentDecryptor (key, CryptoPP::Serpent::MAX_KEYLENGTH); 
    CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcSerpentDecryptor (serpentDecryptor, iv); 

    CryptoPP::StreamTransformationFilter stfSerpentDecryptor(cbcSerpentDecryptor, new CryptoPP::StringSink (plaintext), CryptoPP::StreamTransformationFilter::BlockPaddingScheme::ONE_AND_ZEROS_PADDING); 
    stfSerpentDecryptor.Put(reinterpret_cast<const unsigned char*>(ctext.c_str()), ctext.length()); 
    stfSerpentDecryptor.MessageEnd(); 

    NSString *plainText = [NSString stringWithUTF8String:plaintext.c_str()]; 

    return plainText; 
} 

я заметил, что IV в Base64 имеет длину 29 ... Я не уверен, что это всегда так .. может быть, для некоторых других 16 байт IV длины строки base64 отличается?

+0

29 байтов слишком длинны для кодировки Base64 16 байт. Base64 принимает байты ceil (4n/3) (+ дополнительный) для кодирования n байтов. Таким образом, 16 байтов будут принимать либо 22 (незаполненные), либо 24 (дополненные) байты. –

+0

Я понятия не имею, почему ... но строка IV - 29 символов – user1028028