diff --git a/DVD/CSS.cs b/DVD/CSS.cs
index 8af8d15..56869fb 100644
--- a/DVD/CSS.cs
+++ b/DVD/CSS.cs
@@ -662,6 +662,46 @@ public class CSS
return decryptedBuffer;
}
+ /// Takes a sector and a decrypted title key and returns the decrypted sector.
+ /// Encrypted sector data.
+ /// The Copyright Management Information.
+ /// The encryption keys.
+ /// Number of sectors in sectorData.
+ /// Size of one sector.
+ /// The decrypted sector.
+ public static byte[] DecryptSectorLong(byte[] sectorData, byte[] keyData, byte[]? cmiData, uint blocks = 1,
+ uint blockSize = 2048)
+ {
+ // None of the sectors are encrypted
+ if(cmiData != null && cmiData.All(static cmi => (cmi & 0x80) >> 7 == 0) || keyData.All(static k => k == 0))
+ return sectorData;
+
+ var decryptedBuffer = new byte[sectorData.Length];
+
+ for(uint i = 0; i < blocks; i++)
+ {
+ byte[] currentKey = keyData.Skip((int)(i * 5)).Take(5).ToArray();
+ byte[] currentPrefix = sectorData.Skip((int)(i * 2064)).Take(12).ToArray();
+ byte[] currentSuffix = sectorData.Skip((int)(2060 + i * 2064)).Take(4).ToArray();
+ byte[] currentSector = sectorData.Skip((int)(12 + i * blockSize + (16 * i))).Take((int)blockSize).ToArray();
+
+ Array.Copy(currentPrefix, 0, decryptedBuffer, (int)(i * 2064), 12);
+ Array.Copy(currentSuffix, 0, decryptedBuffer, (int)(2060 + i * 2064), 4);
+
+ if(!IsEncrypted(cmiData?[i], currentKey, currentSector))
+ {
+ Array.Copy(currentSector, 0, decryptedBuffer, (int)(12 + i * blockSize + (16 * i)), blockSize);
+
+ continue;
+ }
+
+ Array.Copy(UnscrambleSector(currentKey, currentSector), 0, decryptedBuffer,
+ (int)(12 + i * blockSize + (16 * i)), blockSize);
+ }
+
+ return decryptedBuffer;
+ }
+
///
/// Unscrambles a DVD sector with a title key.
///