Bug 242387. Security Audit: Use a random salt when generating encryption key from string. This prevents code book attacks.
This commit is contained in:
parent
f84d06fdd6
commit
a2ab8d3f36
28
CASA/micasad/cache/SecretStore.cs
vendored
28
CASA/micasad/cache/SecretStore.cs
vendored
@ -179,12 +179,14 @@ namespace sscs.cache
|
|||||||
byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), false);
|
byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), false);
|
||||||
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
||||||
{
|
{
|
||||||
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, sDesktopPassword, GetPasscodeByDesktopFilePath());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// try old salt
|
// try old salt
|
||||||
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), true);
|
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), true);
|
||||||
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
||||||
{
|
{
|
||||||
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, sDesktopPassword, GetPasscodeByDesktopFilePath());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,6 +340,7 @@ namespace sscs.cache
|
|||||||
{
|
{
|
||||||
lss = new LocalStorage(this, baPasscode);
|
lss = new LocalStorage(this, baPasscode);
|
||||||
bIsStorePersistent = true;
|
bIsStorePersistent = true;
|
||||||
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -347,7 +350,8 @@ namespace sscs.cache
|
|||||||
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
||||||
{
|
{
|
||||||
// rewrite file using new encryption
|
// rewrite file using new encryption
|
||||||
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
|
||||||
|
//CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
|
||||||
lss = new LocalStorage(this, baPasscode);
|
lss = new LocalStorage(this, baPasscode);
|
||||||
bIsStorePersistent = true;
|
bIsStorePersistent = true;
|
||||||
return true;
|
return true;
|
||||||
@ -409,10 +413,7 @@ namespace sscs.cache
|
|||||||
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), false);
|
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), false);
|
||||||
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
||||||
{
|
{
|
||||||
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(
|
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
|
||||||
baPasscode,
|
|
||||||
mPasswd,
|
|
||||||
GetPasscodeByMasterPasswdFilePath());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -422,6 +423,7 @@ namespace sscs.cache
|
|||||||
desktopPasswd,
|
desktopPasswd,
|
||||||
GetPasscodeByDesktopFilePath(),
|
GetPasscodeByDesktopFilePath(),
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
||||||
{
|
{
|
||||||
// rewrite file using new method
|
// rewrite file using new method
|
||||||
@ -518,6 +520,7 @@ namespace sscs.cache
|
|||||||
if (bIsStorePersistent == false)
|
if (bIsStorePersistent == false)
|
||||||
{
|
{
|
||||||
lss = new LocalStorage(this, baPasscode);
|
lss = new LocalStorage(this, baPasscode);
|
||||||
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
|
||||||
bIsStorePersistent = true;
|
bIsStorePersistent = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -553,6 +556,7 @@ namespace sscs.cache
|
|||||||
if (bIsStorePersistent == false)
|
if (bIsStorePersistent == false)
|
||||||
{
|
{
|
||||||
lss = new LocalStorage(this, baPasscode);
|
lss = new LocalStorage(this, baPasscode);
|
||||||
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
|
||||||
bIsStorePersistent = true;
|
bIsStorePersistent = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -566,6 +570,7 @@ namespace sscs.cache
|
|||||||
if (bIsStorePersistent == false)
|
if (bIsStorePersistent == false)
|
||||||
{
|
{
|
||||||
lss = new LocalStorage(this, baPasscode);
|
lss = new LocalStorage(this, baPasscode);
|
||||||
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
|
||||||
bIsStorePersistent = true;
|
bIsStorePersistent = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -604,6 +609,7 @@ namespace sscs.cache
|
|||||||
byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(oldDesktopPasswd, GetPasscodeByDesktopFilePath(), false);
|
byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(oldDesktopPasswd, GetPasscodeByDesktopFilePath(), false);
|
||||||
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
|
||||||
{
|
{
|
||||||
|
ReEncryptPasscodeUsingRandomSalt(baPasscode, oldDesktopPasswd, GetPasscodeByDesktopFilePath());
|
||||||
return baPasscode;
|
return baPasscode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1071,7 +1077,7 @@ namespace sscs.cache
|
|||||||
// encrypt if an encryptionstring was passed
|
// encrypt if an encryptionstring was passed
|
||||||
if ((sEncryptionString != null) && (sEncryptionString.Length > 0))
|
if ((sEncryptionString != null) && (sEncryptionString.Length > 0))
|
||||||
{
|
{
|
||||||
byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false);
|
byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false, false);
|
||||||
|
|
||||||
// now encypt it.
|
// now encypt it.
|
||||||
baSecrets = sscs.crypto.CASACrypto.EncryptData(baSecrets, baKey, ref baIV);
|
baSecrets = sscs.crypto.CASACrypto.EncryptData(baSecrets, baKey, ref baIV);
|
||||||
@ -1089,7 +1095,7 @@ namespace sscs.cache
|
|||||||
if (sEncryptionString != null)
|
if (sEncryptionString != null)
|
||||||
{
|
{
|
||||||
// decrypt the buffer using the string passed in.
|
// decrypt the buffer using the string passed in.
|
||||||
byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false);
|
byte[] baKey = sscs.crypto.CASACrypto.Generate16ByteKeyFromString(sEncryptionString, null, false, false);
|
||||||
byte[] baBuffer = sscs.crypto.CASACrypto.DecryptData(encryptedXmlSecrets, baKey, baIV);
|
byte[] baBuffer = sscs.crypto.CASACrypto.DecryptData(encryptedXmlSecrets, baKey, baIV);
|
||||||
MergeXMLSecrets(baBuffer);
|
MergeXMLSecrets(baBuffer);
|
||||||
}
|
}
|
||||||
@ -1103,6 +1109,14 @@ namespace sscs.cache
|
|||||||
LocalStorage.AddXMLSecretsToStore(this, doc);
|
LocalStorage.AddXMLSecretsToStore(this, doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ReEncryptPasscodeUsingRandomSalt(byte[] baPasscode, string sPassword, string sFilepath)
|
||||||
|
{
|
||||||
|
if (!File.Exists(sFilepath + ".salt"))
|
||||||
|
{
|
||||||
|
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, sPassword, sFilepath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal void CreatePolicyDirectory()
|
internal void CreatePolicyDirectory()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -40,12 +40,12 @@ namespace sscs.crypto
|
|||||||
private const int HASH_SIZE = 32;
|
private const int HASH_SIZE = 32;
|
||||||
private const uint MAX_FILE_SIZE = 16 * 1024 * 1024; //16 MB
|
private const uint MAX_FILE_SIZE = 16 * 1024 * 1024; //16 MB
|
||||||
|
|
||||||
internal static byte[] Generate16ByteKeyFromString(string sTheString, string sFilepath, bool bUseOldMethod)
|
internal static byte[] Generate16ByteKeyFromString(string sTheString, string sFilepath, bool bUseOldMethod, bool bGenerateRandomSalt)
|
||||||
{
|
{
|
||||||
byte[] baKey = new byte[16]; //return value
|
byte[] baKey = new byte[16]; //return value
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes(sTheString, SALTSIZE, ITERATION_COUNT, bUseOldMethod);
|
Rfc2898DeriveBytes pkcs5 = new Rfc2898DeriveBytes(sTheString, SALTSIZE, ITERATION_COUNT, bUseOldMethod, sFilepath, bGenerateRandomSalt);
|
||||||
baKey = pkcs5.GetBytes(16);
|
baKey = pkcs5.GetBytes(16);
|
||||||
}
|
}
|
||||||
catch(Exception e)
|
catch(Exception e)
|
||||||
@ -531,7 +531,7 @@ namespace sscs.crypto
|
|||||||
{
|
{
|
||||||
if(File.Exists(fileName))
|
if(File.Exists(fileName))
|
||||||
File.Delete(fileName);
|
File.Delete(fileName);
|
||||||
byte[] baKey = Generate16ByteKeyFromString(passwd, null, false);
|
byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, false, true);
|
||||||
|
|
||||||
//Get an encryptor.
|
//Get an encryptor.
|
||||||
RijndaelManaged myRijndael = new RijndaelManaged();
|
RijndaelManaged myRijndael = new RijndaelManaged();
|
||||||
@ -578,7 +578,7 @@ namespace sscs.crypto
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, bTryOldMethod);
|
byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, bTryOldMethod, false);
|
||||||
|
|
||||||
/* Get a decryptor that uses the same key and
|
/* Get a decryptor that uses the same key and
|
||||||
* IV as the encryptor.
|
* IV as the encryptor.
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
//using System.Runtime.InteropServices;
|
//using System.Runtime.InteropServices;
|
||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
using sscs.lss;
|
using sscs.lss;
|
||||||
@ -105,11 +106,11 @@ namespace sscs.crypto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Rfc2898DeriveBytes(string password, int saltSize, int iterations)
|
public Rfc2898DeriveBytes(string password, int saltSize, int iterations)
|
||||||
: this (password, saltSize, iterations, false)
|
: this (password, saltSize, iterations, false, null, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rfc2898DeriveBytes (string password, int saltSize, int iterations, bool bUseOldMethod)
|
public Rfc2898DeriveBytes (string password, int saltSize, int iterations, bool bUseOldMethod, string sFilepath, bool bGenerateAndSaveRandomSalt)
|
||||||
{
|
{
|
||||||
if (password == null)
|
if (password == null)
|
||||||
throw new ArgumentNullException ("password");
|
throw new ArgumentNullException ("password");
|
||||||
@ -121,14 +122,70 @@ namespace sscs.crypto {
|
|||||||
Salt = GenerateOldSalt(password, saltSize);
|
Salt = GenerateOldSalt(password, saltSize);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (bGenerateAndSaveRandomSalt)
|
||||||
|
{
|
||||||
|
Salt = GenerateAndSaveRandomSalt(saltSize, sFilepath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// load saved salt if one was saved
|
||||||
|
if ((sFilepath != null) && (File.Exists(sFilepath + ".salt")))
|
||||||
|
{
|
||||||
|
Salt = LoadSavedSalt(sFilepath);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Salt = GenerateNewSalt(password, saltSize);
|
Salt = GenerateNewSalt(password, saltSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IterationCount = iterations;
|
IterationCount = iterations;
|
||||||
_hmac = new HMACSHA1 (Encoding.UTF8.GetBytes (password));
|
_hmac = new HMACSHA1 (Encoding.UTF8.GetBytes (password));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private byte[] GenerateAndSaveRandomSalt(int saltSize, string sFilepath)
|
||||||
|
{
|
||||||
|
byte[] randomSalt = new byte[saltSize];
|
||||||
|
FastRandom fr = new FastRandom();
|
||||||
|
fr.NextBytes(randomSalt);
|
||||||
|
|
||||||
|
// save salt
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileStream fs = new FileStream(sFilepath + ".salt", FileMode.Create);
|
||||||
|
fs.Write(randomSalt, 0, randomSalt.Length);
|
||||||
|
fs.Flush();
|
||||||
|
fs.Close();
|
||||||
|
File.SetAttributes(sFilepath + ".salt", FileAttributes.Hidden);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomSalt;
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] LoadSavedSalt(string sFilePath)
|
||||||
|
{
|
||||||
|
byte[] baSalt = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
FileStream fs = new FileStream(sFilePath + ".salt", FileMode.Open);
|
||||||
|
baSalt = new byte[fs.Length];
|
||||||
|
fs.Read(baSalt, 0, (int)fs.Length);
|
||||||
|
fs.Close();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
return baSalt;
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] GenerateOldSalt(string password, int saltSize)
|
private static byte[] GenerateOldSalt(string password, int saltSize)
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[saltSize];
|
byte[] buffer = new byte[saltSize];
|
||||||
|
Loading…
Reference in New Issue
Block a user