iOS - HMAC 加密算法和一个 MD5 加密的问题
最近阅读
前言
最近我们部门重新定义了一下应用更新的接口,使用到的主要加密方式主要有 HMAC SHA1 加密和 MD5 加密。
HMAC SHA1 加密
HMAC SHA1 加密的方法是在 Stack Overflow 上看到的 CommonHMAC in Swift
大概分两步:
- 定义一个 HMAC 加密方式的枚举
- 实现一个 String 的拓展方法用来加密
代码如下:
1 | enum HMACAlgorithm { |
MD5 加密的问题
细心的朋友注意到,上面 HMAC 加密的枚举里有一个 MD5 的字段,如果同时用到 HMAC 加密和 MD5 加密的朋友,需要注意一下 Hmac-MD5 加密和 MD5 加密的区别,推荐可以用在线加密工具比较直观的看到加密结果的区别:在线加解密。另外这个工具也可以用于通信双方用来和自己解密的结果校验是否正确。
回归正题,MD5
加密本身没什么难度,网上搜索一大把。抱着做笔记的目的贴一下 Swift 的源码:
1 | ///字符直接转 md5 |
然后问题就来了:iOS 端的加密和服务器那边的加密结果无法对应,导致鉴权失败。
排查问题,让服务器同事打印在 MD5
加密前的每个步骤的值,发现都是一致的,在 MD5
加密后就不一致了。然后去就看了一下他写的源码,服务器那边的逻辑使用 Java
写的,发现他丢进 MD5
加密时是把上一步的结果调用 getBytes()
语句后丢进去的。即加密的是字符串转换后的字节数组。所以在 iOS 端这边的处理也需要将 String
转换成 Data
数据来加密。
所以步骤分为以下两步:
1.把 String
类型数据转换成 16 进制 Data
数据——注意是 16 进制的 Data
数据,如果直接用原生方法 "<#String#>".(using: .utf8)
转换肯定是不行的。
2.把 Data
数据丢进 MD5
方法中进行加密
而在网上搜了一圈,Swift 版本大部分看到的都是用字符串进行 MD5
加密,最后仍是在 Stack Overflow 上看到了一个正确的结果 - MD5 of Data in Swift 3
最后和 String
转 Data
的方法整合以后。代码如下:
1 | ///转换成 Data 数据再转换成 md5 |
使用:
1 | let md5Str = "两个黄鹂鸣翠柳,一行白鹭上青天。".conversionToDataToMD5() |
然后因为业务原因,也用 OC 实现了这一整套的加密流程,最后一步的转换加密也大同小异:
- 转换成 16 进制
NSData
数据1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27+(NSData*)getHexDataWithString:(NSString*)string{
const char *buf = [string UTF8String];
NSMutableData *data = [NSMutableData data];
if (buf){
uint32_t len = strlen(buf);
char singleNumberString[3] = {'\0', '\0', '\0'};
uint32_t singleNumber = 0;
for(uint32_t i = 0 ; i < len; i+=2){
if ( ((i+1) < len) && isxdigit(buf[i]) && (isxdigit(buf[i+1])) ){
singleNumberString[0] = buf[i];
singleNumberString[1] = buf[i + 1];
sscanf(singleNumberString, "%x", &singleNumber);
uint8_t tmp = (uint8_t)(singleNumber & 0x000000FF);
[data appendBytes:(void *)(&tmp)length:1];
}else{
break;
}
}
}
return data;
} NSData
MD5
加密
OCMD5
的加密就概不累述了,OC 比 Swift 更容易搜到,放一个我参考的博客:Objective-C NSString NSData Byte 等转换
-
2018-06-14
* 一直有把 iOS 开发里用到的一些边边角角的小技巧写成一个集合的想法,但一直没有付诸实践。刚好备忘录里的零零碎碎记的东西够凑成一篇东西来,就把之前的一篇 OC 笔记 - 一些小技巧和问题处理的集合 给改了名,加上现在的第二篇,打算以后写成一个系列。长路漫漫,与诸君共勉。*
一、打印bool值
-
2020-09-12
注意到工程里面关于权限请求这块的逻辑没有很好地管理起来,一些是用 OC 的工具类,一些是用 Swift 代码在一些
ViewController
里面单独调用,不能复用,就想封装一个 Swift 版关于权限请求的工具类,虽然这个需求在 GitHub 上搜索也有很多现成的轮子,但使用起来感觉太重,而且有些久不维护,Swift 版本更新的又快,有些接口就不好使了,索性就自己封装一个。一开始的思路也是想通过枚举来创建不同权限字段,通过静态方法来实现请求,但是蓝牙权限和定位权限需要实例化对象,设置代理。当使用
static
关键字来创建蓝牙和定位对象,当应用内有其他的业务也要使用蓝牙和定位对象时,代理响应就会有点问题。后面索性就用单例方法创建一个整体的权限管理对象,然后创建类方法,在类方法中自己调用自己。 -
2020-04-24
最近在优化一个项目的过程,过程中发现之前开发时由于刚接触
Swift
的原因,在Swift
中的类里使用了很多OC
的写法,比如字典数组对象会习惯性用NSDictionary
、NSArray
来初始化,而不是用[KeyType: ValueType]()
或是[SomeType]()
这种类型来实例化变量。虽然在使用上没有什么问题,但看起来多少有点。。。不优雅。
当我把大部分类型都修改成Swift
中的写法后(部分未修改是因为使用String
类型来给文本做截取和富文本定义,实在不如NSString
顺手,这种不顺手让我不由想起 Stack Overflow 上看到的一个评论:I thougt i already getting along well with Swift.)发现,原来一些变量是否为空的判断中,使用Swift
里的optional
类型会方便很多。
比如解析一个 json 数据,如果层级多而且里面每个元素都是不确定的,那么可能就需要每个层级都判一次空。而如果使用 ? 来设置当前对象为可选值,只需要在最后一层实际使用到对象值时,判一次空就 OK 了。
对于 ? 和 ! 的区别和总结,网上有很多文章,在这里就不重复造轮子了。下面就对这个optional
的自己两个疑问做个记录。? 和 ! 是表示两种不同的类型吗,一种是可以为空,一种不可以为空?
-
2020-04-11
前言
给
UITableView
同时设置圆角和阴影时发现在视图上只会显示圆角,原因是因为当我们设置masksToBounds
为YES
允许圆角剪裁时,圆角以外的阴影也会一并被剪裁掉。在网上找了一下解决方法,ios阴影圆角共存 这篇文章提供了一个思路,就是把圆角和阴影放在不同的两个控件上实现,然后叠加到一块。基本思路是正确的,但实际操作发现在最后插入作为阴影层的CALayer
,调用的方法可能会照成层级有点混乱的问题。下面展示一下我解决这个问题的方法和用 Swift 实现的代码。 -
2019-05-11
项目最后的交接工作,我被派到了中移动总部进行封闭开发,暂时作为 iOS 方面的项目管理和推进,就之前来说,这个礼拜我负责的内容多了一些,除了我本身的代码维护以外,对外要处理项目的交接工作,对内要分配测试人员测试出的 bug,和一些缺失内容,优化内容的推进。一个礼拜下来,有一些收获。
之前看知乎上一个问题,是有什么是当上管理层才会想的事?虽然我还没有到那个地步,但是管理项目给我的一些体验让我觉得似乎可以把握到一些管理层的想法,比如很多时候我们觉得领导只看结果不问过程有点不可理喻,但是从另一方面来看这其实只是因为需要对接的内容太多,不问过程只看结果,可以最大程度的排除其他因素的干扰。另一个是就是个人的主观动能性,这阵子做项目管理的时候,我总是会因为分配下去的任务而收到关于很多任务的疑问,比如新增一项需求的时候,开发人员会询问关于这个功能在不同场景下需要表现成怎样,在一些无法实现的地方又应该怎样规避。在管理角度看,这些当然是合理的,但提问的时机太零碎了,容易被分散注意力,另一个是有些场景虽然没有给出标准,但其实可以横向参考其他类似的功能来实现需求,这时候提问并不是必要的,所缺乏的只是一点主动去思考,或者说是虽然想到了第一步,即会产生这个问题,但可能是某种局限导致开发人员没有往下一步怎么解决这个问题,我之前也存在过类似问题。切成开发人员角度,规避这些问题,一个是整理问题,统一解决,另一个是解决问题的方法,虽然可以思考怎么解决,但是如果解决方法最终没有通过产品的审核,那之前针对问题的解决也都白费劲,所以最好的应对方法是,发现问题,可以附上一条或两条解决方案,一并提交。我想这些经验对于以后我做个人开发或者管理都会有帮助。
这个礼拜接触到的新技术是使用 OC/Swift 自动生成文档的轮子: