/// ---------------------------------------------------------------------------------------- /// <summary> /// Read SEB settings from UserDefaults and encrypt them using provided security credentials /// </summary> /// ---------------------------------------------------------------------------------------- public static byte[] EncryptSEBSettingsWithCredentials(SebSettings settings, string settingsPassword, bool passwordIsHash, X509Certificate2 certificateRef, SebSettings.sebConfigPurposes configPurpose, bool forEditing) { // Get current settings dictionary and clean it from empty arrays and dictionaries //DictObj cleanedCurrentSettings = SEBSettings.CleanSettingsDictionary(); // Serialize preferences dictionary to an XML string var sebXML = PropertyList.writeXml(settings.settingsCurrent); var encryptedSebData = Encoding.UTF8.GetBytes(sebXML); string encryptingPassword = null; // Check for special case: .seb configures client, empty password if(String.IsNullOrEmpty(settingsPassword) && configPurpose == SebSettings.sebConfigPurposes.sebConfigPurposeConfiguringClient) { encryptingPassword = ""; } else { // in all other cases: // Check if no password entered and no identity selected if(String.IsNullOrEmpty(settingsPassword) && certificateRef == null) { if(SebMessageBox.DisableInteractive || SebMessageBox.Show(SEBUIStrings.noEncryptionChosen, SEBUIStrings.noEncryptionChosenSaveUnencrypted, MessageBoxImage.Question, MessageBoxButton.YesNo) == MessageBoxResult.Yes) { // OK: save .seb config data unencrypted return encryptedSebData; } else { return null; } } } // gzip the serialized XML data encryptedSebData = GZipByte.Compress(encryptedSebData); // Check if password for encryption is provided and use it then if(!String.IsNullOrEmpty(settingsPassword)) { encryptingPassword = settingsPassword; } // So if password is empty (special case) or provided if(encryptingPassword != null) { // encrypt with password encryptedSebData = EncryptDataUsingPassword(encryptedSebData, encryptingPassword, passwordIsHash, configPurpose); } else { // Create byte array large enough to hold prefix and data byte[] encryptedData = new byte[encryptedSebData.Length + PREFIX_LENGTH]; // if no encryption with password: Add a 4-char prefix identifying plain data string prefixString = PLAIN_DATA_MODE; Buffer.BlockCopy(Encoding.UTF8.GetBytes(prefixString), 0, encryptedData, 0, PREFIX_LENGTH); // append plain data Buffer.BlockCopy(encryptedSebData, 0, encryptedData, PREFIX_LENGTH, encryptedSebData.Length); encryptedSebData = (byte[])encryptedData.Clone(); } // Check if cryptographic identity for encryption is selected if(certificateRef != null) { // Encrypt preferences using a cryptographic identity encryptedSebData = EncryptDataUsingIdentity(encryptedSebData, certificateRef); } // gzip the encrypted data encryptedSebData = GZipByte.Compress(encryptedSebData); return encryptedSebData; }
/// ---------------------------------------------------------------------------------------- /// <summary> /// Decrypt, parse and use new SEB settings /// </summary> /// ---------------------------------------------------------------------------------------- public static bool StoreDecryptedSEBSettings(byte[] sebData, GetPasswordMethod getPassword, SebSettings settings) { Logger.AddInformation("Reconfiguring"); string sebFilePassword = null; bool passwordIsHash = false; X509Certificate2 sebFileCertificateRef = null; var sebPreferencesDict = DecryptSEBSettings(sebData, getPassword, false, ref sebFilePassword, ref passwordIsHash, ref sebFileCertificateRef); if(sebPreferencesDict == null) { return false; //Decryption didn't work, we abort } // Store decrypted settings Logger.AddInformation("Attempting to StoreSebClientSettings"); settings.StoreSebClientSettings(sebPreferencesDict); Logger.AddInformation("Successfully StoreSebClientSettings"); return true; }
/// ---------------------------------------------------------------------------------------- /// <summary> /// Encrypt preferences using a password /// </summary> /// ---------------------------------------------------------------------------------------- // Encrypt preferences using a password public static byte[] EncryptDataUsingPassword(byte[] data, string password, bool passwordIsHash, SebSettings.sebConfigPurposes configPurpose) { string prefixString; // Check if .seb file should start exam or configure client if(configPurpose == SebSettings.sebConfigPurposes.sebConfigPurposeStartingExam) { // prefix string for starting exam: normal password will be prompted prefixString = PASSWORD_MODE; } else { // prefix string for configuring client: configuring password will either be hashed admin pw on client // or if no admin pw on client set: empty pw prefixString = PASSWORD_CONFIGURING_CLIENT_MODE; if(!String.IsNullOrEmpty(password) && !passwordIsHash) { //empty password means no admin pw on clients and should not be hashed //or we got already a hashed admin pw as settings pw, then we don't hash again password = SebProtectionController.ComputePasswordHash(password); } } byte[] encryptedData = SebProtectionController.EncryptDataWithPassword(data, password); // Create byte array large enough to hold prefix and data byte[] encryptedSebData = new byte[encryptedData.Length + PREFIX_LENGTH]; Buffer.BlockCopy(Encoding.UTF8.GetBytes(prefixString), 0, encryptedSebData, 0, PREFIX_LENGTH); Buffer.BlockCopy(encryptedData, 0, encryptedSebData, PREFIX_LENGTH, encryptedData.Length); return encryptedSebData; }
public static string CreateSaltedBrowserExamKey(SebSettings settings, Uri uri, string platformHash) { return GetStringSHA256(uri.AbsoluteUri + platformHash); }
/// ---------------------------------------------------------------------------------------- /// <summary> /// Compute a Browser Exam Key SHA256 hash base16 string. /// </summary> /// ---------------------------------------------------------------------------------------- public static string ComputeBrowserExamKeyFromFilesHash(SebSettings settings, string filesHash = null) { // Serialize preferences dictionary to an XML string var sebXml = PropertyList.writeXml(settings.settingsCurrent); //Add the Hash of the Executable and of the XulRunnerFiles to the message sebXml = String.Format("{0}{1}", sebXml, filesHash); // TODO: Implement proper and secure HMAC-SHA256 // var salt = settings.Get<byte[]>(SebSettings.KeyExamKeySalt); // var hash = new HMACSHA256(salt); return GetStringSHA256(sebXml); }
public static string ComputeBrowserExamKey(SebSettings settings, string binDir) { return ComputeBrowserExamKeyFromFilesHash(settings, CreateFilesHashWindows(binDir)); }
static SebInstance() { Settings = new SebSettings(); }