private EReaderProcessor(Pdb pdb, string name, string ccNumber) { if (!(pdb.Filetype == "PNRd" && pdb.Creator == "PPrs")) { throw new FormatException("Invalid eReader file."); } pdbReader = pdb; var eReaderPdb = new EReaderPdb(pdbReader); if (!eReaderPdb.HaveDrm) { throw new InvalidOperationException("File doesn't have DRM or have unknown DRM version: {0}!"); } if (!(eReaderPdb.CompressionMethod == EReaderCompression.Drm1 || eReaderPdb.CompressionMethod == EReaderCompression.Drm2)) { throw new InvalidOperationException($"Unsupported compression method or DRM version: {eReaderPdb.CompressionMethod}!"); } data = pdbReader.GetSection(1); var desEngine = GetDesEngine(data.Copy(0, 8)); var decryptedData = desEngine.TransformFinalBlock(data.Copy(-8), 0, 8); var cookieShuf = decryptedData[0] << 24 | decryptedData[1] << 16 | decryptedData[2] << 8 | decryptedData[3]; var cookieSize = decryptedData[4] << 24 | decryptedData[5] << 16 | decryptedData[6] << 8 | decryptedData[7]; if (cookieShuf < 0x03 || cookieShuf > 0x14 || cookieSize < 0xf0 || cookieSize > 0x200) { throw new InvalidOperationException("Unsupportd eReader format"); } var input = desEngine.TransformFinalBlock(data.Copy(-cookieSize), 0, cookieSize); var r = UnshuffleData(input.SubRange(0, -8), cookieShuf); //using (var stream = new FileStream(pdb.Filename+".eReaderSection1Dump", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) stream.Write(r, 0, r.Length); var userKeyPart1 = Encoding.ASCII.GetBytes(FixUserName(name)); var userKeyPart2 = Encoding.ASCII.GetBytes(ccNumber.ToCharArray().Copy(-8)); long userKey; using (var stream1 = new MemoryStream(userKeyPart1)) using (var stream2 = new MemoryStream(userKeyPart2)) { userKey = new CRC32().GetCrc32(stream1) & 0xffffffff; userKey = userKey << 32 | new CRC32().GetCrc32(stream2) & 0xffffffff; } var drmSubVersion = (ushort)(r[0] << 8 | r[1]); numTextPages = (ushort)(r[2] << 8 | r[3]) - 1; flags = r[4] << 24 | r[5] << 16 | r[6] << 8 | r[7]; firstImagePage = (ushort)(r[24] << 8 | r[25]); numImagePages = (ushort)(r[26] << 8 | r[27]); if ((flags & ReqdFlags) != ReqdFlags) { throw new InvalidOperationException($"Unsupported flags combination: {flags:x8}"); } var userKeyArray = BitConverter.GetBytes(userKey); if (BitConverter.IsLittleEndian) { userKeyArray = userKeyArray.Reverse(); } desEngine = GetDesEngine(userKeyArray); var encryptedKey = new byte[0]; var encryptedKeySha = new byte[0]; if (eReaderPdb.CompressionMethod == EReaderCompression.Drm1) { if (drmSubVersion != 13) { throw new InvalidOperationException($"Unknown eReader DRM subversion ID: {drmSubVersion}"); } encryptedKey = r.Copy(44, 8); encryptedKeySha = r.Copy(52, 20); } else if (eReaderPdb.CompressionMethod == EReaderCompression.Drm2) { encryptedKey = r.Copy(172, 8); encryptedKeySha = r.Copy(56, 20); } contentKey = desEngine.TransformFinalBlock(encryptedKey, 0, encryptedKey.Length); byte[] checkHash; using (var sha1 = SHA1.Create()) checkHash = sha1.ComputeHash(contentKey); if (!encryptedKeySha.SequenceEqual(checkHash)) { var s = new StringBuilder(); for (var x = 0; x < r.Length - 8; x += 2) { for (var y = 0; y < (x - 20); y += 2) { if (TestKeyDecryption(desEngine, r, x, y)) { s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y); } } for (var y = x + 8; y < (r.Length - 20); y += 2) { if (TestKeyDecryption(desEngine, r, x, y)) { s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y); } } } if (s.Length > 0) { throw new InvalidDataException("Key and/or KeyHash offset mismatch. Possible values:\n\n" + s); } throw new ArgumentException("Incorrect Name of Credit Card number."); } contentDecryptor = GetDesEngine(contentKey); }
private EReaderProcessor(Pdb pdb, string name, string ccNumber) { if (!(pdb.Filetype == "PNRd" && pdb.Creator == "PPrs")) throw new FormatException("Invalid eReader file."); pdbReader = pdb; var eReaderPdb = new EReaderPdb(pdbReader); if (!eReaderPdb.HaveDrm) throw new InvalidOperationException("File doesn't have DRM or have unknown DRM version: {0}!"); if (!(eReaderPdb.CompressionMethod == EReaderCompression.Drm1 || eReaderPdb.CompressionMethod == EReaderCompression.Drm2)) throw new InvalidOperationException(string.Format("Unsupported compression method or DRM version: {0}!", eReaderPdb.CompressionMethod)); data = pdbReader.GetSection(1); ICryptoTransform desEngine = GetDesEngine(data.Copy(0, 8)); byte[] decryptedData = desEngine.TransformFinalBlock(data.Copy(-8), 0, 8); int cookieShuf = decryptedData[0] << 24 | decryptedData[1] << 16 | decryptedData[2] << 8 | decryptedData[3]; int cookieSize = decryptedData[4] << 24 | decryptedData[5] << 16 | decryptedData[6] << 8 | decryptedData[7]; if (cookieShuf < 0x03 || cookieShuf > 0x14 || cookieSize < 0xf0 || cookieSize > 0x200) throw new InvalidOperationException("Unsupportd eReader format"); byte[] input = desEngine.TransformFinalBlock(data.Copy(-cookieSize), 0, cookieSize); byte[] r = UnshuffData(input.SubRange(0, -8), cookieShuf); //using (var stream = new FileStream(pdb.Filename+".eReaderSection1Dump", FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) stream.Write(r, 0, r.Length); byte[] userKeyPart1 = Encoding.ASCII.GetBytes(FixUserName(name)); byte[] userKeyPart2 = Encoding.ASCII.GetBytes(ccNumber.ToCharArray().Copy(-8)); long userKey; using (var stream1 = new MemoryStream(userKeyPart1)) using (var stream2 = new MemoryStream(userKeyPart2)) { userKey = new CRC32().GetCrc32(stream1) & 0xffffffff; userKey = userKey << 32 | new CRC32().GetCrc32(stream2) & 0xffffffff; } var drmSubVersion = (ushort)(r[0] << 8 | r[1]); numTextPages = (ushort)(r[2] << 8 | r[3]) - 1; flags = r[4] << 24 | r[5] << 16 | r[6] << 8 | r[7]; firstImagePage = (ushort)(r[24] << 8 | r[25]); numImagePages = (ushort)(r[26] << 8 | r[27]); if ((flags & ReqdFlags) != ReqdFlags) throw new InvalidOperationException(string.Format("Unsupported flags combination: {0:x8}", flags)); byte[] userKeyArray = BitConverter.GetBytes(userKey); if (BitConverter.IsLittleEndian) userKeyArray = userKeyArray.Reverse(); desEngine = GetDesEngine(userKeyArray); byte[] encryptedKey = new byte[0], encryptedKeySha = new byte[0]; if (eReaderPdb.CompressionMethod == EReaderCompression.Drm1) { if (drmSubVersion != 13) throw new InvalidOperationException(string.Format("Unknown eReader DRM subversion ID: {0}", drmSubVersion)); encryptedKey = r.Copy(44, 8); encryptedKeySha = r.Copy(52, 20); } else if (eReaderPdb.CompressionMethod == EReaderCompression.Drm2) { encryptedKey = r.Copy(172, 8); encryptedKeySha = r.Copy(56, 20); } contentKey = desEngine.TransformFinalBlock(encryptedKey, 0, encryptedKey.Length); byte[] checkHash = SHA1.Create().ComputeHash(contentKey); if (!encryptedKeySha.IsEqualTo(checkHash)) { var s = new StringBuilder(); for (var x = 0; x < (r.Length - 8); x += 2) { for (var y = 0; y < (x - 20); y += 2) if (TestKeyDecryption(desEngine, r, x, y)) s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y); for (var y = x + 8; y < (r.Length - 20); y += 2) if (TestKeyDecryption(desEngine, r, x, y)) s.AppendFormat("keyOffset={0}, hashOffset={1}\n", x, y); } if (s.Length > 0) throw new InvalidDataException("Key and/or KeyHash offset mismatch. Possible values:\n\n" + s); throw new ArgumentException("Incorrect Name of Credit Card number."); } contentDecryptor = GetDesEngine(contentKey); }