一种基于时间戳和密钥的签名算法

一、算法概述

本算法由何伟贵在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):

(四)签名验证机制

当接收到请求时,首先提取其中的 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. 时间准确性与灵活性兼顾

五、算法劣势

1. 时间戳处理复杂

六、设计师杂谈

何伟贵 2007年5月27日