diff --git a/include/libgourou.h b/include/libgourou.h index 14f3437..e2ee44c 100644 --- a/include/libgourou.h +++ b/include/libgourou.h @@ -232,7 +232,7 @@ namespace gourou void fetchLicenseServiceCertificate(const std::string& licenseURL, const std::string& operatorURL); std::string encryptedKeyFirstPass(pugi::xml_document& rightsDoc, const std::string& encryptedKey, const std::string& keyType); - void decryptADEPTKey(const std::string& encryptedKey, unsigned char* decryptedKey); + void decryptADEPTKey(pugi::xml_document& rightsDoc, unsigned char* decryptedKey, const unsigned char* encryptionKey=0, unsigned encryptionKeySize=0); void removeEPubDRM(const std::string& filenameIn, const std::string& filenameOut, const unsigned char* encryptionKey, unsigned encryptionKeySize); void generatePDFObjectKey(int version, const unsigned char* masterKey, unsigned int masterKeyLength, diff --git a/src/libgourou.cpp b/src/libgourou.cpp index c69d7b7..e6d81c7 100644 --- a/src/libgourou.cpp +++ b/src/libgourou.cpp @@ -944,23 +944,6 @@ namespace gourou int DRMProcessor::getLogLevel() {return (int)gourou::logLevel;} void DRMProcessor::setLogLevel(int logLevel) {gourou::logLevel = (GOUROU_LOG_LEVEL)logLevel;} - 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); - - dumpBuffer(gourou::LG_LOG_DEBUG, "To decrypt : ", arrayEncryptedKey.data(), arrayEncryptedKey.length()); - - client->RSAPrivateDecrypt(privateRSAKey.data(), privateRSAKey.length(), - RSAInterface::RSA_KEY_PKCS8, "", - arrayEncryptedKey.data(), arrayEncryptedKey.length(), decryptedKey); - } - /** * RSA Key can be over encrypted with AES128-CBC if keyType attribute is set * remainder = keyType % 16 @@ -1009,11 +992,10 @@ namespace gourou for(unsigned int i=0; idecrypt(CryptoInterface::ALGO_AES, CryptoInterface::CHAIN_CBC, @@ -1041,7 +1023,51 @@ namespace gourou return res.toBase64(); } - + + void DRMProcessor::decryptADEPTKey(pugi::xml_document& rightsDoc, unsigned char* decryptedKey, const unsigned char* encryptionKey, unsigned encryptionKeySize) + { + unsigned char rsaKey[RSA_KEY_SIZE]; + + if (!encryptionKey) + { + std::string encryptedKey = extractTextElem(rightsDoc, "/adept:rights/licenseToken/encryptedKey"); + std::string keyType = extractTextAttribute(rightsDoc, "/adept:rights/licenseToken/encryptedKey", "keyType", false); + + if (keyType != "") + encryptedKey = encryptedKeyFirstPass(rightsDoc, encryptedKey, keyType); + + 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); + + dumpBuffer(gourou::LG_LOG_DEBUG, "To decrypt : ", arrayEncryptedKey.data(), arrayEncryptedKey.length()); + + client->RSAPrivateDecrypt(privateRSAKey.data(), privateRSAKey.length(), + RSAInterface::RSA_KEY_PKCS8, "", + arrayEncryptedKey.data(), arrayEncryptedKey.length(), rsaKey); + + dumpBuffer(gourou::LG_LOG_DEBUG, "Decrypted : ", rsaKey, sizeof(rsaKey)); + + if (rsaKey[0] != 0x00 || rsaKey[1] != 0x02 || + rsaKey[RSA_KEY_SIZE-16-1] != 0x00) + EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Unable to retrieve encryption key"); + + memcpy(decryptedKey, &rsaKey[sizeof(rsaKey)-16], 16); + } + else + { + GOUROU_LOG(DEBUG, "Use provided encryption key"); + if (encryptionKeySize != 16) + EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Provided encryption key must be 16 bytes"); + + memcpy(decryptedKey, encryptionKey, encryptionKeySize); + } + } + void DRMProcessor::removeEPubDRM(const std::string& filenameIn, const std::string& filenameOut, const unsigned char* encryptionKey, unsigned encryptionKeySize) { @@ -1053,32 +1079,9 @@ namespace gourou pugi::xml_document rightsDoc; rightsDoc.load_string((const char*)zipData.data()); - std::string encryptedKey = extractTextElem(rightsDoc, "/adept:rights/licenseToken/encryptedKey"); - unsigned char decryptedKey[RSA_KEY_SIZE]; + unsigned char decryptedKey[16]; - if (!encryptionKey) - { - std::string keyType = extractTextAttribute(rightsDoc, "/adept:rights/licenseToken/encryptedKey", "keyType", false); - - if (keyType != "") - encryptedKey = encryptedKeyFirstPass(rightsDoc, encryptedKey, keyType); - - decryptADEPTKey(encryptedKey, decryptedKey); - - dumpBuffer(gourou::LG_LOG_DEBUG, "Decrypted : ", decryptedKey, RSA_KEY_SIZE); - - if (decryptedKey[0] != 0x00 || decryptedKey[1] != 0x02 || - decryptedKey[RSA_KEY_SIZE-16-1] != 0x00) - EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Unable to retrieve encryption key"); - } - else - { - GOUROU_LOG(DEBUG, "Use provided encryption key"); - if (encryptionKeySize != 16) - EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Provided encryption key must be 16 bytes"); - - memcpy(&decryptedKey[sizeof(decryptedKey)-16], encryptionKey, encryptionKeySize); - } + decryptADEPTKey(rightsDoc, decryptedKey, encryptionKey, encryptionKeySize); client->zipReadFile(zipHandler, "META-INF/encryption.xml", zipData); pugi::xml_document encryptionDoc; @@ -1117,7 +1120,7 @@ namespace gourou unsigned int dataOutLength; client->decrypt(CryptoInterface::ALGO_AES, CryptoInterface::CHAIN_CBC, - decryptedKey+sizeof(decryptedKey)-16, 16, /* Key */ + decryptedKey, sizeof(decryptedKey), /* Key */ _data, 16, /* IV */ &_data[16], zipData.length()-16, _clearData, &dataOutLength); @@ -1210,7 +1213,7 @@ namespace gourou std::vector objects = parser.objects(); std::vector::iterator it; std::vector::reverse_iterator rIt; - unsigned char decryptedKey[RSA_KEY_SIZE]; + unsigned char decryptedKey[16]; int ebxId; for(rIt = objects.rbegin(); rIt != objects.rend(); rIt++) @@ -1249,31 +1252,7 @@ namespace gourou pugi::xml_document rightsDoc; rightsDoc.load_string((const char*)rightsStr.data()); - std::string encryptedKey = extractTextElem(rightsDoc, "/adept:rights/licenseToken/encryptedKey"); - - if (!encryptionKey) - { - std::string keyType = extractTextAttribute(rightsDoc, "/adept:rights/licenseToken/encryptedKey", "keyType", false); - - if (keyType != "") - encryptedKey = encryptedKeyFirstPass(rightsDoc, encryptedKey, keyType); - - decryptADEPTKey(encryptedKey, decryptedKey); - - dumpBuffer(gourou::LG_LOG_DEBUG, "Decrypted : ", decryptedKey, RSA_KEY_SIZE); - - if (decryptedKey[0] != 0x00 || decryptedKey[1] != 0x02 || - decryptedKey[RSA_KEY_SIZE-16-1] != 0x00) - EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Unable to retrieve encryption key"); - } - else - { - GOUROU_LOG(DEBUG, "Use provided encryption key"); - if (encryptionKeySize != 16) - EXCEPTION(DRM_ERR_ENCRYPTION_KEY, "Provided encryption key must be 16 bytes"); - - memcpy(&decryptedKey[sizeof(decryptedKey)-16], encryptionKey, encryptionKeySize); - } + decryptADEPTKey(rightsDoc, decryptedKey, encryptionKey, encryptionKeySize); ebxId = ebx->objectId(); @@ -1305,10 +1284,10 @@ namespace gourou GOUROU_LOG(DEBUG, "Obj " << object->objectId()); - unsigned char tmpKey[16]; + unsigned char tmpKey[sizeof(decryptedKey)]; generatePDFObjectKey(ebxVersion->value(), - decryptedKey+sizeof(decryptedKey)-16, 16, + decryptedKey, sizeof(decryptedKey), object->objectId(), object->generationNumber(), tmpKey);