I'm working with mimekit to encrypt and decrypt mime messages and I'm encountering this error everytime I try to decrypt a message:
Unexpected object reading content. BouncyCastle.Crypto at Org.BouncyCastle.Cms.CmsContentInfoParser..ctor(Stream data) in //crypto/src/cms/CMSContentInfoParser.cs:line 35
at Org.BouncyCastle.Cms.CmsEnvelopedDataParser..ctor(Stream envelopedData) in //crypto/src/cms/CMSEnvelopedDataParser.cs:line 65
at MimeKit.Cryptography.BouncyCastleSecureMimeContext.d__50.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at PasarelaLibrary.Bases.GraphService.BaseGraphPasarela.d__11.MoveNext() in C:\Dev\Euroval\PasarelaAceuro\PasarelaLibrary\Bases\GraphService\BaseGraphPasarela.cs:line 302
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at PasarelaLibrary.Bases.GraphService.BaseGraphPasarela.d__9.MoveNext() in C:\Dev\Euroval\PasarelaAceuro\PasarelaLibrary\Bases\GraphService\BaseGraphPasarela.cs:line 237
Inner exception
Unable to cast object of type 'Org.BouncyCastle.Asn1.DerApplicationSpecific' to type 'Org.BouncyCastle.Asn1.Asn1SequenceParser'. at Org.BouncyCastle.Cms.CmsContentInfoParser..ctor(Stream data) in /_/crypto/src/cms/CMSContentInfoParser.cs:line 27
the problem is I'm just trying to encrypt and decrypt a message to test the library and the flow of the application and I'm getting this error. Above you can find the code I'm using. I'm using a x509Certificate with a password that I'm importing in the TemporarySecureMimeContext.
using var context = new TemporarySecureMimeContext();
await context.ImportAsync(certificate);
var encryptedMessage = await GetEncryptedMessage(context, stream, fileroute, certificate, mailFrom, mailTo);
using var testencrypted = new MemoryStream();
await encryptedMessage.WriteToAsync(testencrypted);
testencrypted.Position = 0;
var dec = await context.DecryptAsync(testencrypted); //here it explodes :(
public static async Task<MimeMessage> GetEncryptedMessage(TemporarySecureMimeContext context, Stream stream, string subject, X509Certificate certificate, string mailFrom, string mailTo)
{
stream.Position = 0;
SecureMailboxAddress mailFromEncrypted = new SecureMailboxAddress("name", mailFrom, certificate.GetFingerprint());
SecureMailboxAddress mailToEncrypted = new SecureMailboxAddress("name", mailTo, certificate.GetFingerprint());
BodyBuilder bodyBuilder = new BodyBuilder();
using StreamReader reader = new StreamReader(stream);
bodyBuilder.TextBody = await reader.ReadToEndAsync();
MimeMessage message = new MimeMessage(new List<InternetAddress> { mailFromEncrypted }, new List<InternetAddress> { mailToEncrypted }, subject, bodyBuilder.ToMessageBody());
message.Date = DateTime.Now;
message.MessageId = MimeUtils.GenerateMessageId();
await message.EncryptAsync(context);
return message;
}
I already read other posts here and in other forums but nothing worked for this case scenario. Could someone help me with this?
You're using it wrong :-)
You are trying to decrypt a MIME message stream. You can't do that.
The SecureMimeContext.Decrypt() and DecryptAsync() methods expect the encrypted content of the MIME message.
If your goal is to load the MimeMessage and decrypt it, you would change your code to this:
using var context = new TemporarySecureMimeContext();
await context.ImportAsync(certificate);
// get an encrypted message
var encryptedMessage = await GetEncryptedMessage(context, stream, fileroute, certificate, mailFrom, mailTo);
// write the encrypted message to a stream
using var testencrypted = new MemoryStream();
await encryptedMessage.WriteToAsync(testencrypted);
testencrypted.Position = 0;
// load the message from the stream
var loadedMessage = await MimeMessage.LoadAsync(testencrypted);
// get the encrypted body
var encryptedBody = (ApplicationPkcs7Mime) loadedMessage.Body;
// decrypt it
var decryptedBody = await encryptedBody.DecryptAsync(context);
// restore the message to the pre-encrypted state
loadedMessage.Body = decryptedBody;
Related
I'm trying to get a BrokeredMessage from AzureServiceBus in a .NET client and choose how to deal with the message based on the type of message coming in, but ContentType and other message properties are not set.
My test message sending looks like this:
var client =
QueueClient.CreateFromConnectionString(connectionString, queueName);
var message = new BrokeredMessage("test");
client.Send(message);
My code to receive is using GetBody so that I can inspect the serialized data and decide how to deal with it:
var stream = message.GetBody<Stream>();
string s = null;
using (StreamReader sr = new StreamReader(stream))
{
s = sr.ReadToEnd();
}
The problem is that "s" above ends up with what looks like it should be XML created from a DataContractSerializer, but it is strangely encoded. I've tried many encodings on the receiving side and none seem to get me valid xml. Example results:
#string3http://schemas.microsoft.com/2003/10/Serialization/�test
I see the serialization namespace and what looks like it should start with <string, but as you can see I'm getting control characters. Does any one know how I can try to get the serialized data here as valid XML so I can dynamically handle it?
TIA for any help.
To be really clear I want to test the body so I can do something like:
if (BodyIsString(s)) { do something }
if (BodyIsPerson(s)) { do something else }
If I could getbody twice this would be really easy.
As Sean Feldman mentioned when send message is string type we could use
var body = message.GetBody<string>();
to get message body, after I decompile the WindowsAzure.ServiceBus.dll then get the code:
public T GetBody<T>()
{
if (typeof (T) == typeof (Stream))
{
this.SetGetBodyCalled();
return (T) this.BodyStream;
}
if (!this.bodyObjectDecoded || this.bodyObject == null)
return this.GetBody<T>((XmlObjectSerializer) new DataContractBinarySerializer(typeof (T)));
this.SetGetBodyCalled();
return (T) this.bodyObject;
}
I find that if the send message
is not Stream type it will be DataContractBinarySerializer. so we also could get the message body with following way
var stream = message.GetBody<Stream>();
var messageBody = new DataContractSerializer(typeof(string)).ReadObject(XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max));
From the decompiled code we could know that if we send the stream message, we could get the message body with the way you mentioned.
Send stream message code :
var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
var byteArray = Encoding.UTF8.GetBytes("test stream");
MemoryStream stream = new MemoryStream(byteArray);
client.Send(new BrokeredMessage(stream));
then receive message as you mentioned it should work:
var stream = message.GetBody<Stream>();
string s = null;
using (StreamReader sr = new StreamReader(stream))
{
s = sr.ReadToEnd();
}
Edit :According to update question:
If I could getbody twice this would be really easy.
we could clone the BrokerMessage
var newMessage = receiveMessage.Clone();
Edit2:
We also can get the message Properties to know the body type if we set it during sending. Take Label for example:
var message = new BrokeredMessage(object);
message.Label = "Type of message body";
client.Send(message);
While we receive the message we could get the message Label value then select the corresponding way to get the body.
You passed your payload as a string
var message = new BrokeredMessage("test");
therefore it was serialized as a string. Upon receive you should get the body as a string as well in the following manner:
var body = message.GetBody<string>();
You would use Stream if you'd actually construct your brokered message using a stream.
I want to show message to end user when blob is taking so much time for uploading and downloading. I found useful blog here.
Simply linear retry policy
public static RetryPolicy LinearRetry(int retryCount, TimeSpan intervalBetweenRetries)
{
return () =>
{
return (int currentRetryCount, Exception lastException, out TimeSpan retryInterval) =>
{
// Do custom work here
// Set backoff
retryInterval = intervalBetweenRetries;
// Decide if we should retry, return bool
return currentRetryCount < retryCount;
};
};
}
But here I didn't get how to send response to user back while retrying. Is this right way or anything else. Please suggest
OperationContext class in Storage Client Library has an event called Retrying that you can consume and send message back to the client.
For example, I created a simple console application which tries to create a blob container. When I ran this application, I deliberately turned off Internet access so that I can simulate a situation where operation would be retried. Then in this event consumer, I simply write something back to console. You could simply raise another event from there that would send a message back to your client.
var requestOptions = new BlobRequestOptions()
{
RetryPolicy = new ExponentialRetry(),
};
var operationContext = new OperationContext();
operationContext.Retrying += (sender, args) =>
{
Console.WriteLine("I'm retrying ....");
};
var cloudStorageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
var blobClient = cloudStorageAccount.CreateCloudBlobClient();
var container = blobClient.GetContainerReference("test");
container.CreateIfNotExists(requestOptions, operationContext);
So I tried running this Push notification sample for Xamarin.Android http://azure.microsoft.com/en-us/documentation/articles/partner-xamarin-mobile-services-android-get-started-push/ and after following instructions from the docs - I got it up and running. The insertion of items work absolutely fine however push notification refuses to work.
This is the error I get on Azure for push: Error: 400 - The supplied notification payload is invalid.
Anyone else tried running this sample on their device and tried push notifications? The error isn't doing much to help my case.
The sample is using PushSharp.
I'd appreciate any help. Thanks a bunch!
This is how I send push notification to Google Cloud Messaging from the back-end server.
public async Task<bool> SendNotification(int id, int index, string from, string text, string tag)
{
try
{
var payload = new
{
data = new
{
message = new
{
// this part can be anything you want
id,
index,
from,
text,
when = DateTime.UtcNow.ToString("s") + "Z"
}
}
};
var json = JsonConvert.SerializeObject(payload);
await _hubClient.SendGcmNativeNotificationAsync(json, tag);
return true;
}
catch (ArgumentException ex)
{
// This is expected when an APNS registration doesn't exist.
return false;
}
Then in your app Intent Service, you can parse the JSON "message":
protected override void OnMessage(Context context, Intent intent)
{
var message = intent.Extras.GetString("message");
// message is JSON payload
// { "id":"someid", "index":"1", "text":"some text","from"... }
var json = JObject.Parse(message);
var id = json["id"].ToString();
var index = json["index"].ToString();
var text = json["text"].ToString();
var from = json["from"].ToString();
var when = DateTime.Parse(json["when"].ToString());
// do whatever you want with your values here
}
The web socket is written in javascript by my colleague. I managed to connect. First of all I have to log in on the application using a test account. I have to send the email and password through a json. I have installed the Json.Net packet using NuGet.
Some code that I found on my reaserch is this, but I do not understand how to send my data using that segment.
var buffer = new byte[1024];
var segment = new ArraySegment<byte>(buffer);
webSocket.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None);
Of course, I can use an object
User user=new User();
user.Email="bla#bla.com";
user.Password="pass";
string json = JsonConvert.SerializeObject(user);
But it will not be of any use because the method SendAsync accepts only byte type on segment.
All I want is to send that data, and if log in succeeds, I should receive other data (in Json format) about the user.
As a side note, I am quite new to web sockets, I used http protocols from ASP.NET WEB API 2.
I have no idea about Windows Phone 8, but by the code you pasted it seems similar to the regular .NET ClientWebSocket, so here you have some examples:
public static Task SendString(ClientWebSocket ws, String data, CancellationToken cancellation)
{
var encoded = Encoding.UTF8.GetBytes(data);
var buffer = new ArraySegment<Byte>(encoded, 0, encoded.Length);
return ws.SendAsync(buffer, WebSocketMessageType.Text, true, cancellation);
}
public static async Task<String> ReadString(ClientWebSocket ws)
{
ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[8192]);
WebSocketReceiveResult result = null;
using (var ms = new MemoryStream())
{
do
{
result = await ws.ReceiveAsync(buffer, CancellationToken.None);
ms.Write(buffer.Array, buffer.Offset, result.Count);
}
while (!result.EndOfMessage);
ms.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms, Encoding.UTF8))
return reader.ReadToEnd();
}
}
If something does not compile or exists in WP8, just find an equivalent.
#vtortola is a working example in case your data comes in multiple segmented messages, but if all data comes in a single message you don't need all those streams to read the message, you just need to do this:
public static async Task<String> ReadString(ClientWebSocket socket)
{
var reciveBuffer = new byte[32000];
var result = await socket.ReceiveAsync(new ArraySegment<byte>(reciveBuffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
}
return Encoding.ASCII.GetString(reciveBuffer , 0, result.Count);
}
If your message is splited in multiple segments or you don't know how your message is comming then you have to do like #vtortola
Also if you want to keep receiving messages you can do a while and call ReadString inside, like this:
while (socket.State == WebSocketState.Open)
{
var msg = ReadString(socket)
//do something with your message...
}
Hi I am downloading an image from the following code
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, imageUri);
HttpResponseMessage response = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
var fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite);
DataWriter writer = new DataWriter(fs.GetOutputStreamAt(0));
writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());
await writer.StoreAsync();
writer.DetachStream();
await fs.FlushAsync();
fs.Dispose();
But when I try it to open immediately after running downloading code.. with the help of the following code and trying to set as a source to image control
var imageFile = await ApplicationData.Current.LocalFolder.GetFileAsync(imageName);
IRandomAccessStream stream = await imageFile.OpenAsync(FileAccessMode.Read);
imageControl.SetSource(stream);
It throws the following exception
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
and Inner Exception is:
null
Please let me know that at which point I am doing mistake.
Thanks in Advance
Got answer here.. just had to add one more line.. now the downloading code is
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, imageUri);
HttpResponseMessage response = await http.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
var imageFile = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (var fs = await imageFile.OpenAsync(FileAccessMode.ReadWrite))
{
var outStream = fs.GetOutputStreamAt(0);
DataWriter writer = new DataWriter(outStream);
writer.WriteBytes(await response.Content.ReadAsByteArrayAsync());
await writer.StoreAsync();
writer.DetachStream();
await fs.FlushAsync();
outStream.Dispose();
fs.Dispose();
}