private void FinishEncryption() { TEncryptionParameters EncParams = GetEncryptionParams(Protection); AesManaged EncEngine = TEncryptionUtils.CreateEngine(EncParams); TAgileEncryptionKey DataKey = TAgileEncryptionKey.CreateForWriting(null, EncEngine.KeySize / 8); DataKey.Key = TEncryptionUtils.GetRandom(DataKey.KeySizeInBytes); TAgileEncryptionKey KeyKey = TAgileEncryptionKey.CreateForWriting(Protection.OpenPassword, EncEngine.KeySize / 8); byte[] WorkLen = new byte[8]; BitOps.SetCardinal(WorkLen, 0, WorkingStream.Length - WorkStreamZeroPos); EncryptStream(EncEngine, DataKey, WorkLen); using (MemoryStream ms = new MemoryStream()) { using (TOle2File Ole2File = new TOle2File(GetEmptyEncryptedFile())) { Ole2File.PrepareForWrite(ms, XlsxConsts.EncryptionInfoString, new string[0]); CreateInfoStream(Ole2File, EncEngine, EncParams, KeyKey, DataKey); } ms.Position = 0; using (TOle2File Ole2File = new TOle2File(ms)) { Ole2File.PrepareForWrite(TargetStream, XlsxConsts.ContentString, new string[0]); WorkingStream.Position = 0; TEncryptionUtils.CopyStream(WorkingStream, Ole2File); } } }
private static void WriteAgileCipherParams(XmlWriter xml, TEncryptionParameters EncParams, TAgileEncryptionKey Key) { xml.WriteAttributeString("saltSize", Convert.ToString(Key.Salt.Length, CultureInfo.InvariantCulture)); xml.WriteAttributeString("blockSize", Convert.ToString(Key.BlockSize, CultureInfo.InvariantCulture)); xml.WriteAttributeString("keyBits", Convert.ToString(Key.KeySizeInBytes * 8, CultureInfo.InvariantCulture)); xml.WriteAttributeString("hashSize", Convert.ToString(Key.HashSizeBytes(), CultureInfo.InvariantCulture)); //sha1 hash size xml.WriteAttributeString("cipherAlgorithm", "AES"); switch (EncParams.ChainingMode) { case CipherMode.CBC: xml.WriteAttributeString("cipherChaining", "ChainingModeCBC"); break; case CipherMode.CFB: xml.WriteAttributeString("cipherChaining", "ChainingModeCFB"); break; case CipherMode.CTS: case CipherMode.ECB: case CipherMode.OFB: default: XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); break; } xml.WriteAttributeString("hashAlgorithm", "SHA1"); xml.WriteAttributeString("saltValue", Convert.ToBase64String(Key.Salt)); }
private static Stream DecryptStream(TOle2File DataStream, TEncryptionParameters EncParams, TEncryptionKey Key) { DataStream.SelectStream(XlsxConsts.ContentString); byte[] EncryptedSize = new byte[8]; DataStream.Read(EncryptedSize, EncryptedSize.Length); AesManaged Engine = null; ICryptoTransform Decryptor = null; try { Engine = TEncryptionUtils.CreateEngine(EncParams); if (!Key.VariableIV) { Decryptor = Engine.CreateDecryptor(Key.Key, Key.IV); } return(new TXlsxCryptoStreamReader(DataStream, BitOps.GetCardinal(EncryptedSize, 0), Engine, Decryptor, Key)); } catch { if (Engine != null) { ((IDisposable)Engine).Dispose(); } if (Decryptor != null) { Decryptor.Dispose(); } throw; } }
internal override bool VerifyPass(string Password, TEncryptionParameters EncParams, TEncryptionKey Key) { if (!base.VerifyPass(Password, EncParams, Key)) { return(false); } Key.CalcKey(TStandardEncryptionKey.BlockKey, null); byte[] DecriptedVerifier; byte[] DecriptedVerifierHash; using (AesManaged Engine = TEncryptionUtils.CreateEngine(EncParams)) { using (ICryptoTransform Decryptor = Engine.CreateDecryptor(Key.Key, Key.IV)) { DecriptedVerifier = DecryptBytes(EncryptedVerifier, Decryptor, -1); DecriptedVerifierHash = DecryptBytes(EncryptedVerifierHash, Decryptor, -1); } } using (HashAlgorithm hasher = TEncryptionKey.CreateHasher()) { byte[] DecriptedVerifierHash2 = hasher.ComputeHash(DecriptedVerifier); if (!FlxUtils.CompareMem(DecriptedVerifierHash, 0, DecriptedVerifierHash2, 0, VerifierHashSizeBytes)) { return(false); } } return(true); }
private static void ReadAgileCipherParams(XmlReader xml, TEncryptionParameters EncParams, TEncryptionKey Key) { int SaltSize = Convert.ToInt32(xml.GetAttribute("saltSize"), CultureInfo.InvariantCulture); int BlockSize = Convert.ToInt32(xml.GetAttribute("blockSize"), CultureInfo.InvariantCulture); Key.BlockSize = BlockSize; if (BlockSize != 0x10) { XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); } int KeyBits = Convert.ToInt32(xml.GetAttribute("keyBits"), CultureInfo.InvariantCulture); Key.KeySizeInBytes = KeyBits / 8; switch (KeyBits) { case 128: EncParams.Algorithm = TEncryptionAlgorithm.AES_128; break; case 192: EncParams.Algorithm = TEncryptionAlgorithm.AES_192; break; case 256: EncParams.Algorithm = TEncryptionAlgorithm.AES_256; break; default: XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); break; } string CipherAlgo = xml.GetAttribute("cipherAlgorithm"); if (!string.Equals(CipherAlgo, "AES", StringComparison.InvariantCulture)) { XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); } string CipherChaining = xml.GetAttribute("cipherChaining"); switch (CipherChaining) { case "ChainingModeCBC": EncParams.ChainingMode = CipherMode.CBC; break; case "ChainingModeCFB": EncParams.ChainingMode = CipherMode.CFB; break; default: XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); break; } string HashAlgorithm = xml.GetAttribute("hashAlgorithm"); if (HashAlgorithm != "SHA1" && HashAlgorithm != "SHA-1") { XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); } Key.Salt = Convert.FromBase64String(xml.GetAttribute("saltValue")); if (Key.Salt == null || SaltSize != Key.Salt.Length) { XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); } }
public static TEncryptionParameters CreateStandard(TEncryptionAlgorithm aAlgorithm) { TEncryptionParameters Result = new TEncryptionParameters(); Result.Algorithm = aAlgorithm; Result.ChainingMode = CipherMode.ECB; return(Result); }
private static TEncryptionParameters GetEncryptionParams(TProtection Protection) { TEncryptionParameters Result = new TEncryptionParameters(); Result.Algorithm = Protection.EncryptionAlgorithmXlsx; Result.ChainingMode = CipherMode.CBC; Result.Padding = PaddingMode.Zeros; return(Result); }
public static AesManaged CreateEngine(TEncryptionParameters EncryptionParameters) { AesManaged Engine = new AesManaged(); //using Engine.KeySize = CalcKeySizeInBits(EncryptionParameters); Engine.Padding = EncryptionParameters.Padding; Engine.Mode = EncryptionParameters.ChainingMode; return(Engine); }
private void CreateInfoStream(TOle2File DataStream, AesManaged EncEngine, TEncryptionParameters EncParams, TAgileEncryptionKey KeyKey, TAgileEncryptionKey DataKey) { DataStream.Write16(0x0004); DataStream.Write16(0x0004); DataStream.Write32(0x00040); byte[] InfoStreamXml = GetInfoStreamXml(EncEngine, EncParams, KeyKey, DataKey); DataStream.Write(InfoStreamXml, InfoStreamXml.Length); byte[] pad = new byte[4098 - InfoStreamXml.Length]; //Our Ole2 implementation will fill a sector with 0 so it doesn't go to the ministream. Those 0 will confuse Excel, so we will write spaces. for (int i = 0; i < pad.Length; i++) { pad[i] = 32; } DataStream.Write(pad, pad.Length); }
internal virtual bool VerifyPass(string Password, TEncryptionParameters EncParams, TEncryptionKey Key) { if (Password == null) { XlsMessages.ThrowException(XlsErr.ErrInvalidPassword); } if (Password.Length > 255) { XlsMessages.ThrowException(XlsErr.ErrPasswordTooLong); } Key.Password = Encoding.Unicode.GetBytes(Password); Key.PreCalcKey(); return(true); }
private static int CalcKeySizeInBits(TEncryptionParameters EncryptionParameters) { switch (EncryptionParameters.Algorithm) { case TEncryptionAlgorithm.AES_128: return(0x80); case TEncryptionAlgorithm.AES_192: return(0xC0); case TEncryptionAlgorithm.AES_256: return(0x100); } XlsMessages.ThrowException(XlsErr.ErrNotSupportedEncryption); return(0); }
private static Stream ReadAgileEncryptionInfo(TOle2File DataStream, TEncryptionData Encryption) { byte[] Enc = new byte[DataStream.Length - DataStream.Position]; DataStream.Read(Enc, Enc.Length); TEncryptionParameters DataEncParams = new TEncryptionParameters(); TAgileEncryptionKey DataKey = new TAgileEncryptionKey(); TAgileEncryptionVerifier KeyVerifier = new TAgileEncryptionVerifier(); TEncryptionParameters KeyEncParams = new TEncryptionParameters(); TAgileEncryptionKey KeyKey = new TAgileEncryptionKey(); using (MemoryStream ms = new MemoryStream(Enc)) { using (XmlReader xml = XmlReader.Create(ms)) { xml.ReadStartElement("encryption"); //goes to keyData ReadAgileCipherParams(xml, DataEncParams, DataKey); xml.ReadStartElement("keyData"); //goes to dataIntegrity //We are not checking data integrity at the moment. //DataIntegrity.EncryptedHMacKey = Convert.FromBase64String(xml.GetAttribute("encryptedHmacKey")); //DataIntegrity.EncryptedHmacValue = Convert.FromBase64String(xml.GetAttribute("encryptedHmacValue")); xml.ReadStartElement("dataIntegrity"); //goes to keyEncryptors xml.ReadStartElement("keyEncryptors"); //goes to keyEncryptor xml.ReadStartElement("keyEncryptor"); //goes to encryptedKey KeyKey.SpinCount = Convert.ToInt32(xml.GetAttribute("spinCount"), CultureInfo.InvariantCulture); ReadAgileCipherParams(xml, KeyEncParams, KeyKey); KeyVerifier.EncryptedVerifierHashInput = Convert.FromBase64String(xml.GetAttribute("encryptedVerifierHashInput")); KeyVerifier.EncryptedVerifierHashValue = Convert.FromBase64String(xml.GetAttribute("encryptedVerifierHashValue")); KeyVerifier.EncryptedKeyValue = Convert.FromBase64String(xml.GetAttribute("encryptedKeyValue")); } } CheckPassword(Encryption, KeyVerifier, KeyEncParams, KeyKey); DataKey.Key = KeyKey.Key; DataKey.Password = KeyKey.Password; DataKey.CalcDataIV(0); return(DecryptStream(DataStream, DataEncParams, DataKey)); }
internal override bool VerifyPass(string Password, TEncryptionParameters EncParams, TEncryptionKey Key) { if (!base.VerifyPass(Password, EncParams, Key)) { return(false); } using (AesManaged Engine = TEncryptionUtils.CreateEngine(EncParams)) { byte[] DecriptedVerifierHashInput; Key.CalcKey(TAgileEncryptionKey.VerifierHashInputBlockKey, null); using (ICryptoTransform Decryptor = Engine.CreateDecryptor(Key.Key, Key.IV)) { DecriptedVerifierHashInput = DecryptBytes(EncryptedVerifierHashInput, Decryptor, Key.Salt.Length); //this is the value padded to a blocksize multiple. We want only the Salt.Length initial bytes. DecriptedVerifierHashInput = Key.Hash(DecriptedVerifierHashInput); } byte[] DecriptedVerifierHashValue; Key.CalcKey(TAgileEncryptionKey.VerifierHashValueBlockKey, null); using (ICryptoTransform Decryptor = Engine.CreateDecryptor(Key.Key, Key.IV)) { DecriptedVerifierHashValue = DecryptBytes(EncryptedVerifierHashValue, Decryptor, DecriptedVerifierHashInput.Length); //this is the 20 byte value of the hash + 12 "0" so it goes up to 32. (32 is 2*blocksize) } if (!FlxUtils.CompareMem(DecriptedVerifierHashValue, DecriptedVerifierHashInput)) { return(false); } byte[] DecriptedKeyValue; Key.CalcKey(TAgileEncryptionKey.VerifierKeyValueBlockKey, null); using (ICryptoTransform Decryptor = Engine.CreateDecryptor(Key.Key, Key.IV)) { DecriptedKeyValue = DecryptBytes(EncryptedKeyValue, Decryptor, Key.KeySizeInBytes); } Key.Key = DecriptedKeyValue; } return(true); }
private static Stream ReadStandardEncryptionInfo(TOle2File DataStream, TEncryptionData Encryption) { byte[] RecordHeaderLen = new byte[4]; DataStream.Read(RecordHeaderLen, RecordHeaderLen.Length); long EncryptionHeaderSize = BitOps.GetCardinal(RecordHeaderLen, 0); byte[] EncryptionHeader = new byte[EncryptionHeaderSize]; DataStream.Read(EncryptionHeader, EncryptionHeader.Length); long AlgId = BitOps.GetCardinal(EncryptionHeader, 8); long KeyBits = BitOps.GetCardinal(EncryptionHeader, 16); TEncryptionParameters EncParams = TEncryptionParameters.CreateStandard(GetStandardEncAlg(AlgId)); byte[] VerifierBytes = new byte[DataStream.Length - DataStream.Position]; DataStream.Read(VerifierBytes, VerifierBytes.Length); TStandardEncryptionVerifier Verifier = ReadStandardVerifier(VerifierBytes); TEncryptionKey Key = new TStandardEncryptionKey(ReadStandardSalt(VerifierBytes), (int)KeyBits / 8); CheckPassword(Encryption, Verifier, EncParams, Key); return(DecryptStream(DataStream, EncParams, Key)); }
private static void CheckPassword(TEncryptionData Encryption, TEncryptionVerifier Verifier, TEncryptionParameters EncParams, TEncryptionKey Key) { if (Verifier.VerifyPass(XlsConsts.EmptyExcelPassword, EncParams, Key)) { return; //workbook password protected } string Password = Encryption.ReadPassword; if (Encryption.OnPassword != null) { OnPasswordEventArgs ea = new OnPasswordEventArgs(Encryption.Xls); Encryption.OnPassword(ea); Encryption.ReadPassword = ea.Password; Password = ea.Password; } if (!Verifier.VerifyPass(Password, EncParams, Key)) { XlsMessages.ThrowException(XlsErr.ErrInvalidPassword); } }
private byte[] GetInfoStreamXml(AesManaged EncEngine, TEncryptionParameters EncParams, TAgileEncryptionKey KeyKey, TAgileEncryptionKey DataKey) { const string KeyEncryptorPasswordNamespace = "http://schemas.microsoft.com/office/2006/keyEncryptor/password"; using (MemoryStream ms = new MemoryStream()) { XmlWriterSettings Settings = new XmlWriterSettings(); Settings.Encoding = new System.Text.UTF8Encoding(false); using (XmlWriter xml = XmlWriter.Create(ms, Settings)) { xml.WriteStartDocument(true); xml.WriteStartElement("encryption", "http://schemas.microsoft.com/office/2006/encryption"); xml.WriteAttributeString("xmlns", "p", null, KeyEncryptorPasswordNamespace); xml.WriteStartElement("keyData"); WriteAgileCipherParams(xml, EncParams, DataKey); xml.WriteEndElement(); xml.WriteStartElement("dataIntegrity"); byte[] HMacKeyBlockKey = new byte[] { 0x5f, 0xb2, 0xad, 0x01, 0x0c, 0xb9, 0xe1, 0xf6 }; DataKey.CalcDataIV(HMacKeyBlockKey); byte[] HMacKey = TEncryptionUtils.GetRandom((int)DataKey.HashSizeBytes()); using (ICryptoTransform Encryptor = EncEngine.CreateEncryptor(DataKey.Key, DataKey.IV)) { byte[] EncryptedHMacKey = TAgileEncryptionVerifier.EncryptBytes(HMacKey, Encryptor, DataKey.BlockSize); xml.WriteAttributeString("encryptedHmacKey", Convert.ToBase64String(EncryptedHMacKey)); } HMAC HMacCalc = new HMACSHA1(HMacKey); WorkingStream.Position = 0; byte[] HMac = HMacCalc.ComputeHash(WorkingStream); byte[] HMacValBlockKey = new byte[] { 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33 }; DataKey.CalcDataIV(HMacValBlockKey); using (ICryptoTransform Encryptor = EncEngine.CreateEncryptor(DataKey.Key, DataKey.IV)) { byte[] EncryptedHMacValue = TAgileEncryptionVerifier.EncryptBytes(HMac, Encryptor, DataKey.BlockSize); xml.WriteAttributeString("encryptedHmacValue", Convert.ToBase64String(EncryptedHMacValue)); } xml.WriteEndElement(); xml.WriteStartElement("keyEncryptors"); xml.WriteStartElement("keyEncryptor"); xml.WriteAttributeString("uri", KeyEncryptorPasswordNamespace); xml.WriteStartElement("encryptedKey", KeyEncryptorPasswordNamespace); xml.WriteAttributeString("spinCount", Convert.ToString(KeyKey.SpinCount, CultureInfo.InvariantCulture)); WriteAgileCipherParams(xml, EncParams, KeyKey); byte[] RandData = TEncryptionUtils.GetRandom(KeyKey.Salt.Length); KeyKey.CalcKey(TAgileEncryptionKey.VerifierHashInputBlockKey, null); using (ICryptoTransform Encryptor = EncEngine.CreateEncryptor(KeyKey.Key, KeyKey.IV)) { byte[] EncryptedVerifierHashInput = TAgileEncryptionVerifier.EncryptBytes(RandData, Encryptor, KeyKey.BlockSize); xml.WriteAttributeString("encryptedVerifierHashInput", Convert.ToBase64String(EncryptedVerifierHashInput)); } KeyKey.CalcKey(TAgileEncryptionKey.VerifierHashValueBlockKey, null); using (ICryptoTransform Encryptor = EncEngine.CreateEncryptor(KeyKey.Key, KeyKey.IV)) { byte[] EncryptedVerifierHashValue = TAgileEncryptionVerifier.EncryptBytes(KeyKey.Hash(RandData), Encryptor, KeyKey.BlockSize); xml.WriteAttributeString("encryptedVerifierHashValue", Convert.ToBase64String(EncryptedVerifierHashValue)); } KeyKey.CalcKey(TAgileEncryptionKey.VerifierKeyValueBlockKey, null); using (ICryptoTransform Encryptor = EncEngine.CreateEncryptor(KeyKey.Key, KeyKey.IV)) { byte[] EncryptedKeyValue = TAgileEncryptionVerifier.EncryptBytes(DataKey.Key, Encryptor, KeyKey.BlockSize); xml.WriteAttributeString("encryptedKeyValue", Convert.ToBase64String(EncryptedKeyValue)); } xml.WriteEndElement(); xml.WriteEndElement(); xml.WriteEndElement(); xml.WriteEndElement(); xml.WriteEndDocument(); } return(ms.ToArray()); } }