[转]Hash算法的理论介绍
Hash,一般翻译做"散列",也有直接音译为"哈希"的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不 同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。
简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
HASH主要用于信息安全领域中加密算法,他把一些不同长度的信息转化成杂乱的128位的编码里,叫做HASH值. 也可以说,hash就是找到一种数据内容和数据存放地址之间的映射关系
了解了hash基本定义,就不能不提到一些著名的hash算法,MD5 和 SHA1 可以说是目前应用最广泛的Hash算法,而它们都是以 MD4 为基础设计的。那么他们都是什么意思呢?
这里简单说一下:
1) MD4
MD4(RFC 1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的,MD 是 Message Digest 的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位操作数的位操作来实现的。
2) MD5
MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好
3) SHA1 及其他
SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。
那么这些Hash算法到底有什么用呢?
Hash算法在信息安全方面的应用主要体现在以下的3个方面:
1) 文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
MD5 Hash算法的"数字指纹"特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。
2) 数字签名
Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。 对 Hash 值,又称"数字摘要"进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。
3) 鉴权协议
如下的鉴权协议又被称作"挑战--认证模式:在传输信道是可被侦听,但不可被篡改的情况下,这是一种简单而安全的方法。
用hash算法加密用户名对应的密码,存入数据库中,使密码不能直观可见,增强密码的安全性能。哈希算法是单向的,可以将字符串转换成某个某个输出,但无法从输出确定输入值,确保即使加密后的字符泄漏,也无法获得原输入值。本系统中使用的hash算法是MD5.
/// <summary>
/// 对字符串进行md5哈希算法加密。
/// </summary>
/// <param name="unencryptPassword">待加密的字符串</param>
/// <returns>返回一个包含哈希密码的字符串</returns>
public string Encrypt(string unencryptPassword)
{
//添加对应加密算法
string hashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(unencryptPassword, "md5");
return hashedPassword;
}
/// <summary>
/// 检查密码是否正确
/// </summary>
/// <param name="userID"></param>
/// <param name="password"></param>
/// <returns></returns>
public bool CheckUserPassword(decimal userID, string password)
{
return iL.CheckUserPassword(userID,Encrypt(password));
}
/// <summary>
/// 修改密码
/// </summary>
/// <param name="userID"></param>
/// <param name="password"></param>
/// <returns></returns>
public int UpdateUserPassword(decimal userID, string password)
{
return iL.UpdateUserPassword(userID, Encrypt(password));
}
===================================================================
best way to handle user id hash common to all rails requests
Q:
Each client is identified by a hash, passed along with every request to the server. What's the best way to handle tracking a users session in this case?
I'm using restful_authentication for user accounts etc. A large percentage of requests are expected to originate without a user account but just the unique hash.
My understanding of the way handles sessions is limited so please bear that in mind. :)
A:
Using this hash in the URL means that you don't have Rails built-in session. The point of the session is to provide some sense of state between requests. You're already providing this state, seeing that you are passing this hash, so in my opinion you could remove the restful_authentication plugin and do something like this instead:
class ApplicationController < ActionController::Base
def require_login
if params[:access_key]
@current_user = User.find_by_access_key(params[:access_key]) || restrict_access
else
restrict_access
end
end
def restrict_access
flash[:error] = "You have to log in to access that."
redirect_to root_path
endThen, do a
end
before_filter :require_loginin the controllers where login is required for access.
=====================================================================================
Hash表和TList的结合使用
试想一下,如果在游戏中如果突然有哪个玩家断线,那么即便是我们知道这个玩家的Socket,但是要从所有玩家中检索出他的信息,
也不是一件容易的事。
那我们为什么不能将Hash表和Tlist结合使用呢。在我开发的游戏中,我就是将Hash表和Tlist同时使用,来对玩家断线做相关的处理。
今天我就简单的写一下我是如何处理的。
假定有一个Tlist中(UserList)保存着游戏中某房间的所有玩家信息。玩家的信息结构如下:
RuserInfo = record
Socket;Tsocket;
UserID:String[20];
Face:Byte;
Sex:Boolean;
Socre:Integer;
CurrStatus:Integer;
End;
PuserInfo = ^ RuserInfo;
我们来创建一个Hash表和一个Tlist表:
ScHash:= THashedStringlist.Create;
UserList:=Tlist.Create;
当某一玩家加入游戏时这样处理。
New(P_User)
P_User.Socket:=3500;
P_User.UserID:=’fxh7622’;
P_User.Face:=3;
P_User.Sex:=true;
P_User.Socre:=1000;
P_User.CurrStatus:=0;
Index:=ScHash.IndexOf(IntToStr(p_User.Socket));
if Index=-1 then
begin
ScHash.AddObject(IntToStr(p_User^.Socket),TObject(Integer(p_User)));
end;
//这里将玩家的信息以Socket作为KEY来放入Hash表中。
UserList.Add(P_User);
//在这里将玩家的信息保存在一个Tlist表中。通过前面我的文章中介绍,大家可以知道在HASH表中和在Tlist表中保存的是
//同一个内容,也就是说:如果修改了某玩家在Tlist中保存的信息那么他在Hash表中保存的信息也将随着修改。
这样当玩家断线以后,我们可以快速的使用Hash表来检索出是哪个玩家断线。
function TUserBaseControl.Sel_Hash(sc:TSOCKET;var p_User:PUserSocket): Boolean;
var
t_User:PUserSocket;
t_Object:TObject;
Index:Integer;
begin
Result:=false;
Index:=ScHash.IndexOf(IntToStr(sc));
if Index<>-1 then
begin
t_Object:=ScHash.Objects[Index];
p_User:=PUserSocket(t_Object);
Result:=true;
end;
end;
检索出玩家信息以后可以将玩家信息中的相关信息进行修改。
例如:p_User.CurrStatus:=5;
以上的例子只是对Hash表和Tlist使用的一个小小的窍门,但是的确可以加快服务器的处理速度。希望也对大家有一个帮助。
浙公网安备 33010602011771号