8 Commits

Author SHA1 Message Date
Grégory Soutadé
16a13eed89 Update version & README 2022-02-22 21:26:19 +01:00
Grégory Soutadé
479869b7f2 Fix a use after free in adept_activate : pass string destroyed too early 2022-02-22 20:58:40 +01:00
Grégory Soutadé
41f1a1e980 Fix a bug in adept_activate : cannot ask for interactive password if output directory already exists 2022-02-22 20:58:36 +01:00
Grégory Soutadé
9648157bf7 Remove README_package.md 2022-02-22 20:58:34 +01:00
Grégory Soutadé
a97a915bc8 Rework HTTP request loop events (Thanks Milian) and display download progression 2022-02-22 20:58:32 +01:00
Grégory Soutadé
a623a3d796 Skip files with inflate errors during ePub decryption 2022-02-22 20:58:30 +01:00
Grégory Soutadé
7d161133c3 Check for key size before files decryption 2022-02-22 20:58:26 +01:00
Grégory Soutadé
7d93817e49 Add PKCS8 error 2022-02-22 20:58:14 +01:00
7 changed files with 67 additions and 89 deletions

View File

@@ -70,10 +70,10 @@ BUILD_SHARED build libgourou.so if 1, nothing if 0, can be combined with BUILD_S
Utils
-----
You can import configuration from your eReader or create a new one with utils/activate :
You can import configuration from your eReader or create a new one with _utils/adept\_activate_ :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./utils/activate -u <AdobeID USERNAME>
./utils/adept_activate -u <AdobeID USERNAME>
Then a _./.adept_ directory is created with all configuration file
@@ -82,7 +82,7 @@ To download an ePub/PDF :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./utils/acsmdownloader -f <ACSM_FILE>
To export your private key :
To export your private key (for DeDRM software) :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./utils/acsmdownloader --export-private-key [-o adobekey_1.der]
@@ -92,6 +92,9 @@ To remove ADEPT DRM :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./utils/adept_remove -f <encryptedFile>
You can get utils full options description with -h or --help switch
Copyright
---------
@@ -113,3 +116,4 @@ Special thanks
--------------
* _Jens_ for all test samples and utils testing
* _Milian_ for debug & code

View File

@@ -1,69 +0,0 @@
Introduction
------------
libgourou is a free implementation of Adobe's ADEPT protocol used to add DRM on ePub/PDF files. It overcome the lacks of Adobe support for Linux platforms.
Dependencies
------------
For libgourou :
* None
For utils :
* QT5Core
* QT5Network
* OpenSSL
* libzip
Utils
-----
You can import configuration from your eReader or create a new one with utils/activate :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./activate -u <AdobeID USERNAME>
Then a _./.adept_ directory is created with all configuration file
To download an ePub/PDF :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./acsmdownloader -f <ACSM_FILE>
To export your private key :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./acsmdownloader --export-private-key [-o adobekey_1.der]
To remove ADEPT DRM :
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD
./adept_remove -f <encryptedFile>
Copyright
---------
Grégory Soutadé
License
-------
libgourou : LGPL v3 or later
utils : BSD
Special thanks
--------------
* _Jens_ for all test samples and utils testing

View File

@@ -40,7 +40,7 @@
#define ACS_SERVER "http://adeactivate.adobe.com/adept"
#endif
#define LIBGOUROU_VERSION "0.5.1"
#define LIBGOUROU_VERSION "0.5.2"
namespace gourou
{

View File

@@ -110,6 +110,7 @@ namespace gourou
CLIENT_ZIP_ERROR,
CLIENT_GENERIC_EXCEPTION,
CLIENT_NETWORK_ERROR,
CLIENT_INVALID_PKCS8
};
enum DRM_REMOVAL_ERROR {
@@ -118,7 +119,8 @@ namespace gourou
DRM_FILE_ERROR,
DRM_FORMAT_NOT_SUPPORTED,
DRM_IN_OUT_EQUALS,
DRM_MISSING_PARAMETER
DRM_MISSING_PARAMETER,
DRM_INVALID_KEY_SIZE
};
/**

View File

@@ -927,8 +927,12 @@ namespace gourou
void DRMProcessor::decryptADEPTKey(const std::string& encryptedKey, unsigned char* decryptedKey)
{
if (encryptedKey.size() != 172)
EXCEPTION(DRM_INVALID_KEY_SIZE, "Invalid encrypted key size (" << encryptedKey.size() << "). DRM version not supported");
ByteArray arrayEncryptedKey = ByteArray::fromBase64(encryptedKey);
std::string privateKeyData = user->getPrivateLicenseKey();
ByteArray privateRSAKey = ByteArray::fromBase64(privateKeyData);
@@ -1006,9 +1010,20 @@ namespace gourou
_clearData[dataOutLength] = 'Z';
clearData.resize(dataOutLength+1);
client->inflate(clearData, inflateData);
client->zipWriteFile(zipHandler, encryptedFile, inflateData);
try
{
client->inflate(clearData, inflateData);
client->zipWriteFile(zipHandler, encryptedFile, inflateData);
}
catch(gourou::Exception& e)
{
if (e.getErrorCode() == CLIENT_ZIP_ERROR)
{
GOUROU_LOG(ERROR, e.what() << std::endl << "Skip file " << encryptedFile);
}
else
throw e;
}
it->node().parent().remove_child(it->node());
}
@@ -1190,14 +1205,14 @@ namespace gourou
if ((*datasIt)->type() != uPDFParser::DataType::STREAM)
continue;
GOUROU_LOG(DEBUG, "Decrypt stream id " << object->objectId());
stream = (uPDFParser::Stream*) (*datasIt);
unsigned char* encryptedData = stream->data();
unsigned int dataLength = stream->dataLength();
unsigned char* clearData = new unsigned char[dataLength];
unsigned int dataOutLength;
GOUROU_LOG(DEBUG, "Decrypt stream id " << object->objectId() << ", size " << stream->dataLength());
client->Decrypt(CryptoInterface::ALGO_RC4, CryptoInterface::CHAIN_ECB,
tmpKey, 16, /* Key */
NULL, 0, /* IV */

