Storing multiline RSA Key in .NET core User Secrets (JSON)

Viewed 1232

The recommended way to store secrets (like API keys and passwords) during development of an ASP.NET core 3 application is to use user secrets. While this approach works nicely I do have a multiline string which contains an RSA key. The key is copied from a provided .pem file.

Is there any easy way to store the key in secrets.json?

The problem seems to be that json does not support multiline strings. Thus simply copying the key into the file does not work. Workarounds like using an array for the different lines of the key does not play nicely with the Configuration class and binding retrieved secrets to an Options-class.

I have figured out that once I convert the key into a single line string it works. However, the need for a separate tool to convert the key from multiline to single line, seems to me too complex.

By the way, I do need this for building a GitHub-App.

1 Answers

There's nothing stopping you from using a multi-line string with user secrets. You can pass one directly to dotnet user-secrets

For example, some Powershell using a here-string:

$multiVal = @"
Your
Multi-line 
Text
"@
dotnet user-secrets set "YourKeyName" "$multiVal"

Or with embedded new-line character `n:

dotnet user-secrets "YourKeyName" "Your`nMulti-line`nValue"

Or you could read in an entire text-based file:

$fileName = "/path/to/file" 
$multiVal = Get-Content $fileName -Raw
dotnet user-secrets set "YourKeyName" "$multiVal"

A JSON string property also allows "multi-line" text, just not in the way you're thinking. The literal characters \ and n together inside of a string property will be deserialized as a new-line. For example, the following JSON has a string property with a multi-line value:

{
  "YourKeyName": "Your\nMulti-line\nText" 
} 

You can achieve this in a variety of ways, for example doing a manual find-and-replace or with tools like Notepad++. You could also use some Powershell once again:

$inputFile = "/path/to/file" 
$multiVal = Get-Content $inputFile -Raw
$obj = [pscustomobject]@{
   YourKeyName = $multiVal
}
$outputFile = "/path/to/secrets.json"
$obj | ConvertTo-Json -Depth 50 | Out-File -FilePath $outputFile

Edit: you mentioned one of the parameters is not working in the final example. It's possible you are somehow running an older version of powershell (pre 3.0). You can try this instead:

$inputFile = "/path/to/file" 
# no -Raw flag 
$multiVal = (Get-Content $inputFile | Out-String)
# or alternatively 
$multiVal = [System.IO.File]::ReadAllText($inputFile)
$obj = [pscustomobject]@{
   YourKeyName = $multiVal
}
$outputFile = "/path/to/secrets.json"
# use redirection instead of Out-File
($obj | ConvertTo-Json -Depth 50) > $outputFile

Now with respect to RSA keys, according to this answer and its comments while the RSA spec calls for line breaks within the base-64 encoded payload it's possible that implementations may allow non-conformance. This means that depending on how you're using it, you might be able to get away with stripping out the new-lines entirely. You'd have to try it out to know for sure.

Edit: It turns out that dotnet user-secrets has/had a known bug where values cannot have a leading -. It's fixed now but I think only for 5.0+. I found that a leading space works and I would think that the RSA provider shouldn't balk at that. The following should work:

dotnet user-secrets set "PKeyPowerShell" " $multiVal"
Related