一种基于时间戳和密钥的签名算法
一、算法概述
本算法由何伟贵在2007年5月设计,通过整合 UTC 时间戳与特定密钥来生成签名,借助过期时间确保签名的时效性,并引入允许误差机制以应对时间偏差情况,从而有效地验证请求的合法性与及时性,保障系统的安全稳定运行。文中以 MD5 算法为例进行说明,但在实际应用中,建议采用更安全的哈希算法,如 SHA - 256 等,以增强系统的安全性和抗攻击能力,确保敏感信息与系统操作的安全。 该算法结果也可以缓存,将误差时间做适当设置,每过一个误差时间执行一次计算,不需要每次请求都计算,减少计算频率,从而减少性能开销。
二、服务端
(一)配置参数
1. 过期时间(ExpirationTime):明确签名的有效时长,单位为秒,本示例中设定为 600 秒,超过此时间的签名将被判定为无效。 2. 密钥(SecretKey):选取特定字符串,本示例定为“ABCDEFGabcdefg1234567”,其长度适中,能够保障签名的唯一性与安全性,在签名生成和验证过程中起着关键作用。 3. 允许误差(AllowableError):以秒为单位设定整数值,用于在签名验证阶段对 UTC 时间戳进行灵活调整,以此应对网络延迟或时间同步问题所导致的临界情况,从而增强算法的适应性与准确性。
(二)时间戳处理流程
1. 获取 UTC 时间戳(UTCTimestamp):精确获取当前的 UTC 时间戳,该时间戳表示从 1970 年 1 月 1 日 00:00:00 UTC 到当前时刻所经过的秒数,不受时区的影响。假设在本示例中,某时刻对应的 UTC 时间戳为 1735466521(如 2024 - 12 - 30 02:02:01 GMT +8 对应的 UTC 时间戳),此时间戳将作为后续一系列计算的基础数据。 2. 时间戳调整:分别计算 UTCTimestamp + AllowableError 和 UTCTimestamp - AllowableError ,同时妥善保留原始的 UTC 时间戳。这样便得到了三个不同版本的时间戳,即原始时间戳、增加允许误差后的时间戳以及减少允许误差后的时间戳,它们将用于后续不同场景下的计算与验证工作。 3. 取模运算(Modulo Operation):针对上述三个时间戳,分别将它们除以过期时间(ExpirationTime)进行取模运算,也就是计算每个时间戳除以 600 的余数。该操作的目的在于精准确定每个时间戳在 600 秒周期内所处的具体位置,为后续的计算提供关键的周期内偏移量信息,以便能够更加精确地处理时间与签名之间的对应关系。 4. 消除小数部分(Eliminating Decimal Part):对于参与计算的三个时间戳,分别用它们减去各自取模运算所得到的余数,从而得到三个新值。这一步骤能够有效地消除因时间戳除以过期时间而可能产生的小数部分,确保后续的计算结果均为整数,使得时间周期的计算更加准确和稳定,进而精确地反映完整的时间周期数量。 5. 整数计算(Integer Calculation):将得到的三个新值分别除以过期时间(600 秒),最终所得的结果必然为整数。这些整数分别代表了从起始时间点开始,在不同时间偏移情形下所经历的完整 600 秒周期的数量。由于在前述步骤中已经消除了小数部分,所以这些结果既精确又会按照每 600 秒的规律发生变化,为签名的生成提供了准确且随时间规律变动的基础数据,有力地保障了签名在时间维度上的准确性和连贯性。
(三)签名生成步骤
1. 当前时段签名(CurrentPeriodSignature):将原始 UTC 时间戳经处理后所得到的整数与密钥字符串(SecretKey)进行拼接。假设在本示例中,处理后的整数为 2892444,与密钥“ABCDEFGabcdefg1234567”拼接成“2892444ABCDEFGabcdefg1234567”,再通过 MD5 算法进行计算,所得的 MD5 值即为当前时段签名,此签名精准代表了当前准确时间周期内的签名信息。 2. 调整后时段签名(AdjustedPeriodSignature):
- 针对 UTCTimestamp + AllowableError 经处理后所得到的整数,与密钥进行拼接形成新字符串,再通过 MD5 计算得出对应签名。此签名主要用于覆盖时间稍晚的临界情况。
- 针对 UTCTimestamp - AllowableError 经处理后所得到的整数,与密钥进行拼接形成新字符串,再通过 MD5 计算得出对应签名。此签名主要用于应对时间稍早的临界情况。
(四)签名验证机制
当接收到请求时,首先提取其中的 MD5 签名信息,然后将其与服务端依据上述算法生成的三个时段签名(当前时段签名、 UTCTimestamp + AllowableError 对应的签名、 UTCTimestamp - AllowableError 对应的签名)逐一进行细致比对。若请求中的 MD5 签名与其中任何一个时段的签名完全匹配,这便表明该请求处于有效时段内,即便存在一定程度的网络延迟或时间同步问题,由于允许误差机制的存在,该请求仍能够顺利通过验证;反之,若与三个时段签名均不匹配,则验证失败,此请求将被视作无效请求,从而切实保障系统仅接受在合理时间范围内且签名正确的请求,有力地维护了系统的安全性以及数据的完整性。
三、客户端
(一)配置参数
1. 过期时间(ExpirationTime):与服务端保持一致,设定为以秒为单位的时长,本示例为 600 秒,超过此时间的签名将被判定为无效。 2. 密钥(SecretKey):使用与服务端相同的特定字符串,即本示例中的“ABCDEFGabcdefg1234567”,以此保证签名的唯一性与安全性,其长度应适中,以满足安全需求。
(二)时间戳处理流程
1. 获取 UTC 时间戳(UTCTimestamp):准确获取当前的 UTC 时间戳,该时间戳是从 1970 年 1 月 1 日 00:00:00 UTC 到当前时刻所经过的秒数,不受时区影响。假设在本示例中,某时刻对应的 UTC 时间戳为 1735466521(如 2024 - 12 - 30 02:02:01 GMT +8 对应的 UTC 时间戳),此时间戳将作为后续计算的基础数据。 2. 取模运算(Modulo Operation):对获取的 UTC 时间戳除以过期时间(ExpirationTime)进行取模运算,即计算其除以 600 的余数。该操作旨在确定当前时间在 600 秒周期内的位置,为后续计算提供关键的周期内偏移量信息。 3. 消除小数部分(Eliminating Decimal Part):用 UTC 时间戳减去取模得到的余数,得到一个新值。这一步有效消除了因时间戳除以过期时间可能产生的小数部分,确保后续计算得到的结果是整数,从而精确地确定时间周期的整数倍。 4. 整数计算(Integer Calculation):将新值除以过期时间(600 秒),所得结果必然为整数。这个整数代表了从 1970 年 1 月 1 日 00:00:00 UTC 开始,经过了多少个完整的 600 秒周期。由于消除了小数部分,这个结果是精确的整数,并且每 600 秒会改变一次。
(三)签名生成步骤
1. 计算签名(CalculateSignature):将上述计算得到的整数与从服务端获取的密钥字符串(SecretKey)进行拼接。假设在本示例中,处理后的整数为 2892444,与密钥“ABCDEFGabcdefg1234567”拼接成“2892444ABCDEFGabcdefg1234567”,再通过 MD5 算法计算,得到的 MD5 值即为签名。
(四)验证
客户端将生成的签名随请求一同提交给服务器,由服务器按照既定的验证机制进行签名验证,以确定请求的合法性与时效性。
四、算法优势
1. 时间准确性与灵活性兼顾
- 精准的时间周期定位:通过获取UTC时间戳,并进行一系列复杂的时间戳处理流程,包括取模运算、消除小数部分和整数计算等,能够精准地确定签名在时间周期中的位置。这确保了签名验证过程可以精确地判断请求是否在有效时间范围内,减少了因时间判断不准确而导致的误判情况。
- 允许误差机制的优势:允许误差(AllowableError)参数的设置使算法具有良好的灵活性。在实际网络环境中,网络延迟或时间同步问题不可避免。该机制能够有效应对这些情况,在误差范围内依然可以正确验证签名,使得系统不会因为微小的时间偏差而拒绝合法请求。例如,在网络波动较大的环境下,可以适当增大允许误差,确保系统的可用性。 2. 签名的安全性保障
- 密钥机制的安全性:密钥(SecretKey)在签名生成和验证过程中起到关键作用。特定的密钥保证了签名的唯一性,只有拥有正确密钥的一方才能生成合法的签名,有效防止了签名被伪造。这为系统的安全性和数据的完整性提供了有力保障。
- 时效性增强安全性:结合过期时间(ExpirationTime)和允许误差机制,限制了签名的有效时间范围,能够防止签名被攻击者无限期地利用。一旦签名超过有效期或者不在允许误差范围内,就会被判定为无效,这有助于抵御重放攻击等安全威胁。 3. 全面的临界情况覆盖
- 服务端生成三个时段的签名,即当前时段签名(CurrentPeriodSignature)和两个调整后时段签名(AdjustedPeriodSignature)。这种设计能够覆盖因网络延迟或时间同步问题导致的时间稍早或稍晚的临界情况。例如,当请求时间稍早于或稍晚于当前准确时间周期时,通过与相应的调整后时段签名进行比对,合法请求依然有机会通过验证,提高了系统的准确性和可用性。 4. 算法的可适应性
- 哈希算法可替换性:虽然文档以MD5算法为例,但也指出了MD5的安全性局限,并强调在实际应用中可以使用更安全的哈希算法(如SHA - 256等)。这种设计使得算法具有良好的可适应性,开发人员可以根据实际的安全需求和应用场景选择合适的哈希算法进行签名计算和验证,而不需要对整个算法架构进行大规模修改。
五、算法劣势
1. 时间戳处理复杂
- 时间戳处理流程包括获取、调整、取模、消除小数部分和整数计算等多个步骤。这使得算法在实现和理解上都比较复杂。对于开发人员而言,要保证每个步骤的准确性比较困难;对于后期维护人员来说,这样复杂的逻辑也增加了代码维护和故障排查的难度。 2. 签名验证过程复杂
- 服务端需要生成并比对三个时段的签名,这增加了验证的复杂性。在高并发场景下,这种复杂的验证过程会消耗更多的系统资源,使系统性能下降。并且复杂的验证逻辑也更容易出错,比如在比对签名时可能出现遗漏或错误比对的情况。 3. 性能开销较大
- 频繁获取时间戳和复杂的签名计算(如拼接操作和哈希计算)会占用系统资源。特别是在高并发情况下,大量请求都需要进行这些操作,会导致系统响应时间延长,影响用户体验。另外,允许误差机制虽然提高了灵活性,但也增加了计算量,进一步加重了系统负担,尤其在允许误差范围大或者请求量多的时候更为明显。
六、设计师杂谈
无
何伟贵 2007年5月27日