in aios/filesystem/fslib/tools/fsutil/FsUtil.cpp [199:339]
ErrorCode FsUtil::runEncrypt(const char *srcPath, const char *dstPath, const char *cipherOption, bool optionUseBase64) {
autil::cipher::CipherOption option(autil::cipher::CipherType::CT_UNKNOWN);
if (cipherOption == nullptr) {
if (!getCipherOption(option)) {
return EC_BADARGS;
}
} else {
if (!option.fromKVString(cipherOption, optionUseBase64)) {
return EC_BADARGS;
}
}
auto beginTs = autil::TimeUtility::currentTime();
cout << "-------------------------------------------------" << endl;
FileMeta fileMeta;
ErrorCode ret = FileSystem::getFileMeta(srcPath, fileMeta);
if (ret != EC_OK) {
cerr << "fail to get length of file <" << srcPath << ">. " << FileSystem::getErrorString(ret) << endl;
return ret;
}
unique_ptr<File> rFile(FileSystem::openFile(srcPath, READ));
if (!rFile->isOpened()) {
cerr << "open file <" << srcPath << "> for read fail. " << FileSystem::getErrorString(rFile->getLastError())
<< endl;
return rFile->getLastError();
}
if (std::string(dstPath) != "/dev/null" && FileSystem::isExist(dstPath) == EC_TRUE) {
cerr << "target path <" << dstPath << "> already exist. " << endl;
return EC_BADARGS;
}
unique_ptr<File> wFile(FileSystem::openFile(dstPath, WRITE));
if (!wFile->isOpened()) {
cerr << "open file <" << dstPath << "> for write fail. " << FileSystem::getErrorString(wFile->getLastError())
<< endl;
return wFile->getLastError();
}
volatile bool hasError = false;
ErrorCode rCode = EC_OK;
auto encrypter = autil::cipher::AESCipherCreator::createStreamEncrypter(option, 2 * 1024 * 1024 /* 2 MB */);
if (encrypter == nullptr) {
cerr << "create stream encrypter fail." << endl;
return EC_UNKNOWN;
}
Md5StreamPtr rFileMd5;
Md5StreamPtr wFileMd5;
if (autil::EnvUtil::getEnv("PRINT_MD5", false)) {
rFileMd5.reset(new Md5Stream);
wFileMd5.reset(new Md5Stream);
}
size_t totalEncryptLen = 0;
std::thread readThread([&]() {
size_t bufferLen = 2 * 1024 * 1024;
SafeBuffer buffer(bufferLen);
while (!hasError) {
auto readLen = rFile->read(buffer.getBuffer(), bufferLen);
if (readLen < 0) {
cerr << "read file <" << srcPath << "> fail. " << FileSystem::getErrorString(rFile->getLastError())
<< endl;
rCode = rFile->getLastError();
hasError = true;
continue;
}
if (readLen > 0) {
if (rFileMd5) {
rFileMd5->Put((const uint8_t *)buffer.getBuffer(), readLen);
}
if (!encrypter->append((const unsigned char *)buffer.getBuffer(), readLen)) {
cerr << "encrypter append data fail." << endl;
rCode = EC_UNKNOWN;
hasError = true;
continue;
}
}
totalEncryptLen += readLen;
if (rFile->isEof()) {
break;
}
}
if (!encrypter->seal()) {
cerr << "encrypter seal fail." << endl;
rCode = EC_UNKNOWN;
hasError = true;
}
rFile->close();
});
ErrorCode wCode = EC_OK;
size_t totalWriteLen = 0;
std::thread writeThread([&]() {
size_t bufferLen = 2 * 1024 * 1024;
SafeBuffer buffer(bufferLen);
while (!hasError) {
auto ret = encrypter->get((unsigned char *)buffer.getBuffer(), bufferLen);
if (ret > 0) {
if (wFileMd5) {
wFileMd5->Put((const uint8_t *)buffer.getBuffer(), ret);
}
if (wFile->write(buffer.getBuffer(), ret) != ret) {
cerr << "write to dst file <" << dstPath << "> fail. "
<< FileSystem::getErrorString(wFile->getLastError()) << endl;
wCode = wFile->getLastError();
hasError = true;
}
totalWriteLen += ret;
continue;
}
if (encrypter->isEof()) {
break;
}
}
wCode = wFile->close();
if (wCode != EC_OK) {
cerr << "close dst file <" << dstPath << "> fail. " << FileSystem::getErrorString(wFile->getLastError())
<< endl;
hasError = true;
}
});
readThread.join();
writeThread.join();
if (hasError) {
return rCode != EC_OK ? rCode : wCode;
}
auto interval = autil::TimeUtility::currentTime() - beginTs;
cout << "encryption interval:" << (double)interval / 1000000 << " seconds" << endl;
cout << "plain file length:" << totalEncryptLen << ", cipher file length:" << totalWriteLen << endl;
cout << "=================================================" << endl;
cout << "== key hex:" << encrypter->getKeyHexString() << endl;
cout << "== iv hex:" << encrypter->getIvHexString() << endl;
cout << "== salt hex:" << encrypter->getSaltHexString() << endl;
if (rFileMd5 && wFileMd5) {
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++" << endl;
cout << "++ src file md5:" << rFileMd5->GetMd5String() << endl;
cout << "++ dst file md5:" << wFileMd5->GetMd5String() << endl;
}
return EC_OK;
}