diff --git a/AaxDecrypter/AaxDecrypter.csproj b/AaxDecrypter/AaxDecrypter.csproj index 6ca88326..b531426f 100644 --- a/AaxDecrypter/AaxDecrypter.csproj +++ b/AaxDecrypter/AaxDecrypter.csproj @@ -18,19 +18,19 @@ Always - + Always - + Always - + Always - + Always - + Always @@ -63,10 +63,10 @@ Always - + Always - + Always diff --git a/AaxDecrypter/AaxToM4bConverter.cs b/AaxDecrypter/AaxToM4bConverter.cs index 8dffb706..4fbfc4de 100644 --- a/AaxDecrypter/AaxToM4bConverter.cs +++ b/AaxDecrypter/AaxToM4bConverter.cs @@ -48,7 +48,8 @@ namespace AaxDecrypter public event EventHandler DecryptProgressUpdate; public string inputFileName { get; } - public string decryptKey { get; private set; } + public string audible_key { get; private set; } + public string audible_iv { get; private set; } private StepSequence steps { get; } public byte[] coverBytes { get; private set; } @@ -62,20 +63,21 @@ namespace AaxDecrypter public Tags tags { get; private set; } public EncodingInfo encodingInfo { get; private set; } - private Func> getKeyFuncAsync { get; } - - public static async Task CreateAsync(string inputFile, string decryptKey, Func> getKeyFunc, Chapters chapters = null) + public static async Task CreateAsync(string inputFile, string audible_key, string audible_iv, Chapters chapters = null) { - var converter = new AaxToM4bConverter(inputFile, decryptKey, getKeyFunc); + var converter = new AaxToM4bConverter(inputFile, audible_key, audible_iv); converter.chapters = chapters ?? new AAXChapters(inputFile); await converter.prelimProcessing(); converter.printPrelim(); return converter; } - private AaxToM4bConverter(string inputFile, string decryptKey, Func> getKeyFunc) + private AaxToM4bConverter(string inputFile, string audible_key, string audible_iv) { - ArgumentValidator.EnsureNotNullOrWhiteSpace(inputFile, nameof(inputFile)); + ArgumentValidator.EnsureNotNullOrWhiteSpace(inputFile, nameof(inputFile)); + ArgumentValidator.EnsureNotNullOrWhiteSpace(audible_key, nameof(audible_key)); + ArgumentValidator.EnsureNotNullOrWhiteSpace(audible_iv, nameof(audible_iv)); + if (!File.Exists(inputFile)) throw new ArgumentNullException(nameof(inputFile), "File does not exist"); @@ -94,8 +96,8 @@ namespace AaxDecrypter }; inputFileName = inputFile; - this.decryptKey = decryptKey; - this.getKeyFuncAsync = getKeyFunc; + this.audible_key = audible_key; + this.audible_iv = audible_iv; } private async Task prelimProcessing() @@ -109,17 +111,17 @@ namespace AaxDecrypter PathLib.ToPathSafeString(tags.title) + ".m4b" ); - // set default name - SetOutputFilename(defaultFilename); + // set default name + SetOutputFilename(defaultFilename); await Task.Run(() => saveCover(inputFileName)); } private void saveCover(string aaxFile) { - using var file = TagLib.File.Create(aaxFile, "audio/mp4", TagLib.ReadStyle.Average); - coverBytes = file.Tag.Pictures[0].Data.Data; - } + using var file = TagLib.File.Create(aaxFile, "audio/mp4", TagLib.ReadStyle.Average); + coverBytes = file.Tag.Pictures[0].Data.Data; + } private void printPrelim() { @@ -171,27 +173,16 @@ namespace AaxDecrypter { DecryptProgressUpdate?.Invoke(this, 0); - var tempRipFile = Path.Combine(outDir, "funny.aac"); + var tempRipFile = Path.Combine(outDir, "funny.mp4"); var fail = "WARNING-Decrypt failure. "; int returnCode; - if (string.IsNullOrWhiteSpace(decryptKey)) - { - returnCode = getKey_decrypt(tempRipFile); - } - else - { - returnCode = decrypt(tempRipFile); - if (returnCode == -99) - { - Console.WriteLine($"{fail}Incorrect decrypt key: {decryptKey}"); - decryptKey = null; - returnCode = getKey_decrypt(tempRipFile); - } - } - if (returnCode == 100) + returnCode = decrypt(tempRipFile); + if (returnCode == -99) + Console.WriteLine($"{fail}Incorrect decrypt key."); + else if (returnCode == 100) Console.WriteLine($"{fail}Thread completed without changing return code. This shouldn't be possible"); else if (returnCode == 0) { @@ -200,8 +191,6 @@ namespace AaxDecrypter DecryptProgressUpdate?.Invoke(this, 100); return true; } - else if (returnCode == -99) - Console.WriteLine($"{fail}Incorrect decrypt key: {decryptKey}"); else // any other returnCode Console.WriteLine($"{fail}Unknown failure code: {returnCode}"); @@ -210,24 +199,16 @@ namespace AaxDecrypter return false; } - private int getKey_decrypt(string tempRipFile) - { - decryptKey = getKey(); - return decrypt(tempRipFile); - } - - // I am NOT happy about doing async this way. Async needs to be added to Step framework - string getKey() => getKeyFuncAsync().GetAwaiter().GetResult(); private int decrypt(string tempRipFile) { FileExt.SafeDelete(tempRipFile); - Console.WriteLine("Decrypting with key " + decryptKey); + Console.WriteLine($"Decrypting with key={audible_key}, iv={audible_iv}"); var returnCode = 100; - var thread = new Thread(() => returnCode = ngDecrypt()); - thread.Start(); + var thread = new Thread((b) => returnCode = ngDecrypt(b)); + thread.Start(tempRipFile); double fileLen = new FileInfo(inputFileName).Length; while (thread.IsAlive && returnCode == 100) @@ -244,25 +225,35 @@ namespace AaxDecrypter return returnCode; } - private int ngDecrypt() + private int ngDecrypt(object tempFileNameObj) { + var tempFileName = tempFileNameObj as string; + + string args = "-audible_key " + + audible_key + + " -audible_iv " + + audible_iv + + " -i " + + "\"" + inputFileName + "\"" + + " -c:a copy -vn -sn -dn -y " + + "\"" + tempFileName + "\""; + var info = new ProcessStartInfo { - FileName = DecryptSupportLibraries.mp4trackdumpPath, - Arguments = "-c " + encodingInfo.channels + " -r " + encodingInfo.sampleRate + " \"" + inputFileName + "\"" + FileName = DecryptSupportLibraries.ffmpegPath, + Arguments = args }; - info.EnvironmentVariables["VARIABLE"] = decryptKey; var result = info.RunHidden(); - // bad checksum -- bad decrypt key - if (result.Output.Contains("checksums mismatch, aborting!")) + // failed to decrypt + if (result.Error.Contains("aac bitstream error")) return -99; return result.ExitCode; } - // temp file names for steps 3, 4, 5 + // temp file names for steps 3, 4, 5 string tempChapsGuid { get; } = Guid.NewGuid().ToString().ToUpper().Replace("-", ""); string tempChapsPath => Path.Combine(outDir, $"tempChaps_{tempChapsGuid}.mp4"); string mp4_file => outputFileWithNewExt(".mp4"); diff --git a/AaxDecrypter/DecryptLib/avcodec-58.dll b/AaxDecrypter/DecryptLib/avcodec-58.dll new file mode 100644 index 00000000..596f682a Binary files /dev/null and b/AaxDecrypter/DecryptLib/avcodec-58.dll differ diff --git a/AaxDecrypter/DecryptLib/avdevice-57.dll b/AaxDecrypter/DecryptLib/avdevice-57.dll deleted file mode 100644 index 3b91e4bc..00000000 Binary files a/AaxDecrypter/DecryptLib/avdevice-57.dll and /dev/null differ diff --git a/AaxDecrypter/DecryptLib/avdevice-58.dll b/AaxDecrypter/DecryptLib/avdevice-58.dll new file mode 100644 index 00000000..f88b6c5c Binary files /dev/null and b/AaxDecrypter/DecryptLib/avdevice-58.dll differ diff --git a/AaxDecrypter/DecryptLib/avfilter-6.dll b/AaxDecrypter/DecryptLib/avfilter-6.dll deleted file mode 100644 index 7327e65f..00000000 Binary files a/AaxDecrypter/DecryptLib/avfilter-6.dll and /dev/null differ diff --git a/AaxDecrypter/DecryptLib/avcodec-57.dll b/AaxDecrypter/DecryptLib/avfilter-7.dll similarity index 54% rename from AaxDecrypter/DecryptLib/avcodec-57.dll rename to AaxDecrypter/DecryptLib/avfilter-7.dll index 4efd87aa..6cbedea3 100644 Binary files a/AaxDecrypter/DecryptLib/avcodec-57.dll and b/AaxDecrypter/DecryptLib/avfilter-7.dll differ diff --git a/AaxDecrypter/DecryptLib/avformat-57.dll b/AaxDecrypter/DecryptLib/avformat-57.dll deleted file mode 100644 index a5c286f0..00000000 Binary files a/AaxDecrypter/DecryptLib/avformat-57.dll and /dev/null differ diff --git a/AaxDecrypter/DecryptLib/avformat-58.dll b/AaxDecrypter/DecryptLib/avformat-58.dll new file mode 100644 index 00000000..18ccd0e7 Binary files /dev/null and b/AaxDecrypter/DecryptLib/avformat-58.dll differ diff --git a/AaxDecrypter/DecryptLib/avutil-55.dll b/AaxDecrypter/DecryptLib/avutil-55.dll deleted file mode 100644 index 9805d769..00000000 Binary files a/AaxDecrypter/DecryptLib/avutil-55.dll and /dev/null differ diff --git a/AaxDecrypter/DecryptLib/avutil-56.dll b/AaxDecrypter/DecryptLib/avutil-56.dll new file mode 100644 index 00000000..d1565ae4 Binary files /dev/null and b/AaxDecrypter/DecryptLib/avutil-56.dll differ diff --git a/AaxDecrypter/DecryptLib/ffmpeg.exe b/AaxDecrypter/DecryptLib/ffmpeg.exe index 9d759ebc..f2840373 100644 Binary files a/AaxDecrypter/DecryptLib/ffmpeg.exe and b/AaxDecrypter/DecryptLib/ffmpeg.exe differ diff --git a/AaxDecrypter/DecryptLib/ffprobe.exe b/AaxDecrypter/DecryptLib/ffprobe.exe index 2863d735..6028bea1 100644 Binary files a/AaxDecrypter/DecryptLib/ffprobe.exe and b/AaxDecrypter/DecryptLib/ffprobe.exe differ diff --git a/AaxDecrypter/DecryptLib/swresample-2.dll b/AaxDecrypter/DecryptLib/swresample-2.dll deleted file mode 100644 index 591f8414..00000000 Binary files a/AaxDecrypter/DecryptLib/swresample-2.dll and /dev/null differ diff --git a/AaxDecrypter/DecryptLib/swresample-3.dll b/AaxDecrypter/DecryptLib/swresample-3.dll new file mode 100644 index 00000000..d2f5ea87 Binary files /dev/null and b/AaxDecrypter/DecryptLib/swresample-3.dll differ diff --git a/AaxDecrypter/DecryptLib/swscale-4.dll b/AaxDecrypter/DecryptLib/swscale-4.dll deleted file mode 100644 index ec30e0bf..00000000 Binary files a/AaxDecrypter/DecryptLib/swscale-4.dll and /dev/null differ diff --git a/AaxDecrypter/DecryptLib/swscale-5.dll b/AaxDecrypter/DecryptLib/swscale-5.dll new file mode 100644 index 00000000..a30c307e Binary files /dev/null and b/AaxDecrypter/DecryptLib/swscale-5.dll differ diff --git a/AaxDecrypter/DecryptSupportLibraries.cs b/AaxDecrypter/DecryptSupportLibraries.cs index 66238676..c5952295 100644 --- a/AaxDecrypter/DecryptSupportLibraries.cs +++ b/AaxDecrypter/DecryptSupportLibraries.cs @@ -6,7 +6,7 @@ namespace AaxDecrypter { // OTHER EXTERNAL DEPENDENCIES // ffprobe has these pre-req.s as I'm using it: - // avcodec-57.dll, avdevice-57.dll, avfilter-6.dll, avformat-57.dll, avutil-55.dll, postproc-54.dll, swresample-2.dll, swscale-4.dll, taglib-sharp.dll + // avcodec-58.dll, avdevice-58.dll, avfilter-7.dll, avformat-58.dll, avutil-56.dll, postproc-54.dll, swresample-3.dll, swscale-5.dll, taglib-sharp.dll // // something else needs the cygwin files (cyg*.dll) @@ -16,6 +16,5 @@ namespace AaxDecrypter public static string ffmpegPath { get; } = Path.Combine(decryptLib_, "ffmpeg.exe"); public static string ffprobePath { get; } = Path.Combine(decryptLib_, "ffprobe.exe"); public static string atomicParsleyPath { get; } = Path.Combine(decryptLib_, "AtomicParsley.exe"); - public static string mp4trackdumpPath { get; } = Path.Combine(decryptLib_, "mp4trackdump.exe"); } } diff --git a/FileLiberator/DecryptBook.cs b/FileLiberator/DecryptBook.cs index 835c3444..9b2e8871 100644 --- a/FileLiberator/DecryptBook.cs +++ b/FileLiberator/DecryptBook.cs @@ -119,11 +119,7 @@ namespace FileLiberator { using var persister = AudibleApiStorage.GetAccountsSettingsPersister(); - var account = persister - .AccountsSettings - .GetAccount(libraryBook.Account, libraryBook.Book.Locale); - - var converter = await AaxToM4bConverter.CreateAsync(aaxFilename, account.DecryptKey, api.GetActivationBytesAsync, chapters); + var converter = await AaxToM4bConverter.CreateAsync(aaxFilename, libraryBook.Book.AudibleKey, libraryBook.Book.AudibleIV, chapters); converter.AppName = "Libation"; TitleDiscovered?.Invoke(this, converter.tags.title); @@ -143,8 +139,6 @@ namespace FileLiberator if (!success) return null; - account.DecryptKey = converter.decryptKey; - return converter.outputFileName; } finally diff --git a/FileLiberator/DownloadBook.cs b/FileLiberator/DownloadBook.cs index 788a9f9f..6b3dba91 100644 --- a/FileLiberator/DownloadBook.cs +++ b/FileLiberator/DownloadBook.cs @@ -6,7 +6,8 @@ using DataLayer; using Dinah.Core; using Dinah.Core.ErrorHandling; using FileManager; -using InternalUtilities; +using System.Net.Http; +using Dinah.Core.Net.Http; namespace FileLiberator { @@ -29,7 +30,7 @@ namespace FileLiberator public override async Task ProcessItemAsync(LibraryBook libraryBook) { var tempAaxFilename = getDownloadPath(libraryBook); - var actualFilePath = await downloadBookAsync(libraryBook, tempAaxFilename); + var actualFilePath = await downloadAacxBookAsync(libraryBook, tempAaxFilename); moveBook(libraryBook, actualFilePath); return verifyDownload(libraryBook); } @@ -40,7 +41,53 @@ namespace FileLiberator libraryBook.Book.Title, "aax", libraryBook.Book.AudibleProductId); + private async Task downloadAacxBookAsync(LibraryBook libraryBook, string tempAaxFilename) + { + validate(libraryBook); + var api = await GetApiAsync(libraryBook); + + var dlLic = await api.GetDownloadLicenseAsync(libraryBook.Book.AudibleProductId); + + libraryBook.Book.AudibleKey = dlLic.AudibleKey; + libraryBook.Book.AudibleIV = dlLic.AudibleIV; + + var client = new HttpClient(); + client.DefaultRequestHeaders.Add("User-Agent", Resources.UserAgent); + + var actualFilePath = await PerformDownloadAsync( + tempAaxFilename, + (p) => client.DownloadFileAsync(dlLic.DownloadUri.AbsoluteUri, tempAaxFilename, p)); + + System.Threading.Thread.Sleep(100); + // if bad file download, a 0-33 byte file will be created + // if service unavailable, a 52 byte string will be saved as file + var length = new FileInfo(actualFilePath).Length; + + if (length > 100) + return actualFilePath; + + var contents = File.ReadAllText(actualFilePath); + File.Delete(actualFilePath); + + var exMsg = contents.StartsWithInsensitive(SERVICE_UNAVAILABLE) + ? SERVICE_UNAVAILABLE + : "Error downloading file"; + + var ex = new Exception(exMsg); + Serilog.Log.Logger.Error(ex, "Download error {@DebugInfo}", new + { + libraryBook.Book.Title, + libraryBook.Book.AudibleProductId, + libraryBook.Book.Locale, + Account = libraryBook.Account?.ToMask() ?? "[empty]", + tempAaxFilename, + actualFilePath, + length, + contents + }); + throw ex; + } private async Task downloadBookAsync(LibraryBook libraryBook, string tempAaxFilename) { validate(libraryBook); diff --git a/LibationLauncher/LibationLauncher.csproj b/LibationLauncher/LibationLauncher.csproj index fbd552c1..baa93b8a 100644 --- a/LibationLauncher/LibationLauncher.csproj +++ b/LibationLauncher/LibationLauncher.csproj @@ -13,7 +13,7 @@ win-x64 - 4.4.0.5 + 4.4.0.34