private static byte[] EncryptPekList(byte[] cleartextBlob, PekListVersion pekListVersion, byte[] bootKey = null) { // Do not encrypt by default. PekListFlags flags = PekListFlags.Clear; if (bootKey != null) { // Encrypt if the boot key is provided. Validator.AssertLength(bootKey, BootKeyRetriever.BootKeyLength, "bootKey"); flags = PekListFlags.Encrypted; } // Generate random salt byte[] salt = GenerateSalt(SaltSize); // Encode the data structure using (MemoryStream stream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(stream)) { // Header writer.Write((uint)pekListVersion); writer.Write((uint)flags); writer.Write(salt); // Data switch (flags) { case PekListFlags.Clear: writer.Write(cleartextBlob); break; case PekListFlags.Encrypted: byte[] encryptedBlob; switch (pekListVersion) { case PekListVersion.W2016: encryptedBlob = EncryptUsingAES(cleartextBlob, salt, bootKey); writer.Write(encryptedBlob); // Add 16B zeroed padding. The purpose in unknown and NTDS even works without it. byte[] padding = new byte[PekListV3PaddingSize]; writer.Write(padding); break; case PekListVersion.W2k: encryptedBlob = EncryptUsingRC4(cleartextBlob, salt, bootKey, BootKeySaltHashRounds); writer.Write(encryptedBlob); break; default: // TODO: Extract as a resource. throw new FormatException("Unsupported PEK list version."); } break; } } return(stream.ToArray()); } }
private static byte[] EncryptPekList(byte[] cleartextBlob, PekListVersion pekListVersion, byte[] bootKey = null) { // Do not encrypt by default. PekListFlags flags = PekListFlags.Clear; if (bootKey != null) { // Encrypt if the boot key is provided. Validator.AssertLength(bootKey, BootKeyRetriever.BootKeyLength, "bootKey"); flags = PekListFlags.Encrypted; } // Generate random salt byte[] salt = new byte[SaltSize]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(salt); } // Encode the data structure using (MemoryStream stream = new MemoryStream()) { using (BinaryWriter writer = new BinaryWriter(stream)) { // Header writer.Write((uint)pekListVersion); writer.Write((uint)flags); writer.Write(salt); // Data switch (flags) { case PekListFlags.Clear: writer.Write(cleartextBlob); break; case PekListFlags.Encrypted: byte[] encryptedBlob; switch (pekListVersion) { case PekListVersion.W2016: encryptedBlob = EncryptUsingAES(cleartextBlob, salt, bootKey, PaddingMode.Zeros); break; case PekListVersion.W2k: encryptedBlob = EncryptUsingRC4(cleartextBlob, salt, bootKey, BootKeySaltHashRounds); break; default: // TODO: Extract as a resource. throw new FormatException("Unsupported PEK list version."); } writer.Write(encryptedBlob); break; } } return(stream.ToArray()); } }
private static byte[] EncryptPekList(byte[] cleartextBlob, byte[] bootKey = null) { // Do not encrypt by default. PekListFlags flags = PekListFlags.Clear; if (bootKey != null) { // Encrypt if the boot key is provided. Validator.AssertLength(bootKey, BootKeyRetriever.BootKeyLength, "bootKey"); flags = PekListFlags.Encrypted; } int bufferSize = EncryptedPekListOffset + cleartextBlob.Length; byte[] buffer = new byte[bufferSize]; // Generate random salt byte[] salt = new byte[SaltSize]; using (var rng = new RNGCryptoServiceProvider()) { rng.GetBytes(salt); } using (MemoryStream stream = new MemoryStream(buffer)) { using (BinaryWriter writer = new BinaryWriter(stream)) { // Header // TODO: Write version corresponding to the DB or original version!!! writer.Write((uint)PekListVersion.W2k); writer.Write((uint)flags); writer.Write(salt); // Data switch (flags) { case PekListFlags.Clear: writer.Write(cleartextBlob); break; case PekListFlags.Encrypted: byte[] encryptedBlob = EncryptUsingRC4(cleartextBlob, salt, bootKey, BootKeySaltHashRounds); writer.Write(encryptedBlob); break; } } } return(buffer); }