user-0 提问: c/c++,密码有效期的函数

回复:
user: user-1
content: 引用 27 楼 zhao4zhong1 的回复:[quote=引用 25 楼 DelphiGuy 的回复:] [quote=引用 24 楼 zhao4zhong1 的回复:] 使用北斗卫星校准时间！  你咋不让他买俩原子钟呢...  [/quote] 估计买原子钟花钱多多了。[/quote]  那肯定，最便宜的铷原子钟也要一万多，几百年误差一秒，当然二手拆机的也就几百到一两千，这种廉价原子钟精度还是不如北斗授时的，北斗授时精度可以达到误差0.3纳秒以内。

user: user-1
content: 引用 24 楼 zhao4zhong1 的回复:使用北斗卫星校准时间！  你咋不让他买俩原子钟呢...

user: user-2
content: 使用北斗卫星校准时间！

user: user-3
content: 学习路过顶

user: user-2
content: 引用 25 楼 DelphiGuy 的回复:[quote=引用 24 楼 zhao4zhong1 的回复:] 使用北斗卫星校准时间！  你咋不让他买俩原子钟呢...  [/quote] 估计买原子钟花钱多多了。

user: user-4
content: 我是这样想的，客户端有公钥，服务器有私钥，客户端将时间加密，上送到服务器，服务器解密校验看看是不是允许通讯

user: user-5
content: 网游可能涉及到防外挂机制了，确实比较复杂。

user: user-0
content: 引用 20 楼 hzy_76 的回复:不改变长度和字节序？这个要求貌似不是很必要啊，只要在原程序收到之前，被你的程序先解密，原程序收到的依然是正确的数据就够了吧。如果这样的话，就可以考虑压缩和全文加密了。  如果非要这么严格，我给你提供一个思路，不见得好，帮你拓展一下思维：第一个字节转为十进制然后取个位数，按这个数再去取另一个序号的数据，比如02 AB 3F 90这样的头部，按第一个字节02去取第3个字节3F，这个数就用来做密钥的种子。加密时，对第一个字节、所选取的另一个字节（本例中是第3个）不加密。收到数据时也按此思路，保持这两个字节不解密。  这样做不复杂，结果的规律性也不强，你觉得呢？ 你的这个方法我也试过，奇怪的事，在普通聊天程序上没任何问题，因为没有被HOOK的程序本身就没有其它复杂的字节验证什么的， 但现在碰到的这个网游程序，他本身就有一些验证规则，他的程序是WSARecv接收数据的，不知道他程序怎么处理的，一但不是一个字节一个字节处理他就会强制断开这个socket，你说的先看前一个字节，再处理后一个字节就显然 不行了，只要不是单独处理单字节 就会被断开

user: user-5
content: 不改变长度和字节序？这个要求貌似不是很必要啊，只要在原程序收到之前，被你的程序先解密，原程序收到的依然是正确的数据就够了吧。如果这样的话，就可以考虑压缩和全文加密了。  如果非要这么严格，我给你提供一个思路，不见得好，帮你拓展一下思维：第一个字节转为十进制然后取个位数，按这个数再去取另一个序号的数据，比如02 AB 3F 90这样的头部，按第一个字节02去取第3个字节3F，这个数就用来做密钥的种子。加密时，对第一个字节、所选取的另一个字节（本例中是第3个）不加密。收到数据时也按此思路，保持这两个字节不解密。  这样做不复杂，结果的规律性也不强，你觉得呢？

user: user-0
content: 引用 16 楼 hzy_76 的回复:关于时间同步问题，我没测试过如果都同步网络时间的话，能不能达到秒级的一致性。我们以前做过设备时间同步的，有一个时间同步协议，感兴趣的话可以去找来看看。基本的原理我可以在这里给你说说： 首先有一个很重要的假设，就是一来一回两次的数据包传输时间一样。机器A发包时打上时间戳，记为t1，机器B收到包时记录时间T2，回复包时打上另一个时间戳T2，机器A收到回复时记录时间t2。此时机器A可以得知其发包到收到回复的时间是t2 - t1，而机器B的业务处理时间是T2 - T1，则单程的传输时间为((t2 - t1) - (T2 - T1))/2，因为已知机器B的发包时间是T2，因此机器A就可以把自己的时间校正为T2 + ((t2 - t1) - (T2 - T1))/2，即跟机器B同步。 可以看出来这个算法的误差，一是传输时间是否绝对一样，二是设置本地时间所耗费的时间。但是我想这个精度应该已经能满足你的需要了。你可以把这几个时间戳加到数据通讯的报文里，不必单独做时间同步协议，抽取一定比例的数据包中的时间戳用来校正时间就可以了。 你说的这些我也早想过，但如果加个前提 ， 这个前提就是在不改变原数据的长度和字节序的情况下（首先这些程序是客户的，我们是在没有程序源码的情况下给这些客户的程序封包加解密，要求不允许改变原始数据长度和字节序），给这些要发送的数据加密，那只能单字节加密，单字节加解密的缺点是太容易看得懂了，比如客户程序有时候 会在短时间内连续发送数据"01 02 00 00 08 08 FF 00 00 AD 00 00"这样的数据,单字节加密，又不可以改这些数据的序列，如果用固定密钥加密，那么加密后的数据还是会变成连续的“xxxxxxxxx”什么的，所以我想到用时间seed做可变的密钥，这样数据就不会还是连续的"xxxxxxxx"，就会变成杂乱无章的字节序。而且老板不允许增加网络开销，其实倒不是怕有什么开销，主要是怕我们的程序hook客户的程序后另发数据包会给客户程序原本的通信验证带来难度，导致各种有可能不稳定的因素。 所以你看在不改变原数据的长度和字节序的还有不发送额外数据情况下怎么做单字节加解密，然后加密后的数据要看起来杂乱无章呢？

