internal static EncryptionInfo ReadFile(FileStream dataStream) { EncryptionInfo ret; var bytes = new byte[8]; dataStream.Read(bytes, 0, 8); var majorVersion = BitConverter.ToInt16(bytes, 0); var minorVersion = BitConverter.ToInt16(bytes, 2); if ((minorVersion == 2 || minorVersion == 3) && majorVersion <= 4) // minorVersion==1 is RC4, not supported. { ret = new EncryptionInfoBinary(); } else if (majorVersion == 4 && minorVersion == 4) { ret = new EncryptionInfoAgile(); } else { throw (new NotSupportedException("Unsupported encryption format")); } ret.MajorVersion = majorVersion; ret.MinorVersion = minorVersion; ret.Read(dataStream); return(ret); }
private byte[] EncryptDataAgile(byte[] data, EncryptionInfoAgile encryptionInfo, HashAlgorithm hashProvider) { var ke = encryptionInfo.KeyEncryptors[0]; RijndaelManaged aes = new RijndaelManaged(); aes.KeySize = ke.KeyBits; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.Zeros; int pos = 0; int segment = 0; //Encrypt the data var ms = new MemoryStream(); ms.Write(BitConverter.GetBytes(data.LongLength), 0, 8); while (pos < data.Length) { var segmentSize = (int)(data.Length - pos > 4096 ? 4096 : data.Length - pos); var ivTmp = new byte[4 + encryptionInfo.KeyData.SaltSize]; Array.Copy(encryptionInfo.KeyData.SaltValue, 0, ivTmp, 0, encryptionInfo.KeyData.SaltSize); Array.Copy(BitConverter.GetBytes(segment), 0, ivTmp, encryptionInfo.KeyData.SaltSize, 4); var iv = hashProvider.ComputeHash(ivTmp); EncryptAgileFromKey(ke, ke.KeyValue, data, pos, segmentSize, iv, ms); pos += segmentSize; segment++; } ms.Flush(); return(ms.ToArray()); }
// Set the dataintegrity private void SetHMAC(EncryptionInfoAgile ei, HashAlgorithm hashProvider, byte[] salt, byte[] data) { var iv = GetFinalHash(hashProvider, ei.KeyEncryptors[0], BlockKey_HmacKey, ei.KeyData.SaltValue); var ms = new MemoryStream(); EncryptAgileFromKey(ei.KeyEncryptors[0], ei.KeyEncryptors[0].KeyValue, salt, 0L, salt.LongLength, iv, ms); ei.DataIntegrity.EncryptedHmacKey = ms.ToArray(); var h = GetHmacProvider(ei.KeyEncryptors[0], salt); var hmacValue = h.ComputeHash(data); ms = new MemoryStream(); iv = GetFinalHash(hashProvider, ei.KeyEncryptors[0], BlockKey_HmacValue, ei.KeyData.SaltValue); EncryptAgileFromKey(ei.KeyEncryptors[0], ei.KeyEncryptors[0].KeyValue, hmacValue, 0L, hmacValue.LongLength, iv, ms); ei.DataIntegrity.EncryptedHmacValue = ms.ToArray(); }
internal static EncryptionInfo ReadBinary(byte[] data) { var majorVersion = BitConverter.ToInt16(data, 0); var minorVersion = BitConverter.ToInt16(data, 2); EncryptionInfo ret; if ((minorVersion == 2 || minorVersion == 3) && majorVersion <= 4) // minorVersion==1 is RC4, not supported. { ret = new EncryptionInfoBinary(); } else if (majorVersion == 4 && minorVersion==4) { ret = new EncryptionInfoAgile(); } else { throw (new NotSupportedException("Unsupported encryption format")); } ret.MajorVersion = majorVersion; ret.MinorVersion = minorVersion; ret.Read(data); return ret; }
internal static EncryptionInfo ReadBinary(byte[] data) { var majorVersion = BitConverter.ToInt16(data, 0); var minorVersion = BitConverter.ToInt16(data, 2); EncryptionInfo ret; if ((minorVersion == 2 || minorVersion == 3) && majorVersion <= 4) // minorVersion==1 is RC4, not supported. { ret = new EncryptionInfoBinary(); } else if (majorVersion == 4 && minorVersion == 4) { ret = new EncryptionInfoAgile(); } else { throw (new NotSupportedException("Unsupported encryption format")); } ret.MajorVersion = majorVersion; ret.MinorVersion = minorVersion; ret.Read(data); return(ret); }
private FileStream EncryptDataAgile(Stream dataStream, EncryptionInfoAgile encryptionInfo, HashAlgorithm hashProvider) { var ke = encryptionInfo.KeyEncryptors[0]; #if Core var aes = Aes.Create(); #else RijndaelManaged aes = new RijndaelManaged(); #endif aes.KeySize = ke.KeyBits; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.Zeros; int pos = 0; int segment = 0; //Encrypt the data var fs = new FileStream(GetTempFile(), FileMode.Create); fs.Write(BitConverter.GetBytes((ulong)dataStream.Length), 0, 8); while (pos < dataStream.Length) { var segmentSize = (int)(dataStream.Length - pos > 4096 ? 4096 : dataStream.Length - pos); var ivTmp = new byte[4 + encryptionInfo.KeyData.SaltSize]; Array.Copy(encryptionInfo.KeyData.SaltValue, 0, ivTmp, 0, encryptionInfo.KeyData.SaltSize); Array.Copy(BitConverter.GetBytes(segment), 0, ivTmp, encryptionInfo.KeyData.SaltSize, 4); var iv = hashProvider.ComputeHash(ivTmp); EncryptAgileFromKey(ke, ke.KeyValue, dataStream, pos, segmentSize, iv, fs); pos += segmentSize; segment++; } fs.Flush(); fs.Seek(0, SeekOrigin.Begin); return(fs); }
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 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> /// Validate the password /// </summary> /// <param name="key">The encryption key</param> /// <param name="encryptionInfo">The encryption info extracted from the ENCRYPTIOINFO stream inside the OLE document</param> /// <returns></returns> private bool IsPasswordValid(HashAlgorithm sha, EncryptionInfoAgile.EncryptionKeyEncryptor encr) { var valHash = sha.ComputeHash(encr.VerifierHashInput); //Equal? for (int i = 0; i < valHash.Length; i++) { if (encr.VerifierHash[i] != valHash[i]) { return false; } } return true; }
/// <summary> /// Create the hash. /// This method is written with the help of Lyquidity library, many thanks for this nice sample /// </summary> /// <param name="password">The password</param> /// <param name="encryptionInfo">The encryption info extracted from the ENCRYPTIOINFO stream inside the OLE document</param> /// <param name="blockKey">The block key appended to the hash to obtain the final hash</param> /// <returns>The hash to encrypt the document</returns> private byte[] GetPasswordHashAgile(string password, EncryptionInfoAgile.EncryptionKeyEncryptor encr, byte[] blockKey) { try { var hashProvider = GetHashProvider(encr); var hash = GetPasswordHash(hashProvider, encr.SaltValue, password, encr.SpinCount, encr.HashSize); var hashFinal = GetFinalHash(hashProvider, encr, blockKey, hash); return FixHashSize(hashFinal, encr.KeyBits / 8); } catch (Exception ex) { throw (new Exception("An error occured when the encryptionkey was created", ex)); } }
private HMAC GetHmacProvider(EncryptionInfoAgile.EncryptionKeyEncryptor ei, byte[] salt) { switch (ei.HashAlgorithm) { case eHashAlogorithm.RIPEMD160: return new HMACRIPEMD160(salt); case eHashAlogorithm.MD5: return new HMACMD5(salt); case eHashAlogorithm.SHA1: return new HMACSHA1(salt); case eHashAlogorithm.SHA256: return new HMACSHA256(salt); case eHashAlogorithm.SHA384: return new HMACSHA384(salt); case eHashAlogorithm.SHA512: return new HMACSHA512(salt); default: throw(new NotSupportedException(string.Format("Hash method {0} not supported.",ei.HashAlgorithm))); } }
private HashAlgorithm GetHashProvider(EncryptionInfoAgile.EncryptionKeyEncryptor encr) { HashAlgorithm hashProvider; switch (encr.HashAlgorithm) { case eHashAlogorithm.MD5: return new MD5CryptoServiceProvider(); case eHashAlogorithm.RIPEMD160: return new RIPEMD160Managed(); case eHashAlogorithm.SHA1: return new SHA1CryptoServiceProvider(); case eHashAlogorithm.SHA256: return new SHA256CryptoServiceProvider(); case eHashAlogorithm.SHA384: return new SHA384CryptoServiceProvider(); case eHashAlogorithm.SHA512: return new SHA512CryptoServiceProvider(); default: throw new NotSupportedException(string.Format("Hash provider is unsupported. {0}", encr.HashAlgorithm)); } }
private byte[] GetFinalHash(HashAlgorithm hashProvider, EncryptionInfoAgile.EncryptionKeyEncryptor encr, byte[] blockKey, byte[] hash) { //2.3.4.13 MS-OFFCRYPTO var tempHash = new byte[hash.Length + blockKey.Length]; Array.Copy(hash, tempHash, hash.Length); Array.Copy(blockKey, 0, tempHash, hash.Length, blockKey.Length); var hashFinal = hashProvider.ComputeHash(tempHash); return hashFinal; }
readonly byte[] BlockKey_HmacValue = new byte[] { 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33 }; //MSOFFCRYPTO 2.3.4.14 section 5 private void DecryptAgile(EncryptionInfoAgile encryptionInfo, string password, long size, FileStream fs, Stream outputStream) { if (encryptionInfo.KeyData.CipherAlgorithm == eCipherAlgorithm.AES) { var encr = encryptionInfo.KeyEncryptors[0]; var hashProvider = GetHashProvider(encr); var baseHash = GetPasswordHash(hashProvider, encr.SaltValue, password, encr.SpinCount, encr.HashSize); //Get the keys for the verifiers and the key value var valInputKey = GetFinalHash(hashProvider, encr, BlockKey_HashInput, baseHash); var valHashKey = GetFinalHash(hashProvider, encr, BlockKey_HashValue, baseHash); var valKeySizeKey = GetFinalHash(hashProvider, encr, BlockKey_KeyValue, baseHash); //Decrypt encr.VerifierHashInput = DecryptAgileFromKey(encr, valInputKey, encr.EncryptedVerifierHashInput, encr.SaltSize, encr.SaltValue); encr.VerifierHash = DecryptAgileFromKey(encr, valHashKey, encr.EncryptedVerifierHash, encr.HashSize, encr.SaltValue); encr.KeyValue = DecryptAgileFromKey(encr, valKeySizeKey, encr.EncryptedKeyValue, encr.KeyBits / 8, encr.SaltValue); if (IsPasswordValid(hashProvider, encr)) { var ivhmac = GetFinalHash(hashProvider, encr, BlockKey_HmacKey, encryptionInfo.KeyData.SaltValue); var key = DecryptAgileFromKey(encr, encr.KeyValue, encryptionInfo.DataIntegrity.EncryptedHmacKey, encryptionInfo.KeyData.HashSize, ivhmac); ivhmac = GetFinalHash(hashProvider, encr, BlockKey_HmacValue, encryptionInfo.KeyData.SaltValue); var value = DecryptAgileFromKey(encr, encr.KeyValue, encryptionInfo.DataIntegrity.EncryptedHmacValue, encryptionInfo.KeyData.HashSize, ivhmac); var hmca = GetHmacProvider(encr, key); var startPos = fs.Position; fs.Seek(0, SeekOrigin.Begin); var v2 = hmca.ComputeHash(fs); fs.Seek(startPos, SeekOrigin.Begin); for (int i = 0; i < v2.Length; i++) { if (value[i] != v2[i]) { throw (new Exception("Dataintegrity key missmatch")); } } int pos = 0; uint segment = 0; while (pos < size) { var segmentSize = (int)(size - pos > 4096 ? 4096 : size - pos); var bufferSize = (int)(fs.Length - pos > 4096 ? 4096 : fs.Length - pos); var ivTmp = new byte[4 + encryptionInfo.KeyData.SaltSize]; Array.Copy(encryptionInfo.KeyData.SaltValue, 0, ivTmp, 0, encryptionInfo.KeyData.SaltSize); Array.Copy(BitConverter.GetBytes(segment), 0, ivTmp, encryptionInfo.KeyData.SaltSize, 4); var iv = hashProvider.ComputeHash(ivTmp); var buffer = new byte[bufferSize]; fs.Read(buffer, 0, bufferSize); //Array.Copy(encryptedData, pos, buffer, 0, bufferSize); var b = DecryptAgileFromKey(encr, encr.KeyValue, buffer, segmentSize, iv); outputStream.Write(b, 0, b.Length); pos += segmentSize; segment++; } outputStream.Flush(); } else { throw (new SecurityException("Invalid password")); } } }
private byte[] EncryptDataAgile(byte[] data, EncryptionInfoAgile encryptionInfo, HashAlgorithm hashProvider) { var ke = encryptionInfo.KeyEncryptors[0]; RijndaelManaged aes = new RijndaelManaged(); aes.KeySize = ke.KeyBits; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.Zeros; int pos=0; int segment=0; //Encrypt the data var ms = new MemoryStream(); ms.Write(BitConverter.GetBytes(data.LongLength), 0, 8); while (pos < data.Length) { var segmentSize = (int)(data.Length - pos > 4096 ? 4096 : data.Length - pos); var ivTmp = new byte[4 + encryptionInfo.KeyData.SaltSize]; Array.Copy(encryptionInfo.KeyData.SaltValue, 0, ivTmp, 0, encryptionInfo.KeyData.SaltSize); Array.Copy(BitConverter.GetBytes(segment), 0, ivTmp, encryptionInfo.KeyData.SaltSize, 4); var iv=hashProvider.ComputeHash(ivTmp); EncryptAgileFromKey(ke, ke.KeyValue, data, pos, segmentSize, iv, ms); pos += segmentSize; segment++; } ms.Flush(); return ms.ToArray(); }
private void EncryptAgileFromKey(EncryptionInfoAgile.EncryptionKeyEncryptor encr, byte[] key, byte[] data, long pos, long size, byte[] iv,MemoryStream ms) { var encryptKey = GetEncryptionAlgorithm(encr); encryptKey.BlockSize = encr.BlockSize << 3; encryptKey.KeySize = encr.KeyBits; encryptKey.Mode = encr.ChiptherChaining==eChainingMode.ChainingModeCBC ? CipherMode.CBC : CipherMode.CFB; encryptKey.Padding = PaddingMode.Zeros; ICryptoTransform encryptor = encryptKey.CreateEncryptor( FixHashSize(key, encr.KeyBits / 8), FixHashSize(iv, 16, 0x36)); CryptoStream cryptoStream = new CryptoStream(ms, encryptor, CryptoStreamMode.Write); var cryptoSize = size % encr.BlockSize == 0 ? size : (size + (encr.BlockSize - (size % encr.BlockSize))); var buffer = new byte[size]; Array.Copy(data, pos, buffer, 0, size); cryptoStream.Write(buffer, 0, (int)size); while (size % encr.BlockSize != 0) { cryptoStream.WriteByte(0); size++; } }
private byte[] DecryptAgileFromKey(EncryptionInfoAgile.EncryptionKeyEncryptor encr, byte[] key, byte[] encryptedData, long size, byte[] iv) { SymmetricAlgorithm decryptKey = GetEncryptionAlgorithm(encr); decryptKey.BlockSize = encr.BlockSize << 3; decryptKey.KeySize = encr.KeyBits; decryptKey.Mode = encr.ChiptherChaining == eChainingMode.ChainingModeCBC ? CipherMode.CBC : CipherMode.CFB; decryptKey.Padding = PaddingMode.Zeros; ICryptoTransform decryptor = decryptKey.CreateDecryptor( FixHashSize(key, encr.KeyBits / 8), FixHashSize(iv, encr.BlockSize, 0x36)); MemoryStream dataStream = new MemoryStream(encryptedData); CryptoStream cryptoStream = new CryptoStream(dataStream, decryptor, CryptoStreamMode.Read); var decryptedData = new byte[size]; cryptoStream.Read(decryptedData, 0, (int)size); return decryptedData; }
private MemoryStream DecryptAgile(EncryptionInfoAgile encryptionInfo, string password, long size, byte[] encryptedData, byte[] data) { MemoryStream doc = new MemoryStream(); if (encryptionInfo.KeyData.CipherAlgorithm == eCipherAlgorithm.AES) { var encr = encryptionInfo.KeyEncryptors[0]; var hashProvider = GetHashProvider(encr); var baseHash = GetPasswordHash(hashProvider, encr.SaltValue, password, encr.SpinCount, encr.HashSize); //Get the keys for the verifiers and the key value var valInputKey = GetFinalHash(hashProvider, encr, BlockKey_HashInput, baseHash); var valHashKey = GetFinalHash(hashProvider, encr, BlockKey_HashValue, baseHash); var valKeySizeKey = GetFinalHash(hashProvider, encr, BlockKey_KeyValue, baseHash); //Decrypt encr.VerifierHashInput = DecryptAgileFromKey(encr, valInputKey, encr.EncryptedVerifierHashInput, encr.SaltSize, encr.SaltValue); encr.VerifierHash = DecryptAgileFromKey(encr, valHashKey, encr.EncryptedVerifierHash, encr.HashSize, encr.SaltValue); encr.KeyValue = DecryptAgileFromKey(encr, valKeySizeKey, encr.EncryptedKeyValue, encr.KeyBits / 8, encr.SaltValue); if (IsPasswordValid(hashProvider, encr)) { var ivhmac = GetFinalHash(hashProvider, encr, BlockKey_HmacKey, encryptionInfo.KeyData.SaltValue); var key = DecryptAgileFromKey(encr, encr.KeyValue, encryptionInfo.DataIntegrity.EncryptedHmacKey, encryptionInfo.KeyData.HashSize, ivhmac); ivhmac = GetFinalHash(hashProvider, encr, BlockKey_HmacValue, encryptionInfo.KeyData.SaltValue); var value = DecryptAgileFromKey(encr, encr.KeyValue, encryptionInfo.DataIntegrity.EncryptedHmacValue, encryptionInfo.KeyData.HashSize, ivhmac); var hmca = GetHmacProvider(encr, key); var v2 = hmca.ComputeHash(data); for (int i = 0; i < v2.Length; i++) { if (value[i] != v2[i]) { throw (new Exception("Dataintegrity key missmatch")); } } int pos = 0; uint segment = 0; while (pos < size) { var segmentSize = (int)(size - pos > 4096 ? 4096 : size - pos); var bufferSize = (int)(encryptedData.Length - pos > 4096 ? 4096 : encryptedData.Length - pos); var ivTmp = new byte[4 + encryptionInfo.KeyData.SaltSize]; Array.Copy(encryptionInfo.KeyData.SaltValue, 0, ivTmp, 0, encryptionInfo.KeyData.SaltSize); Array.Copy(BitConverter.GetBytes(segment), 0, ivTmp, encryptionInfo.KeyData.SaltSize, 4); var iv = hashProvider.ComputeHash(ivTmp); var buffer = new byte[bufferSize]; Array.Copy(encryptedData, pos, buffer, 0, bufferSize); var b = DecryptAgileFromKey(encr, encr.KeyValue, buffer, segmentSize, iv); doc.Write(b, 0, b.Length); pos += segmentSize; segment++; } doc.Flush(); return doc; } else { throw (new UnauthorizedAccessException("Invalid password")); } } return null; }
readonly byte[] BlockKey_HmacValue = new byte[] { 0xa0, 0x67, 0x7f, 0x02, 0xb2, 0x2c, 0x84, 0x33 }; //MSOFFCRYPTO 2.3.4.14 section 5 private MemoryStream DecryptAgile(EncryptionInfoAgile encryptionInfo, string password, long size, byte[] encryptedData, byte[] data) { MemoryStream doc = new MemoryStream(); if (encryptionInfo.KeyData.CipherAlgorithm == eCipherAlgorithm.AES) { var encr = encryptionInfo.KeyEncryptors[0]; var hashProvider = GetHashProvider(encr); var baseHash = GetPasswordHash(hashProvider, encr.SaltValue, password, encr.SpinCount, encr.HashSize); //Get the keys for the verifiers and the key value var valInputKey = GetFinalHash(hashProvider, encr, BlockKey_HashInput, baseHash); var valHashKey = GetFinalHash(hashProvider, encr, BlockKey_HashValue, baseHash); var valKeySizeKey = GetFinalHash(hashProvider, encr, BlockKey_KeyValue, baseHash); //Decrypt encr.VerifierHashInput = DecryptAgileFromKey(encr, valInputKey, encr.EncryptedVerifierHashInput, encr.SaltSize, encr.SaltValue); encr.VerifierHash = DecryptAgileFromKey(encr, valHashKey, encr.EncryptedVerifierHash, encr.HashSize, encr.SaltValue); encr.KeyValue = DecryptAgileFromKey(encr, valKeySizeKey, encr.EncryptedKeyValue, encr.KeyBits / 8, encr.SaltValue); if (IsPasswordValid(hashProvider, encr)) { var ivhmac = GetFinalHash(hashProvider, encr, BlockKey_HmacKey, encryptionInfo.KeyData.SaltValue); var key = DecryptAgileFromKey(encr, encr.KeyValue, encryptionInfo.DataIntegrity.EncryptedHmacKey, encryptionInfo.KeyData.HashSize, ivhmac); ivhmac = GetFinalHash(hashProvider, encr, BlockKey_HmacValue, encryptionInfo.KeyData.SaltValue); var value = DecryptAgileFromKey(encr, encr.KeyValue, encryptionInfo.DataIntegrity.EncryptedHmacValue, encryptionInfo.KeyData.HashSize, ivhmac); var hmca = GetHmacProvider(encr, key); var v2 = hmca.ComputeHash(data); for (int i = 0; i < v2.Length; i++) { if (value[i] != v2[i]) { throw (new Exception("Dataintegrity key missmatch")); } } int pos = 0; uint segment = 0; while (pos < size) { var segmentSize = (int)(size - pos > 4096 ? 4096 : size - pos); var bufferSize = (int)(encryptedData.Length - pos > 4096 ? 4096 : encryptedData.Length - pos); var ivTmp = new byte[4 + encryptionInfo.KeyData.SaltSize]; Array.Copy(encryptionInfo.KeyData.SaltValue, 0, ivTmp, 0, encryptionInfo.KeyData.SaltSize); Array.Copy(BitConverter.GetBytes(segment), 0, ivTmp, encryptionInfo.KeyData.SaltSize, 4); var iv = hashProvider.ComputeHash(ivTmp); var buffer = new byte[bufferSize]; Array.Copy(encryptedData, pos, buffer, 0, bufferSize); var b = DecryptAgileFromKey(encr, encr.KeyValue, buffer, segmentSize, iv); doc.Write(b, 0, b.Length); pos += segmentSize; segment++; } doc.Flush(); return(doc); } else { throw (new UnauthorizedAccessException("Invalid password")); } } return(null); }
private SymmetricAlgorithm GetEncryptionAlgorithm(EncryptionInfoAgile.EncryptionKeyEncryptor encr) { switch (encr.CipherAlgorithm) { case eCipherAlgorithm.AES: return new RijndaelManaged(); case eCipherAlgorithm.DES: return new DESCryptoServiceProvider(); case eCipherAlgorithm.TRIPLE_DES: case eCipherAlgorithm.TRIPLE_DES_112: return new TripleDESCryptoServiceProvider(); case eCipherAlgorithm.RC2: return new RC2CryptoServiceProvider(); default: throw(new NotSupportedException(string.Format("Unsupported Cipher Algorithm: {0}", encr.CipherAlgorithm.ToString()))); } }