public static void Save(AnsibleVaultFile f, TextWriter output, string label, int width = 80)
        {
            if (string.IsNullOrEmpty(f.Label))
            {
                output.WriteLine($"{AnsibleVaultSignature};{f.Version};{f.Algorithm}");
            }
            else
            {
                output.WriteLine($"{AnsibleVaultSignature};{f.Version};{f.Algorithm};{f.Label}");
            }
            var data     = new byte[f.Salt.Length * 2 + f.ExpectedHMac.Length * 2 + f.EncryptedBytes.Length * 2 + 2];
            var dataSpan = data.AsSpan();

            Encoding.ASCII.GetBytes(ByteUtil.ConvertToHexString(f.Salt)).AsSpan().CopyTo(dataSpan);
            dataSpan[f.Salt.Length * 2] = 0x0a;

            Encoding.ASCII.GetBytes(ByteUtil.ConvertToHexString(f.ExpectedHMac)).AsSpan().CopyTo(dataSpan.Slice(f.Salt.Length * 2 + 1));
            dataSpan[f.Salt.Length * 2 + 1 + f.ExpectedHMac.Length * 2] = 0x0a;

            Encoding.ASCII.GetBytes(ByteUtil.ConvertToHexString(f.EncryptedBytes)).AsSpan().CopyTo(dataSpan.Slice(f.Salt.Length * 2 + f.ExpectedHMac.Length * 2 + 2));
            Span <char> buffer = stackalloc char[width];

            while (!dataSpan.IsEmpty)
            {
                var len = Math.Min(40, dataSpan.Length);
                ByteUtil.ConvertToHexChars(dataSpan.Slice(0, len), buffer);
                output.WriteLine(buffer.Slice(0, len * 2));
                dataSpan = dataSpan.Slice(len);
            }
        }
        public static AnsibleVaultFile Load(TextReader sr)
        {
            var ret          = new AnsibleVaultFile();
            var headerString = sr.ReadLine();
            var header       = headerString.Split(';');

            if (header[0] != AnsibleVaultSignature)
            {
                throw new ArgumentException($"invalid ansible vault header:{headerString}");
            }
            ret.Version   = header[1];
            ret.Algorithm = header[2];
            if (header.Length > 3)
            {
                ret.Label = header[3];
            }
            var bodyBytes = new List <byte>();

            while (true)
            {
                var line = sr.ReadLine();
                if (line == null)
                {
                    break;
                }
                ByteUtil.ConvertToBytes(line, bodyBytes);
            }
            var(salt, expectedhmac, encrypted_bytes) = DecodeBody(bodyBytes.ToArray());
            ret.Salt           = salt;
            ret.ExpectedHMac   = expectedhmac;
            ret.EncryptedBytes = encrypted_bytes;
            return(ret);
        }
Пример #3
0
        public void Encode(byte[] data, byte[] password, byte[] salt, TextWriter output, string label, int width)
        {
            var pbkdf2    = new Rfc2898DeriveBytes(password, salt, 10000, HashAlgorithmName.SHA256);
            var derived   = pbkdf2.GetBytes(32 + 32 + 16);
            var vaultFile = new AnsibleVaultFile();

            vaultFile.Version   = "1.1";
            vaultFile.Algorithm = "AES256";
            vaultFile.Salt      = salt;
            var cipher         = CipherUtilities.GetCipher("AES/CTR/PKCS7Padding");
            var cipherKeyBytes = derived.AsSpan(0, 32).ToArray();
            var hmacKey        = derived.AsSpan(32, 32).ToArray();
            var iv             = derived.AsSpan(64, 16).ToArray();
            var cparam         = new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", cipherKeyBytes), iv);

            cipher.Init(true, cparam);
            var encrypted = cipher.DoFinal(data);
            var hmac256   = new HMACSHA256(hmacKey);

            vaultFile.EncryptedBytes = encrypted;
            vaultFile.ExpectedHMac   = hmac256.ComputeHash(encrypted);
            AnsibleVaultFile.Save(vaultFile, output, label, width);
        }
Пример #4
0
        public void Decode(TextReader vaultFileReader, byte[] password, Stream output)
        {
            var vaultFile      = AnsibleVaultFile.Load(vaultFileReader);
            var cipher         = CipherUtilities.GetCipher("AES/CTR/PKCS7Padding");
            var pbkdf2         = new Rfc2898DeriveBytes(password, vaultFile.Salt, 10000, HashAlgorithmName.SHA256);
            var derived        = pbkdf2.GetBytes(32 + 32 + 16);
            var cipherKeyBytes = derived.AsSpan(0, 32).ToArray();
            var hmacKey        = derived.AsSpan(32, 32).ToArray();
            var iv             = derived.AsSpan(64, 16).ToArray();
            var hmac256        = new HMACSHA256(hmacKey);
            var actualhmac     = hmac256.ComputeHash(vaultFile.EncryptedBytes);

            if (!actualhmac.AsSpan().SequenceEqual(vaultFile.ExpectedHMac))
            {
                throw new InvalidKeyException("HMAC check error: invalid password");
            }
            var cparam = new ParametersWithIV(ParameterUtilities.CreateKeyParameter("AES", cipherKeyBytes), iv);

            cipher.Init(false, cparam);
            var decrypted = cipher.DoFinal(vaultFile.EncryptedBytes);

            output.Write(decrypted.AsSpan());
        }