
“散列”,也有直接音译为“哈希”的,就是把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,所以不可能从散列值来确定唯一的输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。简单来说,hash算法(即散列函数),是一种单向密码体制,即它是一个从明文到密文的不可逆的映射,只有加密过程,没有解密过程。同时,哈希函数可以将任意长度的输入经过变化以后得到固定长度的输出。哈希函数的这种单向特征和输出数据长度固定的特征使得它可以生成消息或者数据。相同数据运算,得到的结果是一样的(同样的数据,得到的结果是一样的)不同数据运算,得到的结果是定长的,如MD5得到的结果默认是128位,32个字符(16进制标识)。无法逆运算“指纹”,是用来做数据识别的、完整性检查的。网络传输数据 + 本地保存数据 + 服务端保存数据等 ,这些是隐私数据,绝对不能明文,一定是密文传输/存储。作为一个iOS开发者,我自己也有总结归纳很多在这条路上要用到的进阶学习资源,文档视频资源等等,这里我免费分享给大家点击领取
MD4(RFC 1320)是 MIT 的Ronald L. Rivest在 1990 年设计的,MD 是 Message Digest(消息摘要) 的缩写。它适用在32位字长的处理器上用高速软件实现——它是基于 32位操作数的位操作来实现的。MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。Message Digest Algorithm MD5(消息摘要算法5)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。是计算机广泛使用的杂凑算法之一,将数据(如汉字)运算为另一固定长度值,是杂凑算法的基础原理,MD5的前身有MD2、MD3和MD4。特点压缩性:任意长度的数据,算出的MD5值长度都是固定的。容易计算:从原数据计算出MD5值很容易。抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。强抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。安全哈希算法(Secure Hash Algorithm)主要适用于数字签名标准里面定义的数字签名算法(Digital Signature Algorithm DSA)。对于长度小于2^64位的消息,SHA1会产生一个160位的消息摘要。当接收到消息的时候,这个消息摘要可以用来验证数据的完整性。在传输的过程中,数据很可能会发生变化,那么这时候就会产生不同的消息摘要。SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。SHA-2 SHA-224、SHA-256、SHA-384,和SHA-512并称为SHA-2。 新的哈希函数并没有接受像SHA-1一样的公众密码社区做详细的检验,所以它们的密码安全性还不被大家广泛的信任。 虽然至今尚未出现对SHA-2有效的攻击,它的算法跟SHA-1基本上仍然相似;因此有些人开始发展其他替代的哈希算法。注:这里只做简单介绍,并不展开详细说明,有兴趣的可以参考以下链接
<!--h文件-->#import <Foundation/Foundation.h>@interface NSString (Hash)#pragma mark - 散列函数
/**
* 计算MD5散列结果
*
* 终端测试命令:
* @code
* md5 -s "string"
* @endcode
*
* <p>提示:随着 MD5 碰撞生成器的出现,MD5 算法不应被用于任何软件完整性检查或代码签名的用途。<p>
*
* @return 32个字符的MD5散列字符串
*/- (NSString *)md5String; /**
* 计算SHA1散列结果
*
* 终端测试命令:
* @code
* echo -n "string" | openssl sha1
* @endcode
*
* @return 40个字符的SHA1散列字符串
*/- (NSString *)sha1String; /**
* 计算SHA256散列结果
*
* 终端测试命令:
* @code
* echo -n "string" | openssl sha -sha256
* @endcode
*
* @return 64个字符的SHA256散列字符串
*/- (NSString *)sha256String; /**
* 计算SHA 512散列结果
*
* 终端测试命令:
* @code
* echo -n "string" | openssl sha -sha512
* @endcode
*
* @return 128个字符的SHA 512散列字符串
*/- (NSString *)sha512String;#pragma mark - HMAC 散列函数
/**
* 计算HMAC MD5散列结果
*
* 终端测试命令:
* @code
* echo -n "string" | openssl dgst -md5 -hmac "key"
* @endcode
*
* @return 32个字符的HMAC MD5散列字符串
*/- (NSString *)hmacMD5StringWithKey:(NSString *)key; /**
* 计算HMAC SHA1散列结果
*
* 终端测试命令:
* @code
* echo -n "string" | openssl sha -sha1 -hmac "key"
* @endcode
*
* @return 40个字符的HMAC SHA1散列字符串
*/- (NSString *)hmacSHA1StringWithKey:(NSString *)key; /**
* 计算HMAC SHA256散列结果
*
* 终端测试命令:
* @code
* echo -n "string" | openssl sha -sha256 -hmac "key"
* @endcode
*
* @return 64个字符的HMAC SHA256散列字符串
*/- (NSString *)hmacSHA256StringWithKey:(NSString *)key; /**
* 计算HMAC SHA512散列结果
*
* 终端测试命令:
* @code
* echo -n "string" | openssl sha -sha512 -hmac "key"
* @endcode
*
* @return 128个字符的HMAC SHA512散列字符串
*/- (NSString *)hmacSHA512StringWithKey:(NSString *)key;#pragma mark - 文件散列函数
/**
* 计算文件的MD5散列结果
*
* 终端测试命令:
* @code
* md5 file.dat
* @endcode
*
* @return 32个字符的MD5散列字符串
*/- (NSString *)fileMD5Hash; /**
* 计算文件的SHA1散列结果
*
* 终端测试命令:
* @code
* openssl sha -sha1 file.dat
* @endcode
*
* @return 40个字符的SHA1散列字符串
*/- (NSString *)fileSHA1Hash; /**
* 计算文件的SHA256散列结果
*
* 终端测试命令:
* @code
* openssl sha -sha256 file.dat
* @endcode
*
* @return 64个字符的SHA256散列字符串
*/- (NSString *)fileSHA256Hash; /**
* 计算文件的SHA512散列结果
*
* 终端测试命令:
* @code
* openssl sha -sha512 file.dat
* @endcode
*
* @return 128个字符的SHA512散列字符串
*/- (NSString *)fileSHA512Hash;@end<!--m文件-->#import "NSString+Hash.h"#import <CommonCrypto/CommonCrypto.h>@implementation NSString (Hash)#pragma mark - 散列函数- (NSString *)md5String { const char *str = self.UTF8String;
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *)sha1String { const char *str = self.UTF8String;
uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
- (NSString *)sha256String { const char *str = self.UTF8String;
uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
CC_SHA256(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
- (NSString *)sha512String { const char *str = self.UTF8String;
uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
CC_SHA512(str, (CC_LONG)strlen(str), buffer); return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}#pragma mark - HMAC 散列函数- (NSString *)hmacMD5StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String;
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *)hmacSHA1StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String;
uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
- (NSString *)hmacSHA256StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String;
uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
- (NSString *)hmacSHA512StringWithKey:(NSString *)key { const char *keyData = key.UTF8String; const char *strData = self.UTF8String;
uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer); return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}#pragma mark - 文件散列函数#define FileHashDefaultChunkSizeForReadingData 4096- (NSString *)fileMD5Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil;
}
CC_MD5_CTX hashCtx;
CC_MD5_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break;
}
}
}
[fp closeFile];
uint8_t buffer[CC_MD5_DIGEST_LENGTH];
CC_MD5_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
}
- (NSString *)fileSHA1Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil;
}
CC_SHA1_CTX hashCtx;
CC_SHA1_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
CC_SHA1_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break;
}
}
}
[fp closeFile];
uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
CC_SHA1_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
}
- (NSString *)fileSHA256Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil;
}
CC_SHA256_CTX hashCtx;
CC_SHA256_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
CC_SHA256_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break;
}
}
}
[fp closeFile];
uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
CC_SHA256_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
}
- (NSString *)fileSHA512Hash { NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self]; if (fp == nil) { return nil;
}
CC_SHA512_CTX hashCtx;
CC_SHA512_Init(&hashCtx); while (YES) { @autoreleasepool { NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
CC_SHA512_Update(&hashCtx, data.bytes, (CC_LONG)data.length); if (data.length == 0) { break;
}
}
}
[fp closeFile];
uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
CC_SHA512_Final(buffer, &hashCtx); return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
}#pragma mark - 助手方法
/**
* 返回二进制 Bytes 流的字符串表示形式
*
* @param bytes 二进制 Bytes 数组
* @param length 数组长度
*
* @return 字符串表示形式
*/- (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length { NSMutableString *strM = [NSMutableString string]; for (int i = 0; i < length; i++) {
[strM appendFormat:@"%02x", bytes[i]];
} return [strM copy];
}@ende10adc3949ba59abbe56e057f20f883e- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
NSString *pwd = @"123456";
//传递数据
pwd = pwd.md5String;
NSLog(@"pwd - %@", pwd);
}<!--运行结果-->
pwd - e10adc3949ba59abbe56e057f20f883e结论:直接使用MD5不安全,大部分MD5现在通过网站都可以还原//加盐static NSString *salt = @"LKSJDFLKJ";
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ NSString *pwd = @"123456"; //传递数据
pwd = [pwd stringByAppendingString:salt].md5String; NSLog(@"pwd - %@", pwd);
}
<!--运行结果-->
pwd - 2cac01acb03a3cc2b96cee3aae4d2276结论:加固定盐,现在也不安全,因为如果盐泄漏了,也会有数据泄漏的风险判断是否有key,这个key是由服务器动态提供的,保存在手机侧。简单来说,就相当于现在的授权设备,HMAC主要就是检测你的设备是否有授权。其代码演示如下- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ NSString *pwd = @"123456"; //传递数据
//key是动态的,由服务器提供(即一个账号一个key)
pwd = [pwd hmacMD5StringWithKey:@"CJL"]; NSLog(@"pwd - %@", pwd);
}
<!--打印结果-->
pwd - b123975de0f19edef5a546bf212bd918结论:现在这种加密方式,用户密码确实安全了。但是用于服务器登录验证是一个hash值,而不是密码。所以这个hash值也有被拦截的风险。也是不安全的时间戳。对于密码来说,加密方式还是采用HMAC加密。只是验证方式发生了变化。原本只是验证hash值即可。现在是在hash值的基础上加上了一个时间期限。例如hash值的有效时间最多是2分钟,超过这个时间就失效了。类似于现在验证码的验证。主要流程如下:HMAC加密,得到一个hash值A,hash值带上服务器给的时间戳,求得另一个hash值BHash值A、Hash值B发送到服务器进行验证Hash值A = b123975de0f19edef5a546bf212bd9182021-4-10 17:15:10) 得到的hash值B = 430a60f4989e104e9e903dbdcb84c69aHash值A : b123975de0f19edef5a546bf212bd918hash值B : 430a60f4989e104e9e903dbdcb84c69a2021-4-10 17:15:11) 得到的hash值C = 0cf1dceda0fd58aefd4c7a7b2b08e193hash值C不等,继续求HMAC带上上一个时间(2分钟内)的 hash值D = 430a60f4989e104e9e903dbdcb84c69a.与hash值B相等,所以验证通过- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ NSString *pwd = @"123456"; //传递数据
pwd = [pwd hmacMD5StringWithKey:@"CJL"];//key是动态的,由服务器提供
NSLog(@"pwd - %@", pwd);
pwd = [NSString stringWithFormat:@"%@%@",pwd, [self getOtherTimeStrWithString:@"2021-4-10 17:15:10"]].md5String; NSLog(@"pwd - %@", pwd);
}
- (NSString *)getOtherTimeStrWithString:(NSString *)formatTime{ NSLog(@"formatTime - - - - - -%@",formatTime); NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterMediumStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
[formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"]; //(@"YYYY-MM-dd hh:mm:ss") ----------设置你想要的格式,hh与HH的区别:分别表示12小时制,24小时制
//设置时区选择北京时间
NSTimeZone* timeZone = [NSTimeZone timeZoneWithName:@"Asia/Beijing"];
[formatter setTimeZone:timeZone]; NSDate* date = [formatter dateFromString:formatTime]; //------------将字符串按formatter转成nsdate
//时间转时间戳的方法:
NSInteger timeSp = [[NSNumber numberWithDouble:[date timeIntervalSince1970]] integerValue] * 1000; NSLog(@"将某个时间转化成 时间戳timeSp:%ld",(long)timeSp); //时间戳的值
return [NSString stringWithFormat:@"%ld",(long)timeSp];
}

原始数据Hash值进行RSA加密后得到的hash值,其中原始数据HASH值RSA加密后得到的值称为原始数据的 数字签名
相同的数据结果相同不同的数据长度相同HMAC:比较好的方案,因为破解的成本 大于 破解后的获益,所以相对安全HASH + 时间戳:这样的方式,每次加密结果不一样,因为受时间的影响比较大RSA + HASH在rails源中:https://github.com/rails/rails/blob/master/activesupport/lib/active_support/lazy_load_hooks.rb可以看到以下内容@load_hooks=Hash.new{|h,k|h[k]=[]}在IRB中,它只是初始化一个空哈希。和做有什么区别@load_hooks=Hash.new 最佳答案 查看rubydocumentationforHashnew→new_hashclicktotogglesourcenew(obj)→new_has
我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为
我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上
如何将lambda传递给hash.each,以便我可以重复使用一些代码?>h={a:'b'}>h.eachdo|key,value|end=>{:a=>"b"}>test=lambdado|key,value|puts"#{key}=#{value}"end>test.call('a','b')a=b>h.each&testArgumentError:wrongnumberofarguments(1for2)from(irb):1:in`blockinirb_binding'from(irb):5:in`each'from(irb):5from/Users/jstillwell/.rv