最近阅读
前言
最近我们部门重新定义了一下应用更新的接口,使用到的主要加密方式主要有 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 等转换