Table of Contents
Summary
There are two separate layers of encryption on a Swank LYNK order.
-
The key.xml at the drive root is AES symmetrically encrypted with a customer-specific key that Swank creates. It is base64 encoded and will be delivered to you securely.
The parameters are AES-256 (32 byte key), CBC cipher mode, PKCS7 padding, and the first 16 bytes of the encrypted file are the initialization vector rather than content.
Once you have key.xml open, the individual movie keys inside it (the SK values) are encrypted by Samsung's packaging tool under Samsung's own key. Pass them straight through to the LYNK DRM server untouched - you will not be able to decrypt them, and you do not need to. If the LYNK DRM server rejects them, you would need to contact Samsung support.
Example processes are provided below using PowerShell, GitBash, and C# to decrypt key.xml, but you can devise whatever method works best for your organization using these concepts.
What you will need before you begin:
- Common Tools for AES / File Inspection / Crypto (macOS, Linux, Windows)
Platform Crypto Tools Hex Tools Base64 Tools Linux OpenSSL, dd xxd, hexdump base64 macOS OpenSSL, dd xxd base64 Windows (Git Bash) OpenSSL xxd base64 Windows (PowerShell) OpenSSL Format-Hex certutil WSL Same as Linux Same as Linux Same as Linux
- The AES‑256‑CBC encrypted file named
key.xml - The Base64‑encoded AES‑256 Samsung LYNK key from Swank
- Note: The first 16 bytes of key.xml are the IV (Initialization Vector)
Git Bash Decryption Process
STEP 1 — Convert your Base64 key → Hex
Note: you need to put in your Samsung LYNK key where it states YOURBASE64KEY.
echo "<YOURBASE64KEY>" | base64 -d | xxd -p -c 256
Save this hex key. You’ll need it later.
STEP 2 — Extract the IV (first 16 bytes)
Note: If you are not working from the path your key.xml resides, you would need to include a path.
dd if=key.xml of=iv.bin bs=1 count=16
Convert IV to hex:
xxd -p iv.bin
Save the converted IV output from this command. You’ll need it later.
STEP 3 — Extract the encrypted payload
Remove the IV from the input file so OpenSSL decrypts only the ciphertext:
dd if=key.xml of=encrypted.bin bs=1 skip=16
You now have:
- The encrypted XML: encrypted.bin
- The IV: Saved from Step 2
- The hex AES‑256 key: Saved from Step 1
STEP 4 — Decrypt using OpenSSL (AES‑256‑CBC)
Replace <HEX_KEY> with your 64‑character hex key.\ Replace <HEX_IV> with your 32‑character hex IV.
openssl aes-256-cbc -d \ -in encrypted.bin \ -out keydecrypted.xml \ -K <HEXKEY> \ -iv <HEX_IV>
Your decrypted XML file should now be in the keydecrypted.xml file.
Note: The file will be saved in the directory you run this last command in, unless you specify the path.
PowerShell Decryption Process
Note: PowerShell requires OpenSSL to be installed. You can download prebuilt binaries from other third-party sources.
STEP 1 — Convert your Base64 key → Hex
Note: You will need to put in your Samsung LYNK key where it states YOURBASE64KEY.
$hexKey = [System.BitConverter]::ToString([System.Convert]::FromBase64String("YOURBASE64KEY")).Replace("-", "")
STEP 2 — Extract the IV (first 16 bytes)
Note: You will need to put in the path to your key.xml where it states YOURPATH on the first line.
$bytes = [System.IO.File]::ReadAllBytes("YOURPATH/key.xml")
$ivBytes = $bytes[0..15]
$cipher = $bytes[16..($bytes.Length-1)]
[IO.File]::WriteAllBytes("iv.bin", $ivBytes)
[IO.File]::WriteAllBytes("encrypted.bin", $cipher)
$hexIV = ([System.BitConverter]::ToString($ivBytes)).Replace("-", "")
You now have:
- The encrypted XML: encrypted.bin
- The IV: $hexIV
- The hex AES‑256 key: $hexKey
STEP 3 — Decrypt using OpenSSL (AES‑256‑CBC)
Note: You may need to alter your path to openssl.exe
& "C:\Program Files\OpenSSL-Win64\bin\openssl.exe" aes-256-cbc -d -in encrypted.bin -out key_decryptedPS.xml -K $hexKey -iv $hexIV
Your decrypted XML file should now be in the keydecrypted.xml file.
Note: The file will be saved in the directory you run this last command in, unless you specify the path.
Sample C# Class
using System.Security.Cryptography;
using System.Text;
public class CustomDecryptor
{
private readonly Aes _aesManaged;
public CustomDecryptor(byte[] key)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
if (key.Length != 32)
throw new ArgumentOutOfRangeException(nameof(key), "Key must be 32 bytes in length.");
_aesManaged = Aes.Create() ?? throw new InvalidOperationException("Failed to create AES instance.");
_aesManaged.Key = key;
_aesManaged.Mode = CipherMode.CBC;
_aesManaged.Padding = PaddingMode.PKCS7;
}
public string DecryptAsString(byte[] buffer)
{
byte[] decryptedBuffer = Decrypt(buffer);
return Encoding.UTF8.GetString(decryptedBuffer);
}
public byte[] Decrypt(byte[] buffer)
{
if (buffer == null || buffer.Length == 0)
return Array.Empty<byte>();
using var input = new MemoryStream(buffer);
using var output = new MemoryStream();
Decrypt(input, output);
return output.ToArray();
}
private void Decrypt(Stream input, Stream output)
{
byte[] iv = new byte[16]; // first 16 bytes of the payload are the IV
input.Read(iv, 0, iv.Length);
_aesManaged.IV = iv;
using var cryptoStream = new CryptoStream(output, _aesManaged.CreateDecryptor(), CryptoStreamMode.Write);
input.CopyTo(cryptoStream);
cryptoStream.FlushFinalBlock();
}
}
Sample usage:
var base64Key = "CUSTOMER UNIQUE KEY GOES HERE"; // key swank provides to customer
var decryptor = new CustomDecryptor(Convert.FromBase64String(base64Key));
var decrypted = decryptor.DecryptAsString(File.ReadAllBytes("key.xml"));
Comments
0 comments
Please sign in to leave a comment.