storage icon indicating copy to clipboard operation
storage copied to clipboard

Azure Blob connection string containing key with + chars fails

Open Dehalion opened this issue 5 years ago • 7 comments

If the key in a connection string for an Azure Blob Storage account contains a + character, the method AzureBlobStorageWithSharedKey fails with the message "Invalid length for a Base-64 char array or string."

I'm using Storage.Net 9.2.6

My rough guess is that the + characters are replaced with spaces somewhere (maybe there is some URL decoding).

~~Workaround (until fixed): Regenerate the key until you get one without a +.~~ Workaround/Fix: always URL-encode your storage key.

Stack Trace:

System.FormatException: Invalid length for a Base-64 char array or string.
   at System.Convert.FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
   at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
   at System.Convert.FromBase64String(String s)
   at Storage.Net.Factory.AzureBlobStorageWithSharedKey(IBlobStorageFactory factory, String accountName, String key, Uri serviceUri)
   at Storage.Net.Microsoft.Azure.Storage.Blobs.Module.CreateBlobStorage(StorageConnectionString connectionString)
   at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at Storage.Net.ConnectionString.ConnectionStringFactory.Create[TInstance](String connectionString, Func`3 createAction)

Dehalion avatar May 26 '20 17:05 Dehalion

As I expected the + is replaced by a space in StorageConnectionString.Parse() with the line

_parts[key] = value.UrlDecode();

which leaves me uncertain if this is a bug or a feature.

On one hand, it is formatted like a URI, starting with the storage type as "protocol". So one could argue UrlDecodeing the arguments is a valid thing to do.

On the other hand it is really unexpected for me as a user that I cannot just copy&paste the storage key into the connection string but have to check for characters which need URL encoding, even if its just a connection string, not an actual URL.

Dehalion avatar May 27 '20 11:05 Dehalion

I'm facing the same issue. The workaround is like playing roulette...

banarualexandru avatar Jun 21 '20 06:06 banarualexandru

This is unfortunate, yes plus sign in URL has a special meaning - space. We think of all the parameters as URL-encoded, because in some cases like drive path there are special characters that cause issues with a parser. The safest way to pass parameters is to url-encode them first though.

aloneguid avatar Jun 22 '20 08:06 aloneguid

Yes, this is a bit unfortunate. It is inconsistent with how DB connection strings work, for example. But I understand, why it is necessary to url-encode the parameters.

It would be great though if this is mentioned in the documentation. I would add this as a hint to every occurrence of a connection string in the documentation, but I know this seems a bit excessive.

Dehalion avatar Jun 22 '20 10:06 Dehalion

Workaround (until fixed): Regenerate the key until you get one without a +.

The workaround is like playing roulette...

Maybe instead of "key roulette" you could (strictly a workaround) use %2B instead of +

628426 avatar Jun 22 '20 10:06 628426

Yeah, should have updated the workaround after finding out the reason it doesn't work with a +. Have done it now.

Dehalion avatar Jun 22 '20 19:06 Dehalion

@aloneguid should the connection string be encoded within the StorageNet library, or encoding it before initializing the storage would be the right way to do it?

yannickrondeau avatar Feb 10 '22 05:02 yannickrondeau