/// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="fi">The file</param> /// <param name="encryption"></param> /// <returns></returns> internal MemoryStream DecryptPackage(FileInfo fi, ExcelEncryption encryption) { MemoryStream ret = null; if (StgIsStorageFile(fi.FullName) == 0) { IStorage storage = null; if (StgOpenStorage( fi.FullName, null, STGM.DIRECT | STGM.READ | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out storage) == 0) { ret = GetStreamFromPackage(storage, encryption); Marshal.ReleaseComObject(storage); } } else { throw(new InvalidDataException(string.Format("File {0} is not an encrypted package", fi.FullName))); } return(ret); }
/// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="stream">The memory stream. </param> /// <param name="encryption">The encryption object from the Package</param> /// <returns></returns> internal MemoryStream DecryptPackage(MemoryStream stream, ExcelEncryption encryption) { //Create the lockBytes object. ILockBytes lb = GetLockbyte(stream); MemoryStream ret = null; if (StgIsStorageILockBytes(lb) == 0) { IStorage storage = null; if (StgOpenStorageOnILockBytes( lb, null, STGM.DIRECT | STGM.READ | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out storage) == 0) { ret = GetStreamFromPackage(storage, encryption); } Marshal.ReleaseComObject(storage); } else { throw (new InvalidDataException("The stream is not an encrypted package")); } Marshal.ReleaseComObject(lb); return(ret); }
public static WorkBook Load(string excelFilePath, string password) { FileInfo excelFile = new FileInfo(excelFilePath); ExceptionHelper.FalseThrow(excelFile.Exists, "文件不存在!"); excelFile.Refresh(); if (!string.IsNullOrEmpty(password)) { EncryptedPackageHandler encrHandler = new EncryptedPackageHandler(); ExcelEncryption fileEncryption = new ExcelEncryption(); fileEncryption.IsEncrypted = true; fileEncryption.Password = password; using (MemoryStream excelStream = encrHandler.DecryptPackage(excelFile, fileEncryption)) { return(Load(excelStream)); } } else { using (FileStream stream = excelFile.OpenRead()) { return(Load(stream)); } } }
/// <summary> /// 保存工作表为指定文件设置密码 /// </summary> /// <param name="targetFilePath"></param> /// <param name="password"></param> public void Save(string targetFilePath, string password) { FileInfo targetFile = new FileInfo(targetFilePath); if (targetFile.Exists) { targetFile.Delete(); } ExcelEncryption fileEncryption = new ExcelEncryption(); fileEncryption.Password = password; if (fileEncryption.IsEncrypted) { using (FileStream fi = new FileStream(targetFile.FullName, FileMode.Create)) { byte[] file = this.SaveAsBytes(); EncryptedPackageHandler eph = new EncryptedPackageHandler(); using (MemoryStream ms = eph.EncryptPackage(file, fileEncryption)) { fi.Write(ms.GetBuffer(), 0, (int)ms.Length); } } } else { using (Package package = Package.Open(targetFile.FullName, FileMode.Create, FileAccess.ReadWrite)) { InnerSave(package); } } }
private void EncryptPackageBinary(Stream package, ExcelEncryption encryption, Stream outputStream) { byte[] encryptionKey; //Create the Encryption Info. This also returns the Encryptionkey var encryptionInfo = CreateEncryptionInfo(encryption.Password, encryption.Algorithm == EncryptionAlgorithm.AES128 ? AlgorithmID.AES128 : encryption.Algorithm == EncryptionAlgorithm.AES192 ? AlgorithmID.AES192 : AlgorithmID.AES256, out encryptionKey); //ILockBytes lb; //var iret = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out lb); //IStorage storage = null; //MemoryStream ret = null; var doc = new CompoundDocument(tempFolder); CreateDataSpaces(doc); doc.Storage.DataStreams.Add("EncryptionInfo", new MemoryStream(encryptionInfo.WriteBinary())); //Encrypt the package byte[] encryptedPackage = EncryptData(encryptionKey, package, false); MemoryStream ms = new MemoryStream(); ms.Write(BitConverter.GetBytes((ulong)package.Length), 0, 8); ms.Write(encryptedPackage, 0, encryptedPackage.Length); doc.Storage.DataStreams.Add("EncryptedPackage", ms); doc.Save(outputStream); }
//Helpmethod to output the streams in the storage //private void WriteDoc(CompoundDocument.StoragePart storagePart, string p) //{ // foreach (var store in storagePart.SubStorage) // { // string sdir=p + store.Key.Replace((char)6,'x') + "\\"; // Directory.CreateDirectory(sdir); // WriteDoc(store.Value, sdir); // } // foreach (var str in storagePart.DataStreams) // { // File.WriteAllBytes(p + str.Key.Replace((char)6, 'x') + ".bin", str.Value); // } //} /// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="stream">The memory stream. </param> /// <param name="encryption">The encryption object from the Package</param> /// <returns></returns> internal MemoryStream DecryptPackage(MemoryStream stream, ExcelEncryption encryption) { //Create the lockBytes object. CompoundDocument.ILockBytes lb = null; try { lb = CompoundDocument.GetLockbyte(stream); if (CompoundDocument.IsStorageILockBytes(lb) == 0) { var doc = new CompoundDocument(lb); return(GetStreamFromPackage(doc, encryption)); } else { Marshal.ReleaseComObject(lb); throw (new InvalidDataException("The stream is not an valid/supported encrypted document.")); } } catch (Exception ex) { throw (ex); } finally { Marshal.ReleaseComObject(lb); lb = null; } }
private MemoryStream GetStreamFromPackage(IStorage storage, ExcelEncryption encryption) { MemoryStream ret = null; comTypes.STATSTG statstg; storage.Stat(out statstg, (uint)STATFLAG.STATFLAG_DEFAULT); IEnumSTATSTG pIEnumStatStg = null; storage.EnumElements(0, IntPtr.Zero, 0, out pIEnumStatStg); comTypes.STATSTG[] regelt = { statstg }; uint fetched = 0; uint res = pIEnumStatStg.Next(1, regelt, out fetched); //if (regelt[0].pwcsName == "DataSpaces") //{ // PrintStorage(storage, regelt[0],""); //} if (res == 0) { byte[] data; EncryptionInfo encryptionInfo = null; while (res != 1) { switch (statstg.pwcsName) { case "EncryptionInfo": data = GetOleStream(storage, statstg); //File.WriteAllBytes(@"c:\temp\EncInfo1.bin", data); encryptionInfo = new EncryptionInfo(); encryptionInfo.ReadBinary(data); encryption.Algorithm = encryptionInfo.Header.AlgID == AlgorithmID.AES128 ? EncryptionAlgorithm.AES128 : encryptionInfo.Header.AlgID == AlgorithmID.AES192 ? EncryptionAlgorithm.AES192 : EncryptionAlgorithm.AES256; break; case "EncryptedPackage": data = GetOleStream(storage, statstg); ret = DecryptDocument(data, encryptionInfo, encryption.Password); break; } if ((res = pIEnumStatStg.Next(1, regelt, out fetched)) != 1) { statstg = regelt[0]; } } } Marshal.ReleaseComObject(pIEnumStatStg); return(ret); }
/// <summary> /// Encrypts a package /// </summary> /// <param name="package">The package as a byte array</param> /// <param name="encryption">The encryption info from the workbook</param> /// <returns></returns> internal MemoryStream EncryptPackage(byte[] package, ExcelEncryption encryption) { if (encryption.Version == EncryptionVersion.Standard) //Standard encryption { return(EncryptPackageBinary(package, encryption)); } else if (encryption.Version == EncryptionVersion.Agile) //Agile encryption { return(EncryptPackageAgile(package, encryption)); } throw(new ArgumentException("Unsupported encryption version.")); }
/// <summary> /// Encrypts a package /// </summary> /// <param name="package">The package as a byte array</param> /// <param name="encryption">The encryption info from the workbook</param> /// <returns></returns> internal void EncryptPackage(Stream package, ExcelEncryption encryption, Stream outputStream) { if (encryption.Version == EncryptionVersion.Standard) //Standard encryption { EncryptPackageBinary(package, encryption, outputStream); return; } else if (encryption.Version == EncryptionVersion.Agile) //Agile encryption { EncryptPackageAgile(package, encryption, outputStream); return; } throw (new ArgumentException("Unsupported encryption version.")); }
private MemoryStream GetStreamFromPackage(CompoundDocument doc, ExcelEncryption encryption) { if (doc.Storage.DataStreams.ContainsKey("EncryptionInfo") || doc.Storage.DataStreams.ContainsKey("EncryptedPackage")) { var encryptionInfo = EncryptionInfo.ReadBinary(doc.Storage.DataStreams["EncryptionInfo"]); return(DecryptDocument(doc.Storage.DataStreams["EncryptedPackage"], encryptionInfo, encryption.Password)); } else { throw (new InvalidDataException("Invalid document. EncryptionInfo or EncryptedPackage stream is missing")); } }
private void GetStreamFromPackage(CompoundDocument doc, ExcelEncryption encryption, Stream outputStream) { if (doc.Storage.DataStreams.ContainsKey("EncryptionInfo") || doc.Storage.DataStreams.ContainsKey("EncryptedPackage")) { var encryptionInfo = EncryptionInfo.ReadFile(doc.Storage.DataStreams["EncryptionInfo"] as FileStream); DecryptDocument(doc.Storage.DataStreams["EncryptedPackage"] as FileStream, encryptionInfo, encryption.Password, outputStream); } else { throw (new InvalidDataException("Invalid document. EncryptionInfo or EncryptedPackage stream is missing")); } }
/// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="fi">The file</param> /// <param name="encryption"></param> /// <returns></returns> internal MemoryStream DecryptPackage(FileInfo fi, ExcelEncryption encryption) { CompoundDocument doc = new CompoundDocument(fi); MemoryStream ret = null; if (CompoundDocument.IsStorageFile(fi.FullName) == 0) { ret = GetStreamFromPackage(doc, encryption); } else { throw (new InvalidDataException(string.Format("File {0} is not an encrypted package", fi.FullName))); } return ret; }
/// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="fi">The file</param> /// <param name="encryption"></param> /// <returns></returns> internal MemoryStream DecryptPackage(FileInfo fi, ExcelEncryption encryption) { if (CompoundDocument.IsCompoundDocument(fi)) { CompoundDocument doc = new CompoundDocument(fi); MemoryStream ret = null; ret = GetStreamFromPackage(doc, encryption); return(ret); } else { throw (new InvalidDataException(string.Format("File {0} is not an encrypted package", fi.FullName))); } }
/// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="fi">The file</param> /// <param name="encryption"></param> /// <returns></returns> internal void DecryptPackage(FileInfo fi, ExcelEncryption encryption, Stream outputStream) { if (CompoundDocument.IsCompoundDocument(fi)) { CompoundDocument doc = new CompoundDocument(fi, this.tempFolder); //Stream ret = null; GetStreamFromPackage(doc, encryption, outputStream); } else { throw (new InvalidDataException(string.Format("File {0} is not an encrypted package", fi.FullName))); } //return ret; }
//Helpmethod to output the streams in the storage //private void WriteDoc(CompoundDocument.StoragePart storagePart, string p) //{ // foreach (var store in storagePart.SubStorage) // { // string sdir=p + store.Key.Replace((char)6,'x') + "\\"; // Directory.CreateDirectory(sdir); // WriteDoc(store.Value, sdir); // } // foreach (var str in storagePart.DataStreams) // { // File.WriteAllBytes(p + str.Key.Replace((char)6, 'x') + ".bin", str.Value); // } //} /// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="stream">The memory stream. </param> /// <param name="encryption">The encryption object from the Package</param> /// <returns></returns> internal void DecryptPackage(MemoryStream stream, ExcelEncryption encryption, Stream outputStream) { try { if (CompoundDocument.IsCompoundDocument(stream)) { var doc = new CompoundDocument(stream, this.tempFolder); GetStreamFromPackage(doc, encryption, outputStream); } else { throw (new InvalidDataException("The stream is not an valid/supported encrypted document.")); } } catch// (Exception ex) { throw; } }
//Helpmethod to output the streams in the storage //private void WriteDoc(CompoundDocument.StoragePart storagePart, string p) //{ // foreach (var store in storagePart.SubStorage) // { // string sdir=p + store.Key.Replace((char)6,'x') + "\\"; // Directory.CreateDirectory(sdir); // WriteDoc(store.Value, sdir); // } // foreach (var str in storagePart.DataStreams) // { // File.WriteAllBytes(p + str.Key.Replace((char)6, 'x') + ".bin", str.Value); // } //} /// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="stream">The memory stream. </param> /// <param name="encryption">The encryption object from the Package</param> /// <returns></returns> internal MemoryStream DecryptPackage(MemoryStream stream, ExcelEncryption encryption) { try { if (CompoundDocument.IsCompoundDocument(stream)) { var doc = new CompoundDocument(stream); return(GetStreamFromPackage(doc, encryption)); } else { throw (new InvalidDataException("The stream is not an valid/supported encrypted document.")); } } catch// (Exception ex) { throw; } }
public void Save(Stream targetStream, string password) { ExcelEncryption fileEncryption = new ExcelEncryption(); fileEncryption.Password = password; if (fileEncryption.IsEncrypted) { EncryptedPackageHandler eph = new EncryptedPackageHandler(); using (MemoryStream encryptStream = eph.EncryptPackage(SaveAsBytes(), fileEncryption)) { encryptStream.Seek(0, SeekOrigin.Begin); encryptStream.CopyTo(targetStream); //ExcelHelper.CopyStream(encryptStream, targetStream); } } else { Save(targetStream); } }
public static WorkBook Load(Stream input, string password) { if (!string.IsNullOrEmpty(password)) { EncryptedPackageHandler encrHandler = new EncryptedPackageHandler(); ExcelEncryption fileEncryption = new ExcelEncryption(); fileEncryption.IsEncrypted = true; fileEncryption.Password = password; using (MemoryStream copyStream = new MemoryStream()) { input.CopyTo(copyStream); //ExcelHelper.CopyStream(input, copyStream); MemoryStream decrytStrem = encrHandler.DecryptPackage(copyStream, fileEncryption); return(Load(decrytStrem)); } } else { return(null); } }
/// <summary> /// 加密后Excel文件 /// </summary> /// <param name="password"></param> /// <returns></returns> public byte[] SaveAsBytes(string password) { byte[] byRet = null; ExcelEncryption fileEncryption = new ExcelEncryption(); fileEncryption.Password = password; if (fileEncryption.IsEncrypted) { EncryptedPackageHandler eph = new EncryptedPackageHandler(); using (MemoryStream encryptStream = eph.EncryptPackage(SaveAsBytes(), fileEncryption)) { byRet = encryptStream.ToArray(); } } else { byRet = SaveAsBytes(); } return(byRet); }
private MemoryStream EncryptPackageBinary(byte[] package, ExcelEncryption encryption) { byte[] encryptionKey; //Create the Encryption Info. This also returns the Encryptionkey var encryptionInfo = CreateEncryptionInfo(encryption.Password, encryption.Algorithm == EncryptionAlgorithm.AES128 ? AlgorithmID.AES128 : encryption.Algorithm == EncryptionAlgorithm.AES192 ? AlgorithmID.AES192 : AlgorithmID.AES256, out encryptionKey); //ILockBytes lb; //var iret = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out lb); //IStorage storage = null; //MemoryStream ret = null; var doc = new CompoundDocument(); CreateDataSpaces(doc); doc.Storage.DataStreams.Add("EncryptionInfo", encryptionInfo.WriteBinary()); //Encrypt the package byte[] encryptedPackage = EncryptData(encryptionKey, package, false); using (var ms = RecyclableMemory.GetStream()) { ms.Write(BitConverter.GetBytes((ulong)package.Length), 0, 8); ms.Write(encryptedPackage, 0, encryptedPackage.Length); doc.Storage.DataStreams.Add("EncryptedPackage", ms.ToArray()); } var ret = RecyclableMemory.GetStream(); doc.Save(ret); return(ret); }
//Helpmethod to output the streams in the storage //private void WriteDoc(CompoundDocument.StoragePart storagePart, string p) //{ // foreach (var store in storagePart.SubStorage) // { // string sdir=p + store.Key.Replace((char)6,'x') + "\\"; // Directory.CreateDirectory(sdir); // WriteDoc(store.Value, sdir); // } // foreach (var str in storagePart.DataStreams) // { // File.WriteAllBytes(p + str.Key.Replace((char)6, 'x') + ".bin", str.Value); // } //} /// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="stream">The memory stream. </param> /// <param name="encryption">The encryption object from the Package</param> /// <returns></returns> internal MemoryStream DecryptPackage(MemoryStream stream, ExcelEncryption encryption) { //Create the lockBytes object. CompoundDocument.ILockBytes lb=null; try { lb = CompoundDocument.GetLockbyte(stream); if (CompoundDocument.IsStorageILockBytes(lb) == 0) { var doc = new CompoundDocument(lb); return GetStreamFromPackage(doc, encryption); } else { Marshal.ReleaseComObject(lb); throw (new InvalidDataException("The stream is not an valid/supported encrypted document.")); } } catch (Exception ex) { throw (ex); } finally { Marshal.ReleaseComObject(lb); lb = null; } }
private MemoryStream EncryptPackageAgile(byte[] package, ExcelEncryption encryption) { var xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n"; xml += "<encryption xmlns=\"http://schemas.microsoft.com/office/2006/encryption\" xmlns:p=\"http://schemas.microsoft.com/office/2006/keyEncryptor/password\" xmlns:c=\"http://schemas.microsoft.com/office/2006/keyEncryptor/certificate\">"; xml += "<keyData saltSize=\"16\" blockSize=\"16\" keyBits=\"256\" hashSize=\"64\" cipherAlgorithm=\"AES\" cipherChaining=\"ChainingModeCBC\" hashAlgorithm=\"SHA512\" saltValue=\"\"/>"; xml += "<dataIntegrity encryptedHmacKey=\"\" encryptedHmacValue=\"\"/>"; xml += "<keyEncryptors>"; xml += "<keyEncryptor uri=\"http://schemas.microsoft.com/office/2006/keyEncryptor/password\">"; xml += "<p:encryptedKey spinCount=\"100000\" saltSize=\"16\" blockSize=\"16\" keyBits=\"256\" hashSize=\"64\" cipherAlgorithm=\"AES\" cipherChaining=\"ChainingModeCBC\" hashAlgorithm=\"SHA512\" saltValue=\"\" encryptedVerifierHashInput=\"\" encryptedVerifierHashValue=\"\" encryptedKeyValue=\"\" />"; xml += "</keyEncryptor></keyEncryptors></encryption>"; var encryptionInfo = new EncryptionInfoAgile(); encryptionInfo.ReadFromXml(xml); var encr = encryptionInfo.KeyEncryptors[0]; var rnd = RandomNumberGenerator.Create(); var s = new byte[16]; rnd.GetBytes(s); encryptionInfo.KeyData.SaltValue = s; rnd.GetBytes(s); encr.SaltValue = s; encr.KeyValue = new byte[encr.KeyBits / 8]; rnd.GetBytes(encr.KeyValue); //Get the passwork key. var hashProvider = GetHashProvider(encryptionInfo.KeyEncryptors[0]); var baseHash = GetPasswordHash(hashProvider, encr.SaltValue, encryption.Password, encr.SpinCount, encr.HashSize); var hashFinal = GetFinalHash(hashProvider, encr, BlockKey_KeyValue, baseHash); hashFinal = FixHashSize(hashFinal, encr.KeyBits / 8); var encrData = EncryptDataAgile(package, encryptionInfo, hashProvider); /**** Data Integrity ****/ var saltHMAC = new byte[64]; rnd.GetBytes(saltHMAC); SetHMAC(encryptionInfo, hashProvider, saltHMAC, encrData); /**** Verifier ****/ encr.VerifierHashInput = new byte[16]; rnd.GetBytes(encr.VerifierHashInput); encr.VerifierHash = hashProvider.ComputeHash(encr.VerifierHashInput); var VerifierInputKey = GetFinalHash(hashProvider, encr, BlockKey_HashInput, baseHash); var VerifierHashKey = GetFinalHash(hashProvider, encr, BlockKey_HashValue, baseHash); var KeyValueKey = GetFinalHash(hashProvider, encr, BlockKey_KeyValue, baseHash); var ms = new MemoryStream(); EncryptAgileFromKey(encr, VerifierInputKey, encr.VerifierHashInput, 0, encr.VerifierHashInput.Length, encr.SaltValue, ms); encr.EncryptedVerifierHashInput = ms.ToArray(); ms = new MemoryStream(); EncryptAgileFromKey(encr, VerifierHashKey, encr.VerifierHash, 0, encr.VerifierHash.Length, encr.SaltValue, ms); encr.EncryptedVerifierHash = ms.ToArray(); ms = new MemoryStream(); EncryptAgileFromKey(encr, KeyValueKey, encr.KeyValue, 0, encr.KeyValue.Length, encr.SaltValue, ms); encr.EncryptedKeyValue = ms.ToArray(); xml = encryptionInfo.Xml.OuterXml; var byXml = Encoding.UTF8.GetBytes(xml); ms = new MemoryStream(); ms.Write(BitConverter.GetBytes((ushort)4), 0, 2); //Major Version ms.Write(BitConverter.GetBytes((ushort)4), 0, 2); //Minor Version ms.Write(BitConverter.GetBytes((uint)0x40), 0, 4); //Reserved ms.Write(byXml, 0, byXml.Length); var doc = new CompoundDocument(); //Add the dataspace streams CreateDataSpaces(doc); //EncryptionInfo... doc.Storage.DataStreams.Add("EncryptionInfo", ms.ToArray()); //...and the encrypted package doc.Storage.DataStreams.Add("EncryptedPackage", encrData); ms = new MemoryStream(); var e = doc.Save(); ms.Write(e, 0, e.Length); return(ms); }
private MemoryStream GetStreamFromPackage(IStorage storage, ExcelEncryption encryption) { MemoryStream ret=null; comTypes.STATSTG statstg; storage.Stat(out statstg, (uint)STATFLAG.STATFLAG_DEFAULT); IEnumSTATSTG pIEnumStatStg = null; storage.EnumElements(0, IntPtr.Zero, 0, out pIEnumStatStg); comTypes.STATSTG[] regelt = { statstg }; uint fetched = 0; uint res = pIEnumStatStg.Next(1, regelt, out fetched); //if (regelt[0].pwcsName == "DataSpaces") //{ // PrintStorage(storage, regelt[0],""); //} if (res == 0) { byte[] data; EncryptionInfo encryptionInfo = null; while (res != 1) { switch (statstg.pwcsName) { case "EncryptionInfo": data = GetOleStream(storage, statstg); //File.WriteAllBytes(@"c:\temp\EncInfo1.bin", data); encryptionInfo = new EncryptionInfo(); encryptionInfo.ReadBinary(data); encryption.Algorithm = encryptionInfo.Header.AlgID == AlgorithmID.AES128 ? EncryptionAlgorithm.AES128 : encryptionInfo.Header.AlgID == AlgorithmID.AES192 ? EncryptionAlgorithm.AES192 : EncryptionAlgorithm.AES256; break; case "EncryptedPackage": data = GetOleStream(storage, statstg); ret = DecryptDocument(data, encryptionInfo, encryption.Password); break; } if ((res = pIEnumStatStg.Next(1, regelt, out fetched)) != 1) { statstg = regelt[0]; } } } Marshal.ReleaseComObject(pIEnumStatStg); return ret; }
/// <summary> /// Encrypts a package /// </summary> /// <param name="package">The package as a byte array</param> /// <param name="encryption">The encryption info from the workbook</param> /// <returns></returns> internal MemoryStream EncryptPackage(byte[] package, ExcelEncryption encryption) { byte[] encryptionKey; //Create the Encryption Info. This also returns the Encryptionkey var encryptionInfo = CreateEncryptionInfo(encryption.Password, encryption.Algorithm == EncryptionAlgorithm.AES128 ? AlgorithmID.AES128 : encryption.Algorithm == EncryptionAlgorithm.AES192 ? AlgorithmID.AES192 : AlgorithmID.AES256, out encryptionKey); ILockBytes lb; var iret = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out lb); IStorage storage = null; MemoryStream ret = null; //Create the document in-memory if (StgCreateDocfileOnILockBytes(lb, STGM.CREATE | STGM.READWRITE | STGM.SHARE_EXCLUSIVE | STGM.TRANSACTED, 0, out storage)==0) { //First create the dataspace storage CreateDataSpaces(storage); //Create the Encryption info Stream comTypes.IStream stream; storage.CreateStream("EncryptionInfo", (uint)(STGM.CREATE | STGM.WRITE | STGM.DIRECT | STGM.SHARE_EXCLUSIVE), (uint)0, (uint)0, out stream); byte[] ei=encryptionInfo.WriteBinary(); stream.Write(ei, ei.Length, IntPtr.Zero); stream = null; //Encrypt the package byte[] encryptedPackage=EncryptData(encryptionKey, package, false); storage.CreateStream("EncryptedPackage", (uint)(STGM.CREATE | STGM.WRITE | STGM.DIRECT | STGM.SHARE_EXCLUSIVE), (uint)0, (uint)0, out stream); //Write Size here MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); bw.Write((ulong)package.LongLength); bw.Flush(); byte[] length = ms.ToArray(); //Write Encrypted data length first as an unsigned long stream.Write(length, length.Length, IntPtr.Zero); //And now the Encrypted data stream.Write(encryptedPackage, encryptedPackage.Length, IntPtr.Zero); stream = null; storage.Commit(0); lb.Flush(); //Now copy the unmanaged stream to a byte array --> memory stream var statstg = new comTypes.STATSTG(); lb.Stat(out statstg, 0); int size = (int)statstg.cbSize; IntPtr buffer = Marshal.AllocHGlobal(size); UIntPtr readSize; byte[] pack=new byte[size]; lb.ReadAt(0, buffer, size, out readSize); Marshal.Copy(buffer, pack, 0, size); Marshal.FreeHGlobal(buffer); ret = new MemoryStream(); ret.Write(pack, 0, size); } Marshal.ReleaseComObject(storage); Marshal.ReleaseComObject(lb); return ret; }
/// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="stream">The memory stream. </param> /// <param name="encryption">The encryption object from the Package</param> /// <returns></returns> internal MemoryStream DecryptPackage(MemoryStream stream, ExcelEncryption encryption) { //Create the lockBytes object. ILockBytes lb = GetLockbyte(stream); MemoryStream ret = null; if (StgIsStorageILockBytes(lb) == 0) { IStorage storage = null; if (StgOpenStorageOnILockBytes( lb, null, STGM.DIRECT | STGM.READ | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out storage) == 0) { ret = GetStreamFromPackage(storage, encryption); } Marshal.ReleaseComObject(storage); } else { throw (new InvalidDataException("The stream is not an encrypted package")); } Marshal.ReleaseComObject(lb); return ret; }
/// <summary> /// Read the package from the OLE document and decrypt it using the supplied password /// </summary> /// <param name="fi">The file</param> /// <param name="encryption"></param> /// <returns></returns> internal MemoryStream DecryptPackage(FileInfo fi, ExcelEncryption encryption) { MemoryStream ret = null; if (StgIsStorageFile(fi.FullName) == 0) { IStorage storage = null; if (StgOpenStorage( fi.FullName, null, STGM.DIRECT | STGM.READ | STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out storage) == 0) { ret = GetStreamFromPackage(storage, encryption); Marshal.ReleaseComObject(storage); } } else { throw(new InvalidDataException(string.Format("File {0} is not an encrypted package",fi.FullName))); } return ret; }
private MemoryStream GetStreamFromPackage(CompoundDocument doc, ExcelEncryption encryption) { var ret = new MemoryStream(); if(doc.Storage.DataStreams.ContainsKey("EncryptionInfo") || doc.Storage.DataStreams.ContainsKey("EncryptedPackage")) { var encryptionInfo = EncryptionInfo.ReadBinary(doc.Storage.DataStreams["EncryptionInfo"]); return DecryptDocument(doc.Storage.DataStreams["EncryptedPackage"], encryptionInfo, encryption.Password); } else { throw (new InvalidDataException("Invalid document. EncryptionInfo or EncryptedPackage stream is missing")); } }
private MemoryStream EncryptPackageBinary(byte[] package, ExcelEncryption encryption) { byte[] encryptionKey; //Create the Encryption Info. This also returns the Encryptionkey var encryptionInfo = CreateEncryptionInfo(encryption.Password, encryption.Algorithm == EncryptionAlgorithm.AES128 ? AlgorithmID.AES128 : encryption.Algorithm == EncryptionAlgorithm.AES192 ? AlgorithmID.AES192 : AlgorithmID.AES256, out encryptionKey); //ILockBytes lb; //var iret = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out lb); //IStorage storage = null; //MemoryStream ret = null; var doc = new CompoundDocument(); CreateDataSpaces(doc); doc.Storage.DataStreams.Add("EncryptionInfo", encryptionInfo.WriteBinary()); //Encrypt the package byte[] encryptedPackage = EncryptData(encryptionKey, package, false); MemoryStream ms = new MemoryStream(); ms.Write(BitConverter.GetBytes((ulong)package.LongLength), 0, 8); ms.Write(encryptedPackage, 0, encryptedPackage.Length); doc.Storage.DataStreams.Add("EncryptedPackage", ms.ToArray()); var ret = new MemoryStream(); var buffer = doc.Save(); ret.Write(buffer, 0, buffer.Length); return ret; }
private MemoryStream EncryptPackageAgile(byte[] package, ExcelEncryption encryption) { var xml= "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\r\n"; xml += "<encryption xmlns=\"http://schemas.microsoft.com/office/2006/encryption\" xmlns:p=\"http://schemas.microsoft.com/office/2006/keyEncryptor/password\" xmlns:c=\"http://schemas.microsoft.com/office/2006/keyEncryptor/certificate\">"; xml += "<keyData saltSize=\"16\" blockSize=\"16\" keyBits=\"256\" hashSize=\"64\" cipherAlgorithm=\"AES\" cipherChaining=\"ChainingModeCBC\" hashAlgorithm=\"SHA512\" saltValue=\"\"/>"; xml += "<dataIntegrity encryptedHmacKey=\"\" encryptedHmacValue=\"\"/>"; xml += "<keyEncryptors>"; xml += "<keyEncryptor uri=\"http://schemas.microsoft.com/office/2006/keyEncryptor/password\">"; xml += "<p:encryptedKey spinCount=\"100000\" saltSize=\"16\" blockSize=\"16\" keyBits=\"256\" hashSize=\"64\" cipherAlgorithm=\"AES\" cipherChaining=\"ChainingModeCBC\" hashAlgorithm=\"SHA512\" saltValue=\"\" encryptedVerifierHashInput=\"\" encryptedVerifierHashValue=\"\" encryptedKeyValue=\"\" />"; xml += "</keyEncryptor></keyEncryptors></encryption>"; var encryptionInfo = new EncryptionInfoAgile(); encryptionInfo.ReadFromXml(xml); var encr = encryptionInfo.KeyEncryptors[0]; var rnd = RandomNumberGenerator.Create(); var s = new byte[16]; rnd.GetBytes(s); encryptionInfo.KeyData.SaltValue = s; rnd.GetBytes(s); encr.SaltValue = s; encr.KeyValue = new byte[encr.KeyBits / 8]; rnd.GetBytes(encr.KeyValue); //Get the passwork key. var hashProvider = GetHashProvider(encryptionInfo.KeyEncryptors[0]); var baseHash = GetPasswordHash(hashProvider, encr.SaltValue, encryption.Password, encr.SpinCount, encr.HashSize); var hashFinal = GetFinalHash(hashProvider, encr, BlockKey_KeyValue, baseHash); hashFinal = FixHashSize(hashFinal, encr.KeyBits / 8); var encrData = EncryptDataAgile(package, encryptionInfo, hashProvider); /**** Data Integrity ****/ var saltHMAC=new byte[64]; rnd.GetBytes(saltHMAC); SetHMAC(encryptionInfo,hashProvider,saltHMAC, encrData); /**** Verifier ****/ encr.VerifierHashInput = new byte[16]; rnd.GetBytes(encr.VerifierHashInput); encr.VerifierHash = hashProvider.ComputeHash(encr.VerifierHashInput); var VerifierInputKey = GetFinalHash(hashProvider, encr, BlockKey_HashInput, baseHash); var VerifierHashKey = GetFinalHash(hashProvider, encr, BlockKey_HashValue, baseHash); var KeyValueKey = GetFinalHash(hashProvider, encr, BlockKey_KeyValue, baseHash); var ms = new MemoryStream(); EncryptAgileFromKey(encr, VerifierInputKey, encr.VerifierHashInput, 0, encr.VerifierHashInput.Length, encr.SaltValue, ms); encr.EncryptedVerifierHashInput = ms.ToArray(); ms = new MemoryStream(); EncryptAgileFromKey(encr, VerifierHashKey, encr.VerifierHash, 0, encr.VerifierHash.Length, encr.SaltValue, ms); encr.EncryptedVerifierHash = ms.ToArray(); ms = new MemoryStream(); EncryptAgileFromKey(encr, KeyValueKey, encr.KeyValue, 0, encr.KeyValue.Length, encr.SaltValue, ms); encr.EncryptedKeyValue = ms.ToArray(); xml = encryptionInfo.Xml.OuterXml; var byXml = Encoding.UTF8.GetBytes(xml); ms = new MemoryStream(); ms.Write(BitConverter.GetBytes((ushort)4), 0, 2); //Major Version ms.Write(BitConverter.GetBytes((ushort)4), 0, 2); //Minor Version ms.Write(BitConverter.GetBytes((uint)0x40), 0, 4); //Reserved ms.Write(byXml,0,byXml.Length); var doc = new CompoundDocument(); //Add the dataspace streams CreateDataSpaces(doc); //EncryptionInfo... doc.Storage.DataStreams.Add("EncryptionInfo", ms.ToArray()); //...and the encrypted package doc.Storage.DataStreams.Add("EncryptedPackage", encrData); ms = new MemoryStream(); var e=doc.Save(); ms.Write(e,0,e.Length); return ms; }
/// <summary> /// Encrypts a package /// </summary> /// <param name="package">The package as a byte array</param> /// <param name="encryption">The encryption info from the workbook</param> /// <returns></returns> internal MemoryStream EncryptPackage(byte[] package, ExcelEncryption encryption) { if (encryption.Version == EncryptionVersion.Standard) //Standard encryption { return EncryptPackageBinary(package, encryption); } else if (encryption.Version == EncryptionVersion.Agile) //Agile encryption { return EncryptPackageAgile(package, encryption); } throw(new ArgumentException("Unsupported encryption version.")); }
/// <summary> /// Encrypts a package /// </summary> /// <param name="package">The package as a byte array</param> /// <param name="encryption">The encryption info from the workbook</param> /// <returns></returns> internal MemoryStream EncryptPackage(byte[] package, ExcelEncryption encryption) { byte[] encryptionKey; //Create the Encryption Info. This also returns the Encryptionkey var encryptionInfo = CreateEncryptionInfo(encryption.Password, encryption.Algorithm == EncryptionAlgorithm.AES128 ? AlgorithmID.AES128 : encryption.Algorithm == EncryptionAlgorithm.AES192 ? AlgorithmID.AES192 : AlgorithmID.AES256, out encryptionKey); ILockBytes lb; var iret = CreateILockBytesOnHGlobal(IntPtr.Zero, true, out lb); IStorage storage = null; MemoryStream ret = null; //Create the document in-memory if (StgCreateDocfileOnILockBytes(lb, STGM.CREATE | STGM.READWRITE | STGM.SHARE_EXCLUSIVE | STGM.TRANSACTED, 0, out storage) == 0) { //First create the dataspace storage CreateDataSpaces(storage); //Create the Encryption info Stream comTypes.IStream stream; storage.CreateStream("EncryptionInfo", (uint)(STGM.CREATE | STGM.WRITE | STGM.DIRECT | STGM.SHARE_EXCLUSIVE), (uint)0, (uint)0, out stream); byte[] ei = encryptionInfo.WriteBinary(); stream.Write(ei, ei.Length, IntPtr.Zero); stream = null; //Encrypt the package byte[] encryptedPackage = EncryptData(encryptionKey, package, false); storage.CreateStream("EncryptedPackage", (uint)(STGM.CREATE | STGM.WRITE | STGM.DIRECT | STGM.SHARE_EXCLUSIVE), (uint)0, (uint)0, out stream); //Write Size here MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); bw.Write((ulong)package.LongLength); bw.Flush(); byte[] length = ms.ToArray(); //Write Encrypted data length first as an unsigned long stream.Write(length, length.Length, IntPtr.Zero); //And now the Encrypted data stream.Write(encryptedPackage, encryptedPackage.Length, IntPtr.Zero); stream = null; storage.Commit(0); lb.Flush(); //Now copy the unmanaged stream to a byte array --> memory stream var statstg = new comTypes.STATSTG(); lb.Stat(out statstg, 0); int size = (int)statstg.cbSize; IntPtr buffer = Marshal.AllocHGlobal(size); UIntPtr readSize; byte[] pack = new byte[size]; lb.ReadAt(0, buffer, size, out readSize); Marshal.Copy(buffer, pack, 0, size); Marshal.FreeHGlobal(buffer); ret = new MemoryStream(); ret.Write(pack, 0, size); } Marshal.ReleaseComObject(storage); Marshal.ReleaseComObject(lb); return(ret); }