首页 > 解决方案 > Base64 解码失败,并显示“目标多字节代码页中不存在 Unicode 字符的映射”。

问题描述

我正在尝试创建 Azure 存储表所需的签名字符串,如下所述:

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

访问密钥是"p1qPD2lBiMlDtl/Vb/T/Xt5ysd/ZXNg5AGrwJvtrUbyqiAQxGabWkR9NmKWb8Jhd6ZIyBd9HA3kCRHr6eveKaA=="

失败的代码是:

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;

我该怎么做才能让它工作?

我已经检查了https://www.base64decode.org/AccessKey上的解码,它转换为奇怪的数据,但这是我应该做的...... :-/

标签: delphibase64azure-table-storage

解决方案


它看起来像是CalculateHMACSHA256()来自盲目地复制它并只是摆弄一切以使编译器高兴。但仍然存在逻辑缺陷。没有测试我会这样写:

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;

不能保证,因为我没有机会自己编译它。

如果你无论如何都用Base64对它进行编码,那么在任何地方使用ToHex()都是没有意义的。然后把所有东西都塞进去也没有意义。散列总是意味着使用字节,而不是文本 - 永远不要将二进制与.UTF8StringString


推荐阅读