private byte[] DeriveKeyEncryptionKey_v1(KeyBag item, string password) { byte[] result = default; using (var generator = new Rfc2898DeriveBytes(password, item.Salt, item.Iterations, HashAlgorithmName.SHA1)) { result = generator.GetBytes(32); } return(result); }
private static IReadOnlyDictionary <ProtectionClass, byte[]> UnwrapClassKeys(KeyBag item, byte[] kek) { var result = new Dictionary <ProtectionClass, byte[]>(); foreach (var wrappedKey in item.WrappedKeys) { var key = UnwrapClassKey(wrappedKey, kek); if (key != default) { result.Add(wrappedKey.ProtectionClass, key); } } return(result); }
public void UnwrapClassKeysFromKeyBag(KeyBag keyBag, string password) { if (keyBag is null) { throw new ArgumentNullException(nameof(keyBag)); } _logger.LogInformation("Unwrapping class keys"); var kek = (keyBag.DataProtection is null) ? DeriveKeyEncryptionKey_v1(keyBag, password) : DeriveKeyEncryptionKey_v2(keyBag, password); _classKeys = UnwrapClassKeys(keyBag, kek); }
private byte[] DeriveKeyEncryptionKey_v2(KeyBag item, string password) { byte[] result = default; using (var gen1 = new Rfc2898DeriveBytes(password, item.DataProtection.Dpsl, item.DataProtection.Dpic, HashAlgorithmName.SHA256)) { var derivedPasscode = gen1.GetBytes(32); using (var gen2 = new Rfc2898DeriveBytes(derivedPasscode, item.Salt, item.Iterations, HashAlgorithmName.SHA1)) { result = gen2.GetBytes(32); } } return(result); }
public static void SetValue(this KeyBag item, string blockIdentifier, ReadOnlySpan <byte> value) { switch (blockIdentifier) { case KeyBagConstants.VersionTag: item.Version = BinaryPrimitives.ReadInt32BigEndian(value); break; case KeyBagConstants.TypeTag: item.KeyBagType = (KeyBagType)BinaryPrimitives.ReadInt32BigEndian(value); break; case KeyBagConstants.UuidTag: item.Uuid = ReadGuidBigEndian(value); break; case KeyBagConstants.HmckTag: item.HMCK = value.ToArray(); break; case KeyBagConstants.WrapTag: item.Wrap = BinaryPrimitives.ReadInt32BigEndian(value); break; case KeyBagConstants.SaltTag: item.Salt = value.ToArray(); break; case KeyBagConstants.IterTag: item.Iterations = BinaryPrimitives.ReadInt32BigEndian(value); break; case KeyBagConstants.DpwtTag: case KeyBagConstants.DpicTag: case KeyBagConstants.DpslTag: SetDataProtectionValue(item, blockIdentifier, value); break; default: throw new InvalidDataException($"Unexpected block identifier \"{blockIdentifier}\""); } }
public static void ConsoleWrite(this KeyBag item) { Console.WriteLine($"Version={item.Version}"); Console.WriteLine($"KeyBagType={item.KeyBagType}"); Console.WriteLine($"UUID={item.Uuid}"); Console.WriteLine("HMCK=" + CommonHelpers.ByteArrayToDebugString(item.HMCK)); Console.WriteLine($"WRAP={item.Wrap}"); Console.WriteLine("SALT=" + CommonHelpers.ByteArrayToDebugString(item.Salt)); Console.WriteLine($"ITER={item.Iterations}"); if (item.DataProtection != null) { Console.WriteLine($"DPWT={item.DataProtection.Dpwt}"); Console.WriteLine($"DPIC={item.DataProtection.Dpic}"); Console.WriteLine($"DPSL={item.DataProtection.Dpsl}"); } foreach (var key in item.WrappedKeys) { key.ConsoleWrite(); } }
private static void SetDataProtectionValue(KeyBag item, string blockIdentifier, ReadOnlySpan <byte> value) { if (item.DataProtection == null) { item.DataProtection = new DataProtectionKeyData(); } switch (blockIdentifier) { case KeyBagConstants.DpwtTag: item.DataProtection.Dpwt = BinaryPrimitives.ReadInt32BigEndian(value); break; case KeyBagConstants.DpicTag: item.DataProtection.Dpic = BinaryPrimitives.ReadInt32BigEndian(value); break; case KeyBagConstants.DpslTag: item.DataProtection.Dpsl = value.ToArray(); break; default: throw new InvalidDataException($"Unexpected block identifier \"{blockIdentifier}\""); } }
public static KeyBag Read(byte[] data) { if (data is null) { throw new ArgumentNullException(nameof(data)); } KeyBag result = default; var state = ReaderState.Invalid; KeyBagEntry currentKey = default; var keys = new List <KeyBagEntry>(); var length = data.Length; var position = 0; while (position < length) { var blockIdentifier = Encoding.ASCII.GetString(data, position, 4); position += 4; var blockLength = BinaryPrimitives.ReadInt32BigEndian(data.AsSpan(position, 4)); position += 4; var value = data.AsSpan(position, blockLength); if (state == ReaderState.Invalid) { state = ReaderState.ReadHeader; } if (state == ReaderState.ReadHeader) { if (result is null) { result = new KeyBag(); } if (blockIdentifier == KeyBagConstants.UuidTag && result.Uuid != Guid.Empty) { state = ReaderState.ReadKeyBagEntry; } else { result.SetValue(blockIdentifier, value); } } if (state == ReaderState.ReadKeyBagEntry) { if (blockIdentifier == KeyBagConstants.UuidTag) { if (currentKey != null) { keys.Add(currentKey); } currentKey = new KeyBagEntry(); } currentKey.SetValue(blockIdentifier, value); } position += blockLength; } if (result != null) { if (currentKey != null) { keys.Add(currentKey); } result.WrappedKeys = keys.ToArray(); } return(result); }