using Health.Infrastructure.Services; namespace Health.Tests; /// /// BCE v1 签名算法测试 /// Golden value 由 Python 标准库 hmac + hashlib 按 baidubce-sdk 算法手算, /// 并与 baidubce-sdk 0.9.72 的实际 debug 输出对比验证一致 /// public class BceSignerTests { private const string Ak = "test-ak"; private const string Sk = "test-sk"; private const string Host = "smsv3.bj.baidubce.com"; private const string Method = "POST"; private const string ApiPath = "/api/v3/sendSms"; private const string ContentType = "application/json;charset=utf-8"; private const int ContentLength = 199; private static readonly DateTime Ts1 = new(2026, 1, 1, 0, 0, 0, DateTimeKind.Utc); private static readonly DateTime Ts2 = new(2026, 7, 23, 8, 0, 0, DateTimeKind.Utc); // Golden 1: 固定输入 private const string ExpectedSig1 = "7592321b147186724a0194344aa274b4875fbc3442b4a5a07db4fd00cf44e580"; private const string ExpectedAuth1 = "bce-auth-v1/test-ak/2026-01-01T00:00:00Z/1800/content-length;content-type;host;x-bce-date/" + ExpectedSig1; // Golden 2: 不同 timestamp private const string ExpectedSig2 = "5c058909c04e8a6964fc22f9ae00cd5aae9c9182cb21fca7a76eb834eaa47c0b"; // Golden 3: 不同 SK private const string ExpectedSig3 = "b944339bad2635d0eb41344427c1328f9785335a64baaabced658fa487fb228a"; // Golden 4: 不同 content_length private const string ExpectedSig4 = "7b2f8bfdda2255b2331992a4adb9fb7365aa83c62453b61380cc7be350e6105f"; [Fact] public void BuildAuthorization_FixedInput_MatchesGoldenValue() { var auth = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts1, ContentLength, ContentType); Assert.Equal(ExpectedAuth1, auth); } [Fact] public void BuildAuthorization_DifferentTimestamp_ProducesDifferentSignature() { var auth1 = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts1, ContentLength, ContentType); var auth2 = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts2, ContentLength, ContentType); Assert.NotEqual(auth1, auth2); Assert.EndsWith(ExpectedSig2, auth2); } [Fact] public void BuildAuthorization_DifferentSecretKey_ProducesDifferentSignature() { var auth1 = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts1, ContentLength, ContentType); var auth3 = BceSigner.BuildAuthorization(Ak, "test-sk-2", Method, ApiPath, Host, Ts1, ContentLength, ContentType); Assert.NotEqual(auth1, auth3); Assert.EndsWith(ExpectedSig3, auth3); } [Fact] public void BuildAuthorization_DifferentContentLength_ProducesDifferentSignature() { var auth1 = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts1, ContentLength, ContentType); var auth4 = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts1, 100, ContentType); Assert.NotEqual(auth1, auth4); Assert.EndsWith(ExpectedSig4, auth4); } [Fact] public void BuildAuthorization_Signature_Is64CharLowercaseHex() { var auth = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts1, ContentLength, ContentType); var sig = auth.Split('/')[^1]; Assert.Equal(64, sig.Length); Assert.Matches("^[0-9a-f]{64}$", sig); } [Fact] public void BuildAuthorization_Format_HasCorrectStructure() { var auth = BceSigner.BuildAuthorization(Ak, Sk, Method, ApiPath, Host, Ts1, ContentLength, ContentType); var parts = auth.Split('/'); Assert.Equal(6, parts.Length); Assert.Equal("bce-auth-v1", parts[0]); Assert.Equal(Ak, parts[1]); Assert.Equal("2026-01-01T00:00:00Z", parts[2]); Assert.Equal("1800", parts[3]); Assert.Equal("content-length;content-type;host;x-bce-date", parts[4]); Assert.Equal(ExpectedSig1, parts[5]); } [Fact] public void BuildAuthorization_RealCredentials_MatchesSdkDebugOutput() { // 用百度 SDK 0.9.72 实际 debug 日志里的真实输入,验证 C# 输出和 SDK 完全一致 var auth = BceSigner.BuildAuthorization( "ALTAKnJn8wtdLtBPgl7bD1x3N3", "c5ca05a967d04a69bbc0e12f08062dc8", "POST", "/api/v3/sendSms", "smsv3.bj.baidubce.com", new DateTime(2026, 7, 23, 9, 3, 42, DateTimeKind.Utc), 199, "application/json;charset=utf-8"); Assert.Equal( "bce-auth-v1/ALTAKnJn8wtdLtBPgl7bD1x3N3/2026-07-23T09:03:42Z/1800/content-length;content-type;host;x-bce-date/0fd388266f63e9036de09981d7312ce3b7e279c8789823cb80b6c1800005fe13", auth); } }