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);
}
}