Bug 242387. Security Audit: Use a random salt when generating encryption key from string. This prevents code book attacks.

This commit is contained in:
Jim Norman 2007-04-02 19:05:50 +00:00
parent f84d06fdd6
commit a2ab8d3f36
3 changed files with 104 additions and 33 deletions

View File

@ -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()
{ {

View File

@ -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.

View File

@ -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];