Upload files to 'DRMDecryptSmooth'
parent
6d797244a0
commit
bb6bc660b6
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
||||
</startup>
|
||||
</configuration>
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{F63FEE07-8040-4F89-8166-E7ACBE724877}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DRMDecryptSmooth</RootNamespace>
|
||||
<AssemblyName>DRMDecryptSmooth</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the MIT License.
|
||||
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace DRMDecryptSmooth
|
||||
{
|
||||
// This application demonstrates how to use bento4 to decrypt a Smooth Streaming PlayReady asset.
|
||||
|
||||
class Program
|
||||
{
|
||||
// Location of mp4decrypt from Bento4
|
||||
const string mp4decrypt = @"C:\Temp\Bento4-SDK-1-5-1-620.x86-microsoft-win32-vs2010\bin\mp4decrypt.exe";
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// MANTATORY: Please insert here the key seed in base64 format. Example : "XVBovsmzhP9gRIZxWfFta3VVRPzVEWmJsazEJ46I"
|
||||
string keySeed = "";
|
||||
|
||||
// MANTATORY: Please insert here the key id in guid format. Example : "8d080fae-2b52-4427-9f2c-f2ea93141b45"
|
||||
string keyId = "";
|
||||
|
||||
// Folder where is the asset to process
|
||||
string inputAsset = @"C:\source";
|
||||
|
||||
// Folder where the decrypted asset will be copied (folder must exist)
|
||||
string outputAsset = inputAsset + @"\decrypted";
|
||||
Directory.CreateDirectory(outputAsset);
|
||||
|
||||
// let's calculate the key
|
||||
string key = ByteArrayToHexString(GeneratePlayReadyContentKey(Convert.FromBase64String(keySeed), new Guid(keyId)));
|
||||
|
||||
var files = Directory.GetFiles(inputAsset);
|
||||
|
||||
foreach (var filePath in files)
|
||||
{
|
||||
string ext = Path.GetExtension(filePath).ToLower();
|
||||
|
||||
if (ext == ".isma" || ext == ".ismv")
|
||||
{
|
||||
// we need to decrypt the PIFF file
|
||||
string keyArg = " --key {0}:{1}";
|
||||
string arguments = "--show-progress";
|
||||
var piffFilesCount = files.Where(f => Path.GetExtension(f).ToLower() == ".isma" || Path.GetExtension(f).ToLower() == ".ismv").Count();
|
||||
for (int i = 1; i <= piffFilesCount; i++)
|
||||
{
|
||||
arguments += string.Format(keyArg, i, key);
|
||||
}
|
||||
arguments += " " + filePath + " " + outputAsset + @"\" + Path.GetFileName(filePath);
|
||||
Console.WriteLine($"Decrypting {Path.GetFileName(filePath)}");
|
||||
ExecuteCommandSync(mp4decrypt + " " + arguments);
|
||||
}
|
||||
else if (ext == ".ismc")
|
||||
{
|
||||
// let remove the Playready part in the manifest
|
||||
var manifest = XDocument.Load(filePath);
|
||||
var smoothmedia = manifest.Element("SmoothStreamingMedia");
|
||||
var videotrack = smoothmedia.Element("Protection");
|
||||
videotrack.Remove();
|
||||
Console.WriteLine($"Modifying {Path.GetFileName(filePath)}");
|
||||
manifest.Save(outputAsset + @"\" + Path.GetFileName(filePath));
|
||||
}
|
||||
else
|
||||
{
|
||||
File.Copy(filePath, outputAsset + @"\" + Path.GetFileName(filePath), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public void ExecuteCommandSync(object command)
|
||||
{
|
||||
try
|
||||
{
|
||||
// create the ProcessStartInfo using "cmd" as the program to be run,
|
||||
// and "/c " as the parameters.
|
||||
// Incidentally, /c tells cmd that we want it to execute the command that follows,
|
||||
// and then exit.
|
||||
System.Diagnostics.ProcessStartInfo procStartInfo =
|
||||
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
|
||||
|
||||
// The following commands are needed to redirect the standard output.
|
||||
// This means that it will be redirected to the Process.StandardOutput StreamReader.
|
||||
procStartInfo.RedirectStandardOutput = true;
|
||||
procStartInfo.UseShellExecute = false;
|
||||
// Do not create the black window.
|
||||
procStartInfo.CreateNoWindow = true;
|
||||
// Now we create a process, assign its ProcessStartInfo and start it
|
||||
System.Diagnostics.Process proc = new System.Diagnostics.Process();
|
||||
proc.StartInfo = procStartInfo;
|
||||
proc.Start();
|
||||
// Get the output into a string
|
||||
string result = proc.StandardOutput.ReadToEnd();
|
||||
// Display the command output.
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
catch ()
|
||||
{
|
||||
// Log the exception
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] GeneratePlayReadyContentKey(byte[] keySeed, Guid keyId)
|
||||
{
|
||||
const int DRM_AES_KEYSIZE_128 = 16;
|
||||
byte[] contentKey = new byte[DRM_AES_KEYSIZE_128];
|
||||
//
|
||||
// Truncate the key seed to 30 bytes, key seed must be at least 30 bytes long.
|
||||
//
|
||||
byte[] truncatedKeySeed = new byte[30];
|
||||
Array.Copy(keySeed, truncatedKeySeed, truncatedKeySeed.Length);
|
||||
//
|
||||
// Get the keyId as a byte array
|
||||
//
|
||||
byte[] keyIdAsBytes = keyId.ToByteArray();
|
||||
//
|
||||
// Create sha_A_Output buffer. It is the SHA of the truncatedKeySeed and the keyIdAsBytes
|
||||
//
|
||||
SHA256Managed sha_A = new SHA256Managed();
|
||||
sha_A.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
|
||||
sha_A.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length);
|
||||
byte[] sha_A_Output = sha_A.Hash;
|
||||
//
|
||||
// Create sha_B_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes, and
|
||||
// the truncatedKeySeed again.
|
||||
//
|
||||
SHA256Managed sha_B = new SHA256Managed();
|
||||
sha_B.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
|
||||
sha_B.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0);
|
||||
sha_B.TransformFinalBlock(truncatedKeySeed, 0, truncatedKeySeed.Length);
|
||||
byte[] sha_B_Output = sha_B.Hash;
|
||||
//
|
||||
// Create sha_C_Output buffer. It is the SHA of the truncatedKeySeed, the keyIdAsBytes,
|
||||
// the truncatedKeySeed again, and the keyIdAsBytes again.
|
||||
//
|
||||
SHA256Managed sha_C = new SHA256Managed();
|
||||
sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
|
||||
sha_C.TransformBlock(keyIdAsBytes, 0, keyIdAsBytes.Length, keyIdAsBytes, 0);
|
||||
sha_C.TransformBlock(truncatedKeySeed, 0, truncatedKeySeed.Length, truncatedKeySeed, 0);
|
||||
sha_C.TransformFinalBlock(keyIdAsBytes, 0, keyIdAsBytes.Length);
|
||||
byte[] sha_C_Output = sha_C.Hash;
|
||||
for (int i = 0; i < DRM_AES_KEYSIZE_128; i++)
|
||||
{
|
||||
contentKey[i] = Convert.ToByte(sha_A_Output[i] ^ sha_A_Output[i + DRM_AES_KEYSIZE_128]
|
||||
^ sha_B_Output[i] ^ sha_B_Output[i + DRM_AES_KEYSIZE_128]
|
||||
^ sha_C_Output[i] ^ sha_C_Output[i + DRM_AES_KEYSIZE_128]);
|
||||
}
|
||||
return contentKey;
|
||||
}
|
||||
|
||||
public static string ByteArrayToHexString(byte[] bytes)
|
||||
{
|
||||
return string.Join(string.Empty, Array.ConvertAll(bytes, b => b.ToString("X2")));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue