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

@ -178,13 +178,15 @@ namespace sscs.cache
{
byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), false);
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
{
{
ReEncryptPasscodeUsingRandomSalt(baPasscode, sDesktopPassword, GetPasscodeByDesktopFilePath());
return true;
}
// try old salt
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(sDesktopPassword, GetPasscodeByDesktopFilePath(), true);
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
{
{
ReEncryptPasscodeUsingRandomSalt(baPasscode, sDesktopPassword, GetPasscodeByDesktopFilePath());
return true;
}
}
@ -248,7 +250,7 @@ namespace sscs.cache
if (CASACrypto.ValidatePasscode(baPasscode, GetServerValidationFilePath()))
{
slss = new LocalStorage(this, baPasscode, true);
bIsServerStorePersistent = true;
bIsServerStorePersistent = true;
return true;
}
}
@ -337,7 +339,8 @@ namespace sscs.cache
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
{
lss = new LocalStorage(this, baPasscode);
bIsStorePersistent = true;
bIsStorePersistent = true;
ReEncryptPasscodeUsingRandomSalt(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
return true;
}
else
@ -346,8 +349,9 @@ namespace sscs.cache
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), true);
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
{
// rewrite file using new encryption
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
// rewrite file using new encryption
ReEncryptPasscodeUsingRandomSalt(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
//CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, desktopPasswd, GetPasscodeByDesktopFilePath());
lss = new LocalStorage(this, baPasscode);
bIsStorePersistent = true;
return true;
@ -409,31 +413,29 @@ namespace sscs.cache
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(desktopPasswd, GetPasscodeByDesktopFilePath(), false);
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
{
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(
baPasscode,
mPasswd,
GetPasscodeByMasterPasswdFilePath());
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
return true;
}
else
{
// try old method
baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(
desktopPasswd,
GetPasscodeByDesktopFilePath(),
true);
desktopPasswd,
GetPasscodeByDesktopFilePath(),
true);
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
{
// rewrite file using new method
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(
baPasscode,
desktopPasswd,
GetPasscodeByDesktopFilePath());
baPasscode,
desktopPasswd,
GetPasscodeByDesktopFilePath());
CASACrypto.EncryptAndStoreMasterPasscodeUsingString(
baPasscode,
mPasswd,
GetPasscodeByMasterPasswdFilePath());
baPasscode,
mPasswd,
GetPasscodeByMasterPasswdFilePath());
return true;
}
else
@ -517,7 +519,8 @@ namespace sscs.cache
{
if (bIsStorePersistent == false)
{
lss = new LocalStorage(this, baPasscode);
lss = new LocalStorage(this, baPasscode);
ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
bIsStorePersistent = true;
}
return true;
@ -552,7 +555,8 @@ namespace sscs.cache
RewriteDesktopPasswdFile(baPasscode, desktopPasswd);
if (bIsStorePersistent == false)
{
lss = new LocalStorage(this, baPasscode);
lss = new LocalStorage(this, baPasscode);
ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
bIsStorePersistent = true;
}
return true;
@ -565,7 +569,8 @@ namespace sscs.cache
RewriteDesktopPasswdFile(baPasscode, desktopPasswd);
if (bIsStorePersistent == false)
{
lss = new LocalStorage(this, baPasscode);
lss = new LocalStorage(this, baPasscode);
ReEncryptPasscodeUsingRandomSalt(baPasscode, mPasswd, GetPasscodeByMasterPasswdFilePath());
bIsStorePersistent = true;
}
return true;
@ -603,7 +608,8 @@ namespace sscs.cache
{
byte[] baPasscode = CASACrypto.GetMasterPasscodeUsingDesktopPasswd(oldDesktopPasswd, GetPasscodeByDesktopFilePath(), false);
if (CASACrypto.ValidatePasscode(baPasscode, GetValidationFilePath()))
{
{
ReEncryptPasscodeUsingRandomSalt(baPasscode, oldDesktopPasswd, GetPasscodeByDesktopFilePath());
return baPasscode;
}
else
@ -1071,7 +1077,7 @@ namespace sscs.cache
// encrypt if an encryptionstring was passed
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.
baSecrets = sscs.crypto.CASACrypto.EncryptData(baSecrets, baKey, ref baIV);
@ -1089,7 +1095,7 @@ namespace sscs.cache
if (sEncryptionString != null)
{
// 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);
MergeXMLSecrets(baBuffer);
}
@ -1101,6 +1107,14 @@ namespace sscs.cache
String sXMLData = Encoding.ASCII.GetString(decryptedXmlSecrets);
doc.LoadXml(sXMLData);
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()

View File

@ -40,12 +40,12 @@ namespace sscs.crypto
private const int HASH_SIZE = 32;
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
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);
}
catch(Exception e)
@ -531,7 +531,7 @@ namespace sscs.crypto
{
if(File.Exists(fileName))
File.Delete(fileName);
byte[] baKey = Generate16ByteKeyFromString(passwd, null, false);
byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, false, true);
//Get an encryptor.
RijndaelManaged myRijndael = new RijndaelManaged();
@ -578,7 +578,7 @@ namespace sscs.crypto
try
{
byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, bTryOldMethod);
byte[] baKey = Generate16ByteKeyFromString(passwd, fileName, bTryOldMethod, false);
/* Get a decryptor that uses the same key and
* IV as the encryptor.

View File

@ -54,6 +54,7 @@
//using System.Runtime.InteropServices;
using System;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using sscs.lss;
@ -105,11 +106,11 @@ namespace sscs.crypto {
}
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)
throw new ArgumentNullException ("password");
@ -121,14 +122,70 @@ namespace sscs.crypto {
Salt = GenerateOldSalt(password, saltSize);
}
else
{
Salt = GenerateNewSalt(password, saltSize);
{
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);
}
}
}
IterationCount = iterations;
_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)
{
byte[] buffer = new byte[saltSize];