Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.

If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!

Credentials_CreateOrUpdateCredential



  • Hi,
    I would like to use Native API for Otter to add new credentials but I have a problem with creating encrypted password using the key from the configuration file.
    Do you have any guide on how to generate such password?


  • inedo-engineer

    Unfortunately we don't yet have an API for the credentials, but it's something we'd like to make. In the mean time, the Native API will work. If you look in the database, you'll be able to see how credentials are structured, and how things like Password are stored.

    The secret fields are encrypted using DPAPI, with the Encryption key stored in the configuration file.

    Here's the specific code we use to encrypt/decrypt. Please share what you come up with, would definitely help out in the mean time :)

        private static byte[] Decrypt(byte[] data)
        {
            if (protectedAesKey == null || protectedAesKey.Length == 0)
                throw new InvalidOperationException("Cannot decrypt persistent property; decryption key not configured.");
    
            byte[] key;
            try
            {
                key = ProtectedData.Unprotect(protectedAesKey, null, DataProtectionScope.LocalMachine);
            }
            catch (CryptographicException ex)
            {
                throw new InvalidOperationException(
                    $"An error occurred during decryption (\"{ex.Message}\"). This usually means that the encryption key has changed between"
                    + " encrypting and decrypting the data, which might happen if you accidentally overwrite a configuration setting, perhaps during an upgrade or reinstall."
                    + " Check your configured encryption key, and restart the service and web application(s) as needed.");
            }
            try
            {
                var nonce = new byte[16];
                Array.Copy(data, 0, nonce, 0, 8);
                Array.Copy(data, data.Length - 8, nonce, 8, 8);
                using (var buffer = new MemoryStream(data.Length - 16))
                {
                    buffer.Write(data, 8, data.Length - 16);
                    buffer.Position = 0;
    
                    using (var aes = new AesManaged { Key = key, IV = nonce, Padding = PaddingMode.PKCS7 })
                    using (var cryptoStream = new CryptoStream(buffer, aes.CreateDecryptor(), CryptoStreamMode.Read))
                    {
                        var output = new byte[SlimBinaryFormatter.ReadLength(cryptoStream)];
                        cryptoStream.Read(output, 0, output.Length);
                        return output;
                    }
                }
            }
            finally
            {
                if (key != null)
                    Array.Clear(key, 0, key.Length);
            }
        }
        private static byte[] Encrypt(byte[] data)
        {
            if (protectedAesKey == null || protectedAesKey.Length == 0)
                return null;
    
            var key = ProtectedData.Unprotect(protectedAesKey, null, DataProtectionScope.LocalMachine);
            try
            {
                using (var aes = new AesManaged { Key = key, Padding = PaddingMode.PKCS7 })
                {
                    aes.GenerateIV();
    
                    using (var outputBuffer = new MemoryStream())
                    {
                        outputBuffer.Write(aes.IV, 0, 8);
    
                        using (var cryptoStream = new CryptoStream(new UncloseableStream(outputBuffer), aes.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            SlimBinaryFormatter.WriteLength(cryptoStream, data.Length);
                            cryptoStream.Write(data, 0, data.Length);
                        }
    
                        outputBuffer.Write(aes.IV, 8, 8);
                        return outputBuffer.ToArray();
                    }
                }
            }
            finally
            {
                if (key != null)
                    Array.Clear(key, 0, key.Length);
            }
        }

Log in to reply
 

Inedo Website HomeSupport HomeCode of ConductForums GuideDocumentation