Don Sartain
Don Sartain

Reputation: 617

Azure KeyVault Encrypt API Endpoint Not Returning Base64 Encoded String

In PowerShell I'm calling the KeyVault Encrypt API endpoint to encrypt a connection string.

First I create a byte array of the connection string and then I create a base64 string. Then I call the /encrypt endpoint

[byte[]]$bytes = [System.Text.Encoding]::Unicode.GetBytes($targetConnectionString)

echo "Plain Bytes" $bytes

#$base64Array = [Convert]::ToBase64String($bytes)

#$EncryptedTargetConnectionString = Encrypt-ByteArray -accessToken $kvToken -vaultName $kvName -keyID $encryptionKeyId -plainArray $bytes

# converting the byte array to Base64 string
  # Note from [Chris Clayton (AzureCAT)].
  # "When performing the post methods there is a common theme of converting to Base64 strings which just makes sense so we do not introduce any invalid characters etc. and creating a JSON body as you can see here"
  $base64Array = [Convert]::ToBase64String($bytes)
  
  echo "Base 64 Array" $base64Array

  # constructing the url for the vault encrypt operation by specifying the KeyID and Key version. If key version is not specified, then the most recent key version will be used
  $queryUrl = "$encryptionKeyId" + '/encrypt?api-version=2016-10-01'   

  #echo "Query URL: " $queryUrl

  # injecting the access token we obtained in the authorization header
  $headers = @{ 'Authorization' = "Bearer $kvToken"; "Content-Type" = "application/json" }

  echo "KV Token" $kvToken

  # construct the body with our data to be encrypted and specifying RSA as encryption alg.
  $bodyObject = @{ "alg" = "RSA-OAEP"; "value" = $base64Array }
  $bodyJson = ConvertTo-Json -InputObject $bodyObject

  # invoking a POST call to do the magic
  $encryptionResponse = Invoke-RestMethod -Method POST -Ur $queryUrl -Headers $headers -Body $bodyJson

That seems to be working, because when I use Postman to call the Decrypt endpoint I get the response I'd expect.

Then I call an Azure Function which will need to be able to decrypt this connection string.

$EncryptedTargetConnectionString = $encryptionResponse.value

$webRequestBody = @"
{
        "BlobUrl" : "$blobUrl",
        "Environment" : "$env",
        "State" : "$state",
        "EncryptedConnectionStrings" : [ 
            {
            "EncryptedConnectionString": "$EncryptedTargetConnectionString"
            }
        ]
    }
"@

$webRequest = Invoke-WebRequest http://localhost:7071/api/DisableReplication -Headers @{"Accept" = "application/json"} -Method 'POST' -ContentType 'application/json; charset=utf-8' -Body $webRequestBody -UseBasicParsing

What's crazy here, though, is that the RESPONSE from the /encrypt endpoint doesn't seem to be in base64 format.

When I try to run Convert.FromBase64String(encryptedString) in C# against the encrypted string, it doesn't work. It tells me about it not being it base64 format.

C# Code

byte[] inputAsByteArray = Convert.FromBase64String(encryptedString);

            // Encryption algorithm MUST match what was used in the PowerShell task in the Release Pipeline to encrypt the string
            // Ex: $bodyObject = @{ "alg" = "RSA-OAEP"; "value" = $base64Array }
            DecryptResult decryptResult = await cryptographyClient.DecryptAsync(JsonWebKeyEncryptionAlgorithm.RSAOAEP, inputAsByteArray);

            string decryptedString = Encoding.UTF8.GetString(decryptResult.Plaintext);

            return decryptedString;

None of the Key Vault SDK Clients that I've found for .NET Core support decrypting a string directly, and I can't seem to convert the string into a byte array the way I'd expect to be able to.

Any idea what kind of mind games Microsoft is playing here?

Upvotes: 0

Views: 1178

Answers (1)

Matt Small
Matt Small

Reputation: 2275

Key Vault uses Base64Url Encoding which is slightly different than Base64 encoding.

Base64URL encoding is nearly identical to Base64 encoding except for the fact that it substitutes characters that are not safe in a URL ('+','~', etc.) with other characters. In addition, it does not use padding ('=').

Upvotes: 2

Related Questions