Base64 decode fails with “No mapping for the Unicode character exists in the target multi-byte code page.”

ぐ巨炮叔叔 提交于 2021-02-11 06:51:32

问题


I am trying to create the signature string needed for Azure Storage Tables as described here:

https://docs.microsoft.com/en-us/rest/api/storageservices/authorize-with-shared-key#encoding-the-signature

The Access key is "p1qPD2lBiMlDtl/Vb/T/Xt5ysd/ZXNg5AGrwJvtrUbyqiAQxGabWkR9NmKWb8Jhd6ZIyBd9HA3kCRHr6eveKaA=="

The failing code is:

property AccessKey: string read FAccessKey write SetAccessKey;

function TAzureStorageAPI.GetAuthHeader(StringToSign: UTF8String): UTF8String;
var
  AccessKey64: string;
begin
  AccessKey64 := URLEncoding.Base64.Decode(AccessKey);
  Result := URLEncoding.Base64.Encode(CalculateHMACSHA256(StringtoSign,AccessKey64));
end;

What can I do to get this working?

I have checked that AccessKey decodes on https://www.base64decode.org/ and it converts to strange data, but it is what I am supposed to do.... :-/


回答1:


It looks like CalculateHMACSHA256() comes from blindly copying it and just fiddling everything to make the compiler happy. But there are still logical flaws all over. Without testing I'd write it this way:

function GetAuthHeader
( StringToSign: UTF8String  // Expecting an UTF-8 encoded text
; AzureAccountKey: String  // Base64 is ASCII, so text encoding is almost irrelevant
): String;  // Result is ASCII, too, not UTF-8
var
  HMAC: TIdHMACSHA256;
begin
  HMAC:= TIdHMACSHA256.Create;
  try
    // Your key must be treated as pure binary - don't confuse it with
    // a human-readable text-like password. This corresponds to the part
    // "Base64.decode(<your_azure_storage_account_shared_key>)"
    HMAC.Key:= URLEncoding.Base64.DecodeStringToBytes( AzureAccessKey );

    result:= URLEncoding.Base64.EncodeBytesToString  // The part "Signature=Base64(...)"
    ( HMAC.HashValue  // The part "HMAC-SHA256(...,...)"
      ( IndyTextEncoding_UTF8.GetBytes( StringToSign )  // The part "UTF8(StringToSign)"
      )
    );
  finally
    HMAC.Free;
  end;
end;

No guarantee as I have no chance to compile it myself.

Using ToHex() anywhere makes no sense if you encode it all in Base64 anyway. And stuffing everything into UTF8String makes no sense either then. Hashing always implies working with bytes, not text - never mix up binary with String.



来源:https://stackoverflow.com/questions/66080788/base64-decode-fails-with-no-mapping-for-the-unicode-character-exists-in-the-tar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!