protected override void Execute(CodeActivityContext context) { try { string inputFilePath = InputFilePath.Get(context); string outputFilePath = OutputFilePath.Get(context); string key = Key.Get(context); Encoding keyEncoding = KeyEncoding.Get(context); if (string.IsNullOrWhiteSpace(inputFilePath)) { throw new ArgumentNullException(Resources.InputFilePathDisplayName); } if (string.IsNullOrWhiteSpace(outputFilePath)) { throw new ArgumentNullException(Resources.OutputFilePathDisplayName); } if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentNullException(Resources.Key); } if (keyEncoding == null) { throw new ArgumentNullException(Resources.Encoding); } if (!File.Exists(inputFilePath)) { throw new ArgumentException(Resources.FileDoesNotExistsException, Resources.InputFilePathDisplayName); } // Because we use File.WriteAllText below, we don't need to delete the file now. if (File.Exists(outputFilePath) && !Overwrite) { throw new ArgumentException(Resources.FileAlreadyExistsException, Resources.OutputFilePathDisplayName); } byte[] encrypted = File.ReadAllBytes(inputFilePath); byte[] decrypted = null; try { decrypted = CryptographyHelper.DecryptData(Algorithm, encrypted, keyEncoding.GetBytes(key)); } catch (CryptographicException ex) { throw new InvalidOperationException(Resources.GenericCryptographicException, ex); } // This overwrites the file if it already exists. File.WriteAllBytes(outputFilePath, decrypted); } catch (Exception ex) { Trace.TraceError(ex.ToString()); if (!ContinueOnError.Get(context)) { throw; } } }
/// <summary> /// Constructs a key based on a string <paramref name="name"/>. /// /// If the string is of the form "{16-digit hex}" or "{8-digit hex},{8-digit hex}", this will be parsed into numeric keys. /// /// If the string is an ascii string with 9 or fewer characters, it will be mapped to a key that does not collide with /// any other key based on such a string or based on a 32-bit value. /// /// Other string names will be rejected unless <paramref name="allowHashing"/> is specified, in which case it will be hashed to /// a 64-bit key value. /// </summary> public PostgresAdvisoryLockKey(string name, bool allowHashing = false) { if (name == null) { throw new ArgumentNullException(nameof(name)); } if (TryEncodeAscii(name, out this._key)) { this._keyEncoding = KeyEncoding.Ascii; } else if (TryEncodeHashString(name, out this._key, out var hasSeparator)) { this._keyEncoding = hasSeparator ? KeyEncoding.Int32Pair : KeyEncoding.Int64; } else if (allowHashing) { this._key = HashString(name); this._keyEncoding = KeyEncoding.Int64; } else { throw new FormatException($"Name '{name}' could not be encoded as a {nameof(PostgresAdvisoryLockKey)}. Please specify {nameof(allowHashing)} or use one of the following formats:" + $" or (1) a 0-{MaxAsciiLength} character string using only ASCII characters" + $", (2) a {HashStringLength} character hex string, such as the result of Int64.MaxValue.ToString(\"x{HashStringLength}\")" + $", or (3) a 2-part, {SeparatedHashStringLength} character string of the form XXXXXXXX{HashStringSeparator}XXXXXXXX, where the X's are {HashPartLength} hex strings" + $" such as the result of Int32.MaxValue.ToString(\"x{HashPartLength}\")." + " Note that each unique string provided for formats 1 and 2 will map to a unique hash value, with no collisions across formats. Format 3 strings use the same key space as 2."); } }
public static string FormatByteArray(byte[] data, KeyEncoding encoding) { switch (encoding) { case KeyEncoding.DecArray: return(string.Join(", ", from b in data select b)); case KeyEncoding.HexArray: return("0x" + string.Join(", 0x", from b in data select b.ToString("X2"))); case KeyEncoding.UpperHex: return(string.Join(string.Empty, from b in data select b.ToString("X2"))); case KeyEncoding.LowerHex: return(string.Join(string.Empty, from b in data select b.ToString("x2"))); case KeyEncoding.Base64: return(Convert.ToBase64String(data)); case KeyEncoding.UrlSafeBase64: return(Convert.ToBase64String(data).Replace('-', '+').Replace('/', '_')); default: throw new ArgumentOutOfRangeException("encoding"); } }
public static byte[] ToBytes(this string input, KeyEncoding keyEncoding = KeyEncoding.UTF8) { return(keyEncoding switch { KeyEncoding.ASCII => Encoding.ASCII.GetBytes(input), KeyEncoding.Base64 => Convert.FromBase64String(input), _ => Encoding.UTF8.GetBytes(input), });
/// <summary> /// Return decoded key from configured key value /// </summary> /// <returns>decoded key</returns> protected byte[] DecodeKey() { if (!KeyEncoding.Equals("base64", StringComparison.CurrentCultureIgnoreCase)) { return(Encoding.UTF8.GetBytes(KeyValue)); } else { return(Convert.FromBase64String(KeyValue)); } }
public static string GenerateKey(int length, KeyEncoding encoding) { // Validate arguments if (length < 1) { throw new ArgumentOutOfRangeException("length"); } // Get random bytes var chaos = new byte[length]; using (var rng = new RNGCryptoServiceProvider()) { rng.GetBytes(chaos); } // Format random bytes to various formats return(FormatByteArray(chaos, encoding)); }
/// <summary> /// Parses a string into the key /// </summary> /// <param name="keyString">The string to parse</param> /// <returns>Whether or not the parsing was succesfull</returns> private bool ParseKey(String keyString) { KeyEncoding encoding = KeyEncoding.UNKNOWN; String nums = "0123456789"; String hexNums = "abcdefABCDEF"; //Establish which format to parse the string as foreach (char c in keyString.ToCharArray()) { switch (encoding) { case KeyEncoding.UNKNOWN: if (nums.Contains(c)) { encoding = KeyEncoding.DECIMAL; } else if (hexNums.Contains(c)) { encoding = KeyEncoding.HEX; } else if ((short)c <= 255) { encoding = KeyEncoding.ASCII; } else { encoding = KeyEncoding.UNICODE; } break; case KeyEncoding.DECIMAL: if (nums.Contains(c)) { continue; } else if (hexNums.Contains(c)) { encoding = KeyEncoding.HEX; } else if ((short)c <= 255) { encoding = KeyEncoding.ASCII; } else { encoding = KeyEncoding.UNICODE; } break; case KeyEncoding.HEX: if (nums.Contains(c) || hexNums.Contains(c)) { continue; } else if ((short)c <= 255) { encoding = KeyEncoding.ASCII; } else { encoding = KeyEncoding.UNICODE; } break; case KeyEncoding.ASCII: if ((short)c <= 255) { continue; } else { encoding = KeyEncoding.UNICODE; } break; } } switch (encoding) { //For decimal, just parse. Easy Peasy case KeyEncoding.DECIMAL: try { key = UInt128.Parse(keyString); return(true); } catch (Exception e) { Console.WriteLine(e.Message); return(false); } //For hex first add 00 at the start of the string to ensure good parsing, and then parse case KeyEncoding.HEX: try { UInt128.TryParse("00" + keyString, System.Globalization.NumberStyles.HexNumber, System.Globalization.NumberFormatInfo.CurrentInfo, out this.key); return(true); } catch (Exception e) { Console.WriteLine(e.Message); return(false); } //For ASCII take the low byte of the characters case KeyEncoding.ASCII: if (keyString.Length > BlockSize) { Console.WriteLine("Key too long, maximum of 16 ASCII characters allowed"); return(false); } key = 0; for (int i = 0; i < keyString.Length; i++) { key |= (UInt128)((byte)keyString.ToCharArray()[i] << (i * 8)); } return(true); //For unicode take both bytes of the characters case KeyEncoding.UNICODE: if (keyString.Length * 2 > BlockSize) { Console.WriteLine("Key too long, maximum of 8 Unicode characters allowed"); return(false); } key = 0; for (int i = 0; i < keyString.Length; i++) { key |= (UInt128)((short)(keyString.ToCharArray()[i]) << (i * 16)); } return(true); } return(false); }
/// <summary> /// Constructs a key from a pair of 32-bit values. This is a separate key space /// than <see cref="PostgresAdvisoryLockKey(long)"/>. /// </summary> public PostgresAdvisoryLockKey(int key1, int key2) { this._key = CombineKeys(key1, key2); this._keyEncoding = KeyEncoding.Int32Pair; }
/// <summary> /// Constructs a key from a single 64-bit value. This is a separate key space /// than <see cref="PostgresAdvisoryLockKey(int, int)"/>. /// </summary> public PostgresAdvisoryLockKey(long key) { this._key = key; this._keyEncoding = KeyEncoding.Int64; }