user: user-0
content: 引用 15 楼 baidu_37097818 的回复:自相矛盾，照你的说法，所有时间都只能是同一个值了。1分0秒的密码必须和1分30的密码一样，1分30秒的密码又必须和2分0秒的密码一样，2分0秒的密码又必须和2分30秒的密码一样，2分30秒的密码又必须和3分0秒的密码一样，…… 嗯，你这个比喻很到位，确实是我疯了，想多了。哈哈。

user: user-5
content: 不好意思，手误，其中一句要纠正一下： 机器B收到包时记录时间T1

user: user-5
content: 关于时间同步问题，我没测试过如果都同步网络时间的话，能不能达到秒级的一致性。我们以前做过设备时间同步的，有一个时间同步协议，感兴趣的话可以去找来看看。基本的原理我可以在这里给你说说： 首先有一个很重要的假设，就是一来一回两次的数据包传输时间一样。机器A发包时打上时间戳，记为t1，机器B收到包时记录时间T2，回复包时打上另一个时间戳T2，机器A收到回复时记录时间t2。此时机器A可以得知其发包到收到回复的时间是t2 - t1，而机器B的业务处理时间是T2 - T1，则单程的传输时间为((t2 - t1) - (T2 - T1))/2，因为已知机器B的发包时间是T2，因此机器A就可以把自己的时间校正为T2 + ((t2 - t1) - (T2 - T1))/2，即跟机器B同步。 可以看出来这个算法的误差，一是传输时间是否绝对一样，二是设置本地时间所耗费的时间。但是我想这个精度应该已经能满足你的需要了。你可以把这几个时间戳加到数据通讯的报文里，不必单独做时间同步协议，抽取一定比例的数据包中的时间戳用来校正时间就可以了。

user: user-6
content: 自相矛盾，照你的说法，所有时间都只能是同一个值了。1分0秒的密码必须和1分30的密码一样，1分30秒的密码又必须和2分0秒的密码一样，2分0秒的密码又必须和2分30秒的密码一样，2分30秒的密码又必须和3分0秒的密码一样，……

user: user-0
content: 感谢“老马何以识途”和“早打大打打核战争”你们两位，好像就你们俩位明白我的意思 我最后想了想，在不可能互相通信的情况下，就算时间严格一致也做不到 	for (int i = 0; i < 60; i++) 	{ 		getkey(xx分xx秒) = getkey(xx分xx秒 + i) 	} 帖子先留着看看有没有人讨论吧，明天再来看看

user: user-1
content: 只要两台设备从同一时间服务器定时同步，保证双方时间误差小于一秒就可以。比如这个东西就是每分钟生成一个动态密码：

user: user-5
content: 想了一下，还有另一个做法，更新密钥时也通过加密通讯告知对方，但还用旧密钥通讯，对端收到新的密钥后保存下来，这个过程必须保证可靠，即发送方要确认对端已经收到。确认后方可删除本地旧密钥。

user: user-5
content: 引用 8 楼 micckkk 的回复:客户端的数据需要通过密钥加密，然后服务端通过 这个密钥解密数据，这个密钥就是以上我想问的有时效的密钥 以上通信是严格控制的，也无法多附加任何其实数据的传输，只能传输指定的数据。所以没法传输密钥。 唯一共同点就是日期和时间  那么你这个方案就有很大问题，因为首次生成密钥的时间无法同步，即使时间严格一致，也没办法保证知道对方更新密钥的具体秒数——这个数据若要传输必须通过加密通讯，而新的密钥对方却不知道！发现陷入了一个悖论没？ 解决办法呢，一是大家都从每分钟的开始更新密钥，二是更新时间通过不加密手段告知对方。  但是我还有另一个疑问，你能保证两台设备的时间严格一致吗？

user: user-7
content: 两端平台一样的话可以用伪随机解决啊	time_t t=time(0); 	t=t-t%60; 	srand(t); 	int encode_key=rand();		//这里可以约定循环取几次  拿到key就随便搞了

user: user-1
content: 取秒计数，比如用time()函数，再整除以60得到分计数，以分计数来生成密码就可以。