View File

@@ -282,17 +282,19 @@ int main(int argc, char** argv)
goto end;
if (key == 'y' || key == 'Y')
break;
// Clean STDIN buf
while ((key = getchar()) != '\n')
;
}
// Clean STDIN buf
while ((key = getchar()) != '\n')
;
}
std::string pass;
if (!password)
{
char prompt[128];
std::snprintf(prompt, sizeof(prompt), "Enter password for <%s> : ", username);
std::string pass = getpass((const char*)prompt, false);
pass = getpass((const char*)prompt, false);
password = pass.c_str();
}

View File

@@ -88,6 +88,20 @@ void DRMProcessorClientImpl::randBytes(unsigned char* bytesOut, unsigned int len
}
/* HTTP interface */
#define DISPLAY_THRESHOLD 10*1024 // Threshold to display download progression
static void downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
// For "big" files only
if (bytesTotal >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN)
{
int percent = 0;
if (bytesTotal)
percent = (bytesReceived * 100) / bytesTotal;
std::cout << "\rDownload " << percent << "%" << std::flush;
}
}
std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, const std::string& POSTData, const std::string& contentType, std::map<std::string, std::string>* responseHeaders)
{
QNetworkRequest request(QUrl(URL.c_str()));
@@ -112,10 +126,14 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
else
reply = networkManager.get(request);
QCoreApplication* app = QCoreApplication::instance();
networkManager.moveToThread(app->thread());
while (!reply->isFinished())
app->processEvents();
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
// Handled just below
QObject::connect(reply, &QNetworkReply::errorOccurred, &loop, &QEventLoop::quit);
QObject::connect(reply, &QNetworkReply::downloadProgress, &loop, downloadProgress);
loop.exec();
QByteArray location = reply->rawHeader("Location");
if (location.size() != 0)
@@ -136,6 +154,8 @@ std::string DRMProcessorClientImpl::sendHTTPRequest(const std::string& URL, cons
}
replyData = reply->readAll();
if (replyData.size() >= DISPLAY_THRESHOLD && gourou::logLevel >= gourou::WARN)
std::cout << std::endl;
if (reply->rawHeader("Content-Type") == "application/vnd.adobe.adept+xml")
{
GOUROU_LOG(gourou::DEBUG, ">>> " << std::endl << replyData.data());
@@ -184,7 +204,7 @@ void DRMProcessorClientImpl::RSAPrivateDecrypt(const unsigned char* RSAKey, unsi
PKCS8_PRIV_KEY_INFO* p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(mem, NULL);
if (!p8inf)
EXCEPTION(gourou::CLIENT_INVALID_PKCS12, ERR_error_string(ERR_get_error(), NULL));
EXCEPTION(gourou::CLIENT_INVALID_PKCS8, ERR_error_string(ERR_get_error(), NULL));
EVP_PKEY* pkey = EVP_PKCS82PKEY(p8inf);
RSA * rsa;
@@ -510,7 +530,12 @@ void DRMProcessorClientImpl::inflate(gourou::ByteArray& data, gourou::ByteArray&
ret = ::inflate(&infstream, Z_FINISH);
while (ret == Z_OK || ret == Z_STREAM_END || ret == Z_BUF_ERROR)
{
// Real error
if (ret == Z_BUF_ERROR && infstream.avail_out == (uInt)dataSize)
EXCEPTION(gourou::CLIENT_ZIP_ERROR, "Inflate error, code " << zError(ret) << ", msg " << infstream.msg);
result.append(buffer, dataSize-infstream.avail_out);
if ((ret == Z_OK && infstream.avail_out != 0) || ret == Z_STREAM_END)
break;
infstream.avail_out = (uInt)dataSize; // size of output
@@ -518,7 +543,6 @@ void DRMProcessorClientImpl::inflate(gourou::ByteArray& data, gourou::ByteArray&
ret = ::inflate(&infstream, Z_FINISH);
}
if (ret == Z_STREAM_END)
ret = inflateEnd(&infstream);