0

I'm attempting to use the KMS GenerateDataKeyPairAsync in order to get the public and private key out for testing (Once it works I will switch to the GenerateDataKeyPairWithoutPlaintextAsync).

The GenerateDataKeyPairResponse has three memory streams for the Public Key, Private Key Ciphertext and Private Key plaintext.

I can't seem to convert any of these memory streams to string so I can actually then use the keys.

The SDK docs (https://docs.aws.amazon.com/sdkfornet/v3/apidocs/Index.html) say it will be Base64 encoded if using the HTTP api, does the SDK use the HTTP api? I can't seem to tell.

I have tried using StreamReader.ReadToEnd() and using Encoding.ENCODING.FromString(stream.ToArray()) using all the encodings but I can't seem to get a reasonable value out.

Am I missing something important here?

Thanks

Adding the code:

# USING: AWSSDK.KeyManagementService VERSION: 3.5.0-beta


using System;
using System.IO;
using System.Threading.Tasks;
using Amazon;
using Amazon.KeyManagementService;
using Amazon.KeyManagementService.Model;
using Amazon.Runtime;

namespace ConsoleApp1
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var credentials = new BasicAWSCredentials("AccessKey", "SecretKey");

            var kmsClient = new AmazonKeyManagementServiceClient(credentials, RegionEndpoint.EUCentral1);

            const string keyId = "CMKKey";

            var dataKeyRequest = new GenerateDataKeyPairRequest
            {
                KeyId = keyId, 
                KeyPairSpec = DataKeyPairSpec.RSA_2048
            };

            var dataKeyPairResponse = await kmsClient.GenerateDataKeyPairAsync(dataKeyRequest);

            var publicKeyStream = dataKeyPairResponse.PublicKey;

            var privateKeyStream = dataKeyPairResponse.PrivateKeyPlaintext;

            var publicReader = new StreamReader( publicKeyStream );
            var publicKey = publicReader.ReadToEnd();

            var privateReader = new StreamReader( privateKeyStream );
            var privateKey = privateReader.ReadToEnd();

            Console.WriteLine(publicKey);
            Console.WriteLine(privateKey);
        }
    }
}
Martin Beeby
  • 4,523
  • 1
  • 26
  • 20
AKTheKnight
  • 113
  • 1
  • 7
  • Hi Alex can you share you current code? – Martin Beeby Mar 03 '20 at 14:13
  • Hi @MartinBeeby [Here](https://gist.github.com/AKTheKnight/d7f4c627af38f26350918a5ce2f8c9b3) is the code I have been testing with. I would expect publicKey and privateKey to now be legible strings, but they don't seem to be of any encoding I could work out. Thanks – AKTheKnight Mar 03 '20 at 14:47
  • Yeah the strings returned do look odd. They are not base64 encoded in the SDK according to the docs: "Gets and sets the property PrivateKeyPlaintext. The plaintext copy of the private key. When you use the HTTP API or the AWS CLI, the value is Base64-encoded. Otherwise, it is not Base64-encoded." I will investigate more tomorrow. – Martin Beeby Mar 03 '20 at 17:52

1 Answers1

0

I think I have found a bug in the AWS library. Pretty deep in the call stack there is a DecodefromBase64 call but I don't think the string it is decoding is actually in Base64. Therefore you end up with a string that is actually a decoded normal string. If you encode the string with base64 it returns the correct string.

The following code will fix your issue... However, I will contact the team that works on this library and try to get it fixed. If it's fixed at the library level this code will stop working. So please use with caution/wait for an official fix.

var dataKeyPairResponse = await kmsClient.GenerateDataKeyPairAsync(dataKeyRequest);
var privateKeyBytes = dataKeyPairResponse.PrivateKeyPlaintext.ToArray(); 
var privateKey = Convert.ToBase64String(privateKeyBytes);

var publicKeyBytes = dataKeyPairResponse.PublicKey.ToArray();
var publicKey = Convert.ToBase64String(publicKeyBytes);

Console.Write(privateKey);
Console.Write(publicKey);
Martin Beeby
  • 4,523
  • 1
  • 26
  • 20
  • Hi Martin, Apologies for how long this has taken, I've had to quickly move and only just managed to get settle back to coding. Using your code I get the correct private key, but the public key doesn't seem to be the correct public key for that private key? I've used the gist below to explain more, but using "ssh-keygen -f ~/.ssh/id_rsa -y > ~/.ssh/id_rsa.pub" on the private key gets me a different public key to the one the api returned. https://gist.github.com/AKTheKnight/d851306cb2102f933d91e19689afc20a – AKTheKnight Mar 30 '20 at 13:57