/// <summary> /// Decrypt a string sequence using the selected encryption types /// </summary> /// <param name="data">hex coded string sequence to decrypt</param> /// <param name="encryptedTypes">Encryption types</param> /// <param name="password">optional password</param> /// <param name="yubidata">optional yubi data</param> /// <param name="decode"></param> /// <returns>decrypted string sequence</returns> private static string DecryptSequenceNoHash(string data, PasswordTypes encryptedTypes, string password, YubiKey yubi, bool decode = false) { try { // reverse order they were encrypted if ((encryptedTypes & PasswordTypes.Machine) != 0) { // we are going to decrypt with the Windows local machine key byte[] cipher = Authenticator.StringToByteArray(data); byte[] plain = ProtectedData.Unprotect(cipher, null, DataProtectionScope.LocalMachine); if (decode == true) { data = Encoding.UTF8.GetString(plain, 0, plain.Length); } else { data = ByteArrayToString(plain); } } if ((encryptedTypes & PasswordTypes.User) != 0) { // we are going to decrypt with the Windows User account key byte[] cipher = StringToByteArray(data); byte[] plain = ProtectedData.Unprotect(cipher, null, DataProtectionScope.CurrentUser); if (decode == true) { data = Encoding.UTF8.GetString(plain, 0, plain.Length); } else { data = ByteArrayToString(plain); } } if ((encryptedTypes & PasswordTypes.Explicit) != 0) { // we use an explicit password to encrypt data if (string.IsNullOrEmpty(password) == true) { throw new EncrpytedSecretDataException(); } data = Authenticator.Decrypt(data, password, true); if (decode == true) { byte[] plain = Authenticator.StringToByteArray(data); data = Encoding.UTF8.GetString(plain, 0, plain.Length); } } if ((encryptedTypes & PasswordTypes.YubiKeySlot1) != 0 || (encryptedTypes & PasswordTypes.YubiKeySlot2) != 0) { if (string.IsNullOrEmpty(yubi.Info.Error) == false) { throw new BadYubiKeyException("Unable to detect YubiKey"); } if (yubi.Info.Status.VersionMajor == 0) { throw new BadYubiKeyException("Please insert your YubiKey"); } int slot = ((encryptedTypes & PasswordTypes.YubiKeySlot1) != 0 ? 1 : 2); string seed = data.Substring(0, SALT_LENGTH * 2); data = data.Substring(seed.Length); byte[] key = yubi.ChallengeResponse(slot, StringToByteArray(seed)); data = Authenticator.Decrypt(data, key); if (decode == true) { byte[] plain = Authenticator.StringToByteArray(data); data = Encoding.UTF8.GetString(plain, 0, plain.Length); } yubi.YubiData.Seed = seed; yubi.YubiData.Data = key; } } catch (EncrpytedSecretDataException) { throw; } catch (BadYubiKeyException ) { throw; } catch (ChallengeResponseException ex) { throw new BadYubiKeyException("Please check your YubiKey or touch the flashing button", ex); } catch (Exception ex) { throw new BadPasswordException(ex.Message, ex); } return data; }
public static string EncryptSequence(string data, PasswordTypes passwordType, string password, YubiKey yubi) { // get hash of original var random = new RNGCryptoServiceProvider(); byte[] saltbytes = new byte[SALT_LENGTH]; random.GetBytes(saltbytes); string salt = ByteArrayToString(saltbytes); string hash; using (var sha = new SHA256Managed()) { byte[] plain = StringToByteArray(salt + data); hash = ByteArrayToString(sha.ComputeHash(plain)); } if ((passwordType & PasswordTypes.YubiKeySlot1) != 0 || (passwordType & PasswordTypes.YubiKeySlot2) != 0) { if (yubi.YubiData.Length == 0) { byte[] seed = new byte[SALT_LENGTH]; random = new RNGCryptoServiceProvider(); random.GetBytes(seed); // we encrypt the data using the hash of a random string from the YubiKey int slot = ((passwordType & PasswordTypes.YubiKeySlot1) != 0 ? 1 : 2); yubi.YubiData.Data = yubi.ChallengeResponse(slot, seed); yubi.YubiData.Seed = Authenticator.ByteArrayToString(seed); } byte[] key = yubi.YubiData.Data; string encrypted = Encrypt(data, key); // test the encryption string decrypted = Decrypt(encrypted, key); if (string.Compare(data, decrypted) != 0) { throw new InvalidEncryptionException(data, password, encrypted, decrypted); } data = yubi.YubiData.Seed + encrypted; } if ((passwordType & PasswordTypes.Explicit) != 0) { string encrypted = Encrypt(data, password); // test the encryption string decrypted = Decrypt(encrypted, password, true); if (string.Compare(data, decrypted) != 0) { throw new InvalidEncryptionException(data, password, encrypted, decrypted); } data = encrypted; } if ((passwordType & PasswordTypes.User) != 0) { // we encrypt the data using the Windows User account key byte[] plain = StringToByteArray(data); byte[] cipher = ProtectedData.Protect(plain, null, DataProtectionScope.CurrentUser); data = ByteArrayToString(cipher); } if ((passwordType & PasswordTypes.Machine) != 0) { // we encrypt the data using the Local Machine account key byte[] plain = StringToByteArray(data); byte[] cipher = ProtectedData.Protect(plain, null, DataProtectionScope.LocalMachine); data = ByteArrayToString(cipher); } // prepend the salt + hash return ENCRYPTION_HEADER + salt + hash + data; }