0

I'm using MassTransit 3.4 and using the EncryptedSerializer. Messages are encrypted and decrypted correctly by my application, but now I'd like to be able to decode the base64-encoded messages that appear in the RabbitMQ "_error" queues. I'd like to write some program to allow users to discover the contents of the base64 encoded and encrypted messages and I'm struggling to get the messages decoded properly.

Here's what I've done so far. Copy/paste the "Payload" bits from the RabbitMQ management UI into my text editor and try to run code to Convert.FromBase64String(text), and then pass the byte array to a decryption function like the one found here. This ALMOST works - I see most of the characters of the Payload in plain text, but many characters are messed up. I can't share the entire message payload, but here is a screenshot from LinqPad showing some messed up characters (with red added by me for protection). See the black weird characters? And the leading "g"? What's the deal?

enter image description here

Here's a code snippet I'm using to get that decrypted text (I've also tried different encodings to no avail):

using (Stream msDecrypt = new MemoryStream(cipherText, false))
using (Stream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (StreamReader srDecrypt = new StreamReader(csDecrypt, System.Text.Encoding.UTF8, false, 1024, true))
{
    plaintext = srDecrypt.ReadToEnd();
}

If I try to use MassTransit-style decryption using a NewtonSoft BsonReader, I get "CryptographicException: Padding is invalid and cannot be removed" when it tries to call Dispose on the CryptoStream object:

using (Stream msDecrypt = new MemoryStream(cipherText, false))
using (Stream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (var jsonReader = new BsonReader(csDecrypt))
{
    envelope = deserializer.Deserialize<MessageEnvelope>(jsonReader);
}

What am I doing wrong here?

Update: If I paste into Notepad++, it shows a lot of control characters. The string starts with gmessageId (EOT and STX are control characters). There are a lot of STX characters - I think these are supposed to be either quotes or colons or something...how can I convert these to the correct symbols?

Community
  • 1
  • 1
Andy
  • 2,709
  • 5
  • 37
  • 64
  • interesting, are you sure there _should_ be no control character in the message? Still it looks like an encoding issue – kennyzx May 18 '17 at 14:41

1 Answers1

0

The second approach is correct; you want to deserialize using BsonReader into a MassTransit MessageEnvelope instance. I was getting the "CryptographicException: Padding is invalid and cannot be removed" because I wasn't passing any DeserializerSettings... In the MassTransit source, they initialize the deserializer like the following:

JsonSerializerSettings DeserializerSettings = new JsonSerializerSettings
{
    NullValueHandling = NullValueHandling.Ignore,
    DefaultValueHandling = DefaultValueHandling.Ignore,
    MissingMemberHandling = MissingMemberHandling.Ignore,
    ObjectCreationHandling = ObjectCreationHandling.Auto,
    ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor,
    ContractResolver = new JsonContractResolver(),
    Converters = new List<JsonConverter>(new JsonConverter[]
    {
        new ListJsonConverter(),
        new InterfaceProxyConverter(GreenPipes.Internals.Extensions.TypeCache.ImplementationBuilder),
        new IsoDateTimeConverter {DateTimeStyles = System.Globalization.DateTimeStyles.RoundtripKind},
    })
};

var _deserializer = JsonSerializer.Create(DeserializerSettings);

Previously, I was just doing:

var _deserializer = new JsonSerializer();

So after the deserializer is initialized properly, the deserialization to the MessageEnvelope works, and you can serialize it back to a Json string, formatted nicely like so:

MassTransit.Serialization.MessageEnvelope envelope;

using (MemoryStream msDecrypt = new MemoryStream(cipherText))
using (Stream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
using (BsonReader jsonReader = new Newtonsoft.Json.Bson.BsonReader(csDecrypt))
{
    envelope = _deserializer.Deserialize<MessageEnvelope>(jsonReader);
}

string output = JsonConvert.SerializeObject(envelope, Newtonsoft.Json.Formatting.Indented);
return output;

This assumes MassTransit 3.4, Newtonsoft.Json 9.0.1 (aka Json.NET) and GreenPipes (1.0.6). In the code immediately above, I've added the full namespaces for the classes in those libraries.

Andy
  • 2,709
  • 5
  • 37
  • 64