Skip to content

Instantly share code, notes, and snippets.

@nwrox
Created April 23, 2020 23:04
Show Gist options
  • Save nwrox/82eb06ef7124096603c2dff01a977452 to your computer and use it in GitHub Desktop.
Save nwrox/82eb06ef7124096603c2dff01a977452 to your computer and use it in GitHub Desktop.
public byte[] Unprotect(byte[] protectedData)
{
if (protectedData?.Length < 1)
{
return null;
}
var keyId = new byte[16];
var magicHeader = new byte[4];
var purposes = _appOptions.CookieAadPurposes;
var purposeLen = (uint)purposes.Count;
Buffer.BlockCopy(protectedData, 0, magicHeader, 0, magicHeader.Length);
Buffer.BlockCopy(protectedData, magicHeader.Length, keyId, 0, keyId.Length);
// purpose length byte array
var pByteArrLen = new byte[]
{
(byte)(purposeLen >> 24),
(byte)(purposeLen >> 16),
(byte)(purposeLen >> 8),
(byte)(purposeLen)
};
// 7-bit encoded purpose length + purpose byte array
var pByteArr = purposes.SelectMany(
x => Write7BitEncodedInt(x.Length)
.Concat(
Encoding.UTF8
.GetBytes(x)
)
).ToArray();
var offset = magicHeader.Length + keyId.Length;
var limit = protectedData.Length - offset;
ArraySegment<byte> addAuthData = new ArraySegment<byte>(
magicHeader.Concat(keyId)
.Concat(pByteArrLen)
.Concat(pByteArr)
.ToArray()
);
ArraySegment<byte> ciphertext = new ArraySegment<byte>(
protectedData, offset, limit
);
return _keyMgr?.GetAllKeys()
?.FirstOrDefault(k => k.KeyId == new Guid(keyId))
?.CreateEncryptor()
?.Decrypt(ciphertext, addAuthData) ?? null;
}
// https://referencesource.microsoft.com/#mscorlib/system/io/binarywriter.cs,2daa1d14ff1877bd
private IEnumerable<byte> Write7BitEncodedInt(int value)
{
var x = new List<byte>();
uint v = (uint)value;
while (v >= 0x80)
{
x.Add((byte)(v | 0x80));
v >>= 7;
}
x.Add((byte)v);
return x;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment