Skip to content

Commit

Permalink
Fixed encryption problem with older versions of Excel(sha1). JanKallm…
Browse files Browse the repository at this point in the history
  • Loading branch information
JanKallman committed Mar 4, 2018
1 parent afdad09 commit d0f364b
Showing 1 changed file with 26 additions and 24 deletions.
50 changes: 26 additions & 24 deletions EPPlus/Encryption/EncryptionHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private MemoryStream EncryptPackageAgile(byte[] package, ExcelEncryption encrypt
//Get the password 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);
var hashFinal = GetFinalHash(hashProvider, BlockKey_KeyValue, baseHash);
hashFinal = FixHashSize(hashFinal, encr.KeyBits / 8);

var encrData = EncryptDataAgile(package, encryptionInfo, hashProvider);
Expand All @@ -174,9 +174,9 @@ private MemoryStream EncryptPackageAgile(byte[] package, ExcelEncryption encrypt

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 VerifierInputKey = GetFinalHash(hashProvider, BlockKey_HashInput, baseHash);
var VerifierHashKey = GetFinalHash(hashProvider, BlockKey_HashValue, baseHash);
var KeyValueKey = GetFinalHash(hashProvider, BlockKey_KeyValue, baseHash);

var ms = new MemoryStream();
EncryptAgileFromKey(encr, VerifierInputKey, encr.VerifierHashInput, 0, encr.VerifierHashInput.Length, encr.SaltValue, ms);
Expand Down Expand Up @@ -252,7 +252,7 @@ private byte[] EncryptDataAgile(byte[] data, EncryptionInfoAgile encryptionInfo,
// 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 iv = GetFinalHash(hashProvider, BlockKey_HmacKey, ei.KeyData.SaltValue);
var ms = new MemoryStream();
EncryptAgileFromKey(ei.KeyEncryptors[0], ei.KeyEncryptors[0].KeyValue, salt, 0L, salt.Length, iv, ms);
ei.DataIntegrity.EncryptedHmacKey = ms.ToArray();
Expand All @@ -261,12 +261,12 @@ private void SetHMAC(EncryptionInfoAgile ei, HashAlgorithm hashProvider, byte[]
var hmacValue = h.ComputeHash(data);

ms = new MemoryStream();
iv = GetFinalHash(hashProvider, ei.KeyEncryptors[0], BlockKey_HmacValue, ei.KeyData.SaltValue);
iv = GetFinalHash(hashProvider, BlockKey_HmacValue, ei.KeyData.SaltValue);
EncryptAgileFromKey(ei.KeyEncryptors[0], ei.KeyEncryptors[0].KeyValue, hmacValue, 0L, hmacValue.Length, iv, ms);
ei.DataIntegrity.EncryptedHmacValue = ms.ToArray();
}

private HMAC GetHmacProvider(EncryptionInfoAgile.EncryptionKeyEncryptor ei, byte[] salt)
private HMAC GetHmacProvider(EncryptionInfoAgile.EncryptionKeyData ei, byte[] salt)
{
switch (ei.HashAlgorithm)
{
Expand Down Expand Up @@ -564,34 +564,36 @@ private MemoryStream DecryptAgile(EncryptionInfoAgile encryptionInfo, string pas
{
var encr = encryptionInfo.KeyEncryptors[0];
var hashProvider = GetHashProvider(encr);
var hashProviderDataKey = GetHashProvider(encryptionInfo.KeyData);

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);
var valInputKey = GetFinalHash(hashProvider, BlockKey_HashInput, baseHash);
var valHashKey = GetFinalHash(hashProvider, BlockKey_HashValue, baseHash);
var valKeySizeKey = GetFinalHash(hashProvider, 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);
encr.KeyValue = DecryptAgileFromKey(encr, valKeySizeKey, encr.EncryptedKeyValue, encryptionInfo.KeyData.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);
var ivhmac = GetFinalHash(hashProviderDataKey, BlockKey_HmacKey, encryptionInfo.KeyData.SaltValue);
var key = DecryptAgileFromKey(encryptionInfo.KeyData, 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);
ivhmac = GetFinalHash(hashProviderDataKey, BlockKey_HmacValue, encryptionInfo.KeyData.SaltValue);
var value = DecryptAgileFromKey(encryptionInfo.KeyData, encr.KeyValue, encryptionInfo.DataIntegrity.EncryptedHmacValue, encryptionInfo.KeyData.HashSize, ivhmac);

var hmca = GetHmacProvider(encr, key);
var hmca = GetHmacProvider(encryptionInfo.KeyData, 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"));
throw (new Exception("Dataintegrity key mismatch"));
}
}

Expand All @@ -604,11 +606,11 @@ private MemoryStream DecryptAgile(EncryptionInfoAgile encryptionInfo, string pas
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 iv = hashProviderDataKey.ComputeHash(ivTmp);
var buffer = new byte[bufferSize];
Array.Copy(encryptedData, pos, buffer, 0, bufferSize);

var b = DecryptAgileFromKey(encr, encr.KeyValue, buffer, segmentSize, iv);
var b = DecryptAgileFromKey(encryptionInfo.KeyData, encr.KeyValue, buffer, segmentSize, iv);
doc.Write(b, 0, b.Length);
pos += segmentSize;
segment++;
Expand Down Expand Up @@ -645,7 +647,7 @@ private HashAlgorithm GetHashProvider(EncryptionInfoAgile.EncryptionKeyEncryptor
}
}
#else
private HashAlgorithm GetHashProvider(EncryptionInfoAgile.EncryptionKeyEncryptor encr)
private HashAlgorithm GetHashProvider(EncryptionInfoAgile.EncryptionKeyData encr)
{
switch (encr.HashAlgorithm)
{
Expand Down Expand Up @@ -789,7 +791,7 @@ private bool IsPasswordValid(HashAlgorithm sha, EncryptionInfoAgile.EncryptionKe
return true;
}

private byte[] DecryptAgileFromKey(EncryptionInfoAgile.EncryptionKeyEncryptor encr, byte[] key, byte[] encryptedData, long size, byte[] iv)
private byte[] DecryptAgileFromKey(EncryptionInfoAgile.EncryptionKeyData encr, byte[] key, byte[] encryptedData, long size, byte[] iv)
{
SymmetricAlgorithm decryptKey = GetEncryptionAlgorithm(encr);
decryptKey.BlockSize = encr.BlockSize << 3;
Expand Down Expand Up @@ -837,7 +839,7 @@ private SymmetricAlgorithm GetEncryptionAlgorithm(EncryptionInfoAgile.Encryption
}
}
#else
private SymmetricAlgorithm GetEncryptionAlgorithm(EncryptionInfoAgile.EncryptionKeyEncryptor encr)
private SymmetricAlgorithm GetEncryptionAlgorithm(EncryptionInfoAgile.EncryptionKeyData encr)
{
switch (encr.CipherAlgorithm)
{
Expand Down Expand Up @@ -975,7 +977,7 @@ private byte[] GetPasswordHashAgile(string password, EncryptionInfoAgile.Encrypt
{
var hashProvider = GetHashProvider(encr);
var hash = GetPasswordHash(hashProvider, encr.SaltValue, password, encr.SpinCount, encr.HashSize);
var hashFinal = GetFinalHash(hashProvider, encr, blockKey, hash);
var hashFinal = GetFinalHash(hashProvider, blockKey, hash);

return FixHashSize(hashFinal, encr.KeyBits / 8);
}
Expand All @@ -984,7 +986,7 @@ private byte[] GetPasswordHashAgile(string password, EncryptionInfoAgile.Encrypt
throw (new Exception("An error occured when the encryptionkey was created", ex));
}
}
private byte[] GetFinalHash(HashAlgorithm hashProvider, EncryptionInfoAgile.EncryptionKeyEncryptor encr, byte[] blockKey, byte[] hash)
private byte[] GetFinalHash(HashAlgorithm hashProvider, byte[] blockKey, byte[] hash)
{
//2.3.4.13 MS-OFFCRYPTO
var tempHash = new byte[hash.Length + blockKey.Length];
Expand Down

0 comments on commit d0f364b

Please sign in to comment.