I'm actually using cryptopp on android and ios, and they have dfferent crash behaviors. The android issue is in another thread, and seems related to stl.In iOS I get farther in my app, but when it comes time to do a FileSource to FileSync encryption it locks the device. Has anyone seen this?
What I do is concentrate my error checking and analysis on the desktop OSes, like OS X and Linux. Once I am satisfied the "core" logic is sound, I port it to another platform, like iOS and Android. The philosophy above means you need a clean separation between "core" and "window/ui" logic or routines. You'll get the hang of it quickly.
CFB_Mode<AES>::Encryption e((const byte *) binKey.constData(), binKey.length(), staticIv, 1);
byte iv[16];
byte bKey[32];
memcpy(iv, binIv.constData(), sizeof(iv));
memcpy(bKey, binKey.constData(), sizeof(bKey));
CFB_Mode<AES>::Encryption e(bKey, 32, iv, 1);
FileSource src((const char *)inFilename.toUtf8().constData(), true,
new StreamTransformationFilter(e, //STF
new Base64Encoder(
new FileSink((const char *)outFilename.toUtf8().constData())
, false
)
) //STF
);
Same issue. However, if I comment out the lines with //STF, so that it just removes the STF and just does a base64 encode, the code works. Which makes me think that it's specific to the STF. It is doing something because the phone gets hot. At which point I wonder if the issue is with architecture or packaging. I have created a fat library:
$ xcrun -sdk iphoneos lipo -info libcryptopp-ios.a Architectures in the fat file: libcryptopp-ios.a are: armv7 x86_64 arm64
It's running on a iPhone 4, which is the arm7 arch, the arm7s is for the iPhone 5 & 5c.
Do you have any idea why the STF would fail in this situation?
I redid the code to use simple static bytes:byte iv[16];byte bKey[32];memcpy(iv, binIv.constData(), sizeof(iv));memcpy(bKey, binKey.constData(), sizeof(bKey));CFB_Mode<AES>::Encryption e(bKey, 32, iv, 1);FileSource src((const char *)inFilename.toUtf8().constData(), true,new StreamTransformationFilter(e, //STFnew Base64Encoder(new FileSink((const char *)outFilename.toUtf8().constData()), false)) //STF);Same issue. However, if I comment out the lines with //STF, so that it just removes the STF and just does a base64 encode, the code works. Which makes me think that it's specific to the STF. It is doing something because the phone gets hot. At which point I wonder if the issue is with architecture or packaging. I have created a fat library:$ xcrun -sdk iphoneos lipo -info libcryptopp-ios.a Architectures in the fat file: libcryptopp-ios.a are: armv7 x86_64 arm64
Hmmm... I cannot duplicate it. I just tried again on iOS 6.0 and 8.1.
For iOS, I test using two jail broken devices: (1) iPad2 running 8.1 and (2) iPad3 running iOS 6.0. I cross compile it according to https://www.cryptopp.com/wiki/IOS_%28Command_Line%29 . I SCP cryptest.exe, TestVectors/ and TestData/ to the device. I then SSH into the device, and execute the tests.
Jeff
Hmmm... I cannot duplicate it. I just tried again on iOS 6.0 and 8.1.
For iOS, I test using two jail broken devices: (1) iPad2 running 8.1 and (2) iPad3 running iOS 6.0. I cross compile it according to https://www.cryptopp.com/wiki/IOS_%28Command_Line%29 . I SCP cryptest.exe, TestVectors/ and TestData/ to the device. I then SSH into the device, and execute the tests.
Jeff
You can also specify different architectures. For example, setenv-ios.sh armv7s will configure for A6 processors and the armv7s instruction set. If you want to build a fat binary (for example, both armv7 and armv7s), then its easier to open GNUMakefile and change it by hand (search for IOS_ARCH after applying the patch).
IOS never appears in the makefile, only makefile-cross.
On Monday, December 21, 2015 at 5:37:53 PM UTC-5, jh...@emocha.com wrote:
Hmmm... I cannot duplicate it. I just tried again on iOS 6.0 and 8.1.
For iOS, I test using two jail broken devices: (1) iPad2 running 8.1 and (2) iPad3 running iOS 6.0. I cross compile it according to https://www.cryptopp.com/wiki/IOS_%28Command_Line%29 . I SCP cryptest.exe, TestVectors/ and TestData/ to the device. I then SSH into the device, and execute the tests.
Jeff
1,180,504 locked
2,709,738 locked
8,727,128 locked
7,636 ok
11,429 ok
11,512 ok
11,961 ok
7,672 ok
11,460
975,913 ok (outlier)
11,600 ok
Can you repeat your tests with a lot of data? For comparison on the iPhone 4s, the ~15k files take ~44ms. The big ones, if they work (very rarely) take 17-45 seconds.
Also this instruction is confusing:You can also specify different architectures. For example, setenv-ios.sh armv7s will configure for A6 processors and the armv7s instruction set. If you want to build a fat binary (for example, both armv7 and armv7s), then its easier to open GNUMakefile and change it by hand (search for IOS_ARCH after applying the patch).
IOS never appears in the makefile, only makefile-cross.
Small amounts of data do not seem to crash it. In my app I either get a very small amount of data, or a very large amount if data. A small amount is 7-15kB. A large amount is over a 1MBData size (in bytes), result:1,180,504 locked
2,709,738 locked
8,727,128 locked
7,636 ok
11,429 ok
11,512 ok
11,961 ok
7,672 ok
11,460
975,913 ok (outlier)
11,600 ok
This might be a little closer to what you are doing:
MeterFilter* meter;
StreamTransformationFilter* stf;
FileSource fs("/dev/zero", false, stf = new StreamTransformationFilter(enc, meter = new MeterFilter(new FileSink("/dev/null"))));
unsigned int remaining = BIG_SIZE;
while(remaining)
{
if(remaining % (1024*1024) == 0)
{
cout << "Processed: " << meter->GetTotalBytes();
cout << ", Available: " << stf->MaxRetrievable() << endl;
}
const unsigned int req = STDMIN(remaining, BLOCK_SIZE);
fs.Pump(req);
remaining -= req;
}
Jeff
aesEncryptFileOpen(QString inFile, QString outFile);
aesEncryptFilePump()
is called, to start it then the GUI keeps pumping. I don't know why the MeterFilter should _ever_ crash? readLength is 65536.
void Hash::aesEncryptFileOpen(QString inFile, QString outFile) {inFilename = inFile;outFilename = outFile;QString ivHex = hashFile(inFilename, false).mid(0,32);QByteArray binIv = QByteArray::fromHex(ivHex.toUtf8());char inFilename_[256];char outFilename_[256];memset(inFilename_, 0, sizeof(inFilename_));memset(outFilename_, 0, sizeof(outFilename_));strncpy(inFilename_, inFilename.toLocal8Bit().constData(), inFilename.toLocal8Bit().length());strncpy(outFilename_, outFilename.toLocal8Bit().constData(), outFilename.toLocal8Bit().length());_fileSource = new CryptoPP::FileSource(inFilename_, false);_fileSink = new CryptoPP::FileSink(outFilename_);_meterFilter= new CryptoPP::MeterFilter();CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption e((const byte *)_key.constData(), _key.length(), (const byte *)binIv.constData(), 1);_stf = new CryptoPP::StreamTransformationFilter(e);if (_base64Output)_base64Encoder = new CryptoPP::Base64Encoder();else_base64Encoder = NULL;_fileSource->Attach(_meterFilter);_meterFilter->Attach(_stf);if (_base64Encoder) {_stf->Attach(_base64Encoder);_base64Encoder->Attach(_fileSink);} else {_stf->Attach(_fileSink);}QFileInfo fi (inFilename);totalBytesToEncrypt = fi.size();bytesEncrypted = 0;}
void Hash::aesEncryptFilePump() {qlonglong readLength = qMin(_blockSize, totalBytesToEncrypt - bytesEncrypted);bytesEncrypted += readLength - _fileSource->Pump(readLength);if (_fileSource->SourceExhausted()){aesEncryptFileClose();emit aesEncryptFileComplete(inFilename);}}
after callingaesEncryptFileOpen(QString inFile, QString outFile);aesEncryptFilePump()is called, to start it then the GUI keeps pumping. I don't know why the MeterFilter should _ever_ crash? readLength is 65536.
void Hash::aesEncryptFileOpen(QString inFile, QString outFile) {inFilename = inFile;outFilename = outFile;QString ivHex = hashFile(inFilename, false).mid(0,32);QByteArray binIv = QByteArray::fromHex(ivHex.toUtf8());char inFilename_[256];char outFilename_[256];memset(inFilename_, 0, sizeof(inFilename_));memset(outFilename_, 0, sizeof(outFilename_));strncpy(inFilename_, inFilename.toLocal8Bit().constData(), inFilename.toLocal8Bit().length());strncpy(outFilename_, outFilename.toLocal8Bit().constData(), outFilename.toLocal8Bit().length());
_fileSource = new CryptoPP::FileSource(inFilename_, false);_fileSink = new CryptoPP::FileSink(outFilename_);_meterFilter= new CryptoPP::MeterFilter();CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption e((const byte *)_key.constData(), _key.length(), (const byte *)binIv.constData(), 1);_stf = new CryptoPP::StreamTransformationFilter(e);if (_base64Output)_base64Encoder = new CryptoPP::Base64Encoder();else_base64Encoder = NULL;_fileSource->Attach(_meterFilter);_meterFilter->Attach(_stf);if (_base64Encoder) {_stf->Attach(_base64Encoder);_base64Encoder->Attach(_fileSink);} else {_stf->Attach(_fileSink);}QFileInfo fi (inFilename);totalBytesToEncrypt = fi.size();bytesEncrypted = 0;}
void Hash::aesEncryptFilePump() {qlonglong readLength = qMin(_blockSize, totalBytesToEncrypt - bytesEncrypted);bytesEncrypted += readLength - _fileSource->Pump(readLength);if (_fileSource->SourceExhausted()){aesEncryptFileClose();emit aesEncryptFileComplete(inFilename);}}
void Hash::aesEncryptFilePump() {
qlonglong readLength = qMin(_blockSize, totalBytesToEncrypt - bytesEncrypted);
qlonglong remainder = _fileSource->Pump(readLength);
bytesEncrypted += readLength - remainder; //_fileSource->Pump(readLength);
emit bytesEncryptedChanged(bytesEncrypted);
if (_fileSource->SourceExhausted())
{
aesEncryptFileClose();
emit aesEncryptFileComplete(inFilename);
}
}
CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption *e = new CryptoPP::CFB_Mode<CryptoPP::AES>::Encryption((const byte *)_key.constData(), _key.length(), (const byte *)binIv.constData(), 1);
_fileSource->Attach(new CryptoPP::MeterFilter);
_fileSource->Attach(new CryptoPP::StreamTransformationFilter(*e));
if (_base64Output) {
_fileSource->Attach(new CryptoPP::Base64Encoder());
}
_fileSource->Attach(new CryptoPP::FileSink(outFilename_));
I changed my pump function to be:
void Hash::aesEncryptFilePump() {qlonglong readLength = qMin(_blockSize, totalBytesToEncrypt - bytesEncrypted);qlonglong remainder = _fileSource->Pump(readLength);
_fileSource->AttachedTransformation()->MessageEnd();
bytesEncrypted += readLength - remainder; //_fileSource->Pump(readLength);emit bytesEncryptedChanged(bytesEncrypted);if (_fileSource->SourceExhausted()){aesEncryptFileClose();emit aesEncryptFileComplete(inFilename);}}
Which seems to be what is needed per https://www.cryptopp.com/wiki/User_Guide:_filters.h However you mentioned calling it on the STF. Shouldn't the MessageEnd() cascade down?
1. [As discussed before] For some reason FileSource with the pump argument=true attempts to allocate the entire size of the file? This is a terrible idea. Why doesn't it pump() manageable chunks in a loop internally?
2. In order to not lock the GUI, I had to split the calls into a stateful class, where I have Configure, Open and Pump. Then I realized there is no Close(). I was going to cleanup in the Close().
3. Also with 2, everything is set to automatically delete the attachments automatically. This is a bad idea and confuses ownership. Then I tried using Ref() but that doesn't work with pointers.
4. I'm targeting many platforms, so XCode specifics should not apply.