iOS - 安全
1. CheckList
http://www.jianshu.com/p/d3cc2d5c177d
a 数据安全。分为数据传输安全和数据存储安全
数据存储安全为保存在App中的数据安全。不允许明文存储用户的敏感信息如用户名,密码,token等。应采用适当的加密技术
数据传输安全即要求采用Https传输数据。同事对敏感参数进行加密。客户端收到服务器返回的数据后应进行证书和域名的校验。
b 信息泄露。NSLog和 brachground Snapshot
NSLog在Release下应该销毁。采用宏处理
brackground Snapshot保存在Library/Caches/Snapshots目录下,如果有敏感信息Snapshot机制会造成信息泄露。在进入后台时加蒙层或者覆盖图片。
c IPC安全 URL Scheme检验和UIPasteboard安全
通过URL Scheme调用APP时应校验URL和传递回来的信息。
在进入后台时应该清空粘贴板上的内容
d 越狱和代理校验。
2 通过AFNetworking的SSL保证网络安全
http://www.jianshu.com/p/4102b817ff2f
a 获取到站点的公开二进制证书。
"openssl s_client -connect www.google.com:443 </dev/null 2>/dev/null | openssl x509 -outform DER > https.cer"
此时会在当前目录下保存google的公共证书,保存的名称是https
b 将获取到的证书放入工程中 勾选 copy items if needed 和 add to targets
c 校验证书
1 // 设定证书的校验策略 2 /* 3 typedef NS_ENUM(NSUInteger, AFSSLPinningMode) { 4 AFSSLPinningModeNone, //无条件的信任服务器端返回的证书 5 AFSSLPinningModePublicKey, //验证服务器端返回的证书与本地保存的证书的public key是否一致,一致的话进行请求。否则返回。 6 AFSSLPinningModeCertificate, //代表客户端会将服务器端返回的证书和本地保存的证书中的所有内容,包括PublicKey和证书部分,全部进行校验;如果正确,才继续进行 7 }; 8 */ 9 // 10 - (void)setCustomerSecurityPolicy:(AFHTTPSessionManager*)manager{ 11 //获取本地保存的公共证书的路径。 12 NSString *securityPath = [[NSBundle mainBundle] pathForResource:@"xxxx" ofType:@"cer"]; 13 14 NSData *securityData = [NSData dataWithContentsOfFile:securityPath]; 15 16 AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[NSSet setWithObject:securityData]]; 17 // 校验证书,不允许无效的证书 18 securityPolicy.allowInvalidCertificates = NO; 19 // 检验域名 20 securityPolicy.validatesDomainName = YES; 21 manager.securityPolicy = securityPolicy; 22 }
这种方式是AFNetworking自己实现的单方面的服务器证书验证,双向验证需要自己重写验证回调函数
3 类名混淆
http://www.jianshu.com/p/0d42e5c6361c
在编译时遇到权限拒绝是
cd 到shell脚步所在的目录。执行 chmod 755 xxxx.sh 赋予执行shell脚步的权限。
4 class-dump获取方法名列表
http://stevenygard.com/projects/class-dump/
class-dump的使用
http://www.jianshu.com/p/b37b19864fd5
以3.5版本为例,解压后得到
将archive后得到的ipa包改成zip格式,解压,然后显示包内容的对象项目名的app文件即exec格式
然后将class-dump拖入终端,得到正确的路径之后:
/Volumes/class-dump-3.5/class-dump -h app所在的路径 -o 导出文件的路径
4 加解密
http://www.jianshu.com/p/8424b47cc8a2
MD5
1 - (void)ddk_MD5EncryptWithString:(NSString *)string 2 { 3 // 将要加密的字符串转换成二进制数据 4 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 5 // 加密结果保存地址 6 unsigned char result[CC_MD5_DIGEST_LENGTH]; 7 // 加密 8 CC_MD5(data.bytes, (CC_LONG)data.length, result); 9 NSString *encry16 = @""; 10 // 获取16位的加密串 11 for (int i = 4; i < 12; i++) { 12 encry16 = [encry16 stringByAppendingString:[NSString stringWithFormat:@"%02x", result[i]]]; 13 } 14 15 NSLog(@"%@", [encry16 uppercaseString]); 16 17 NSString *encrypt = @""; 18 // 获取32位的加密串 19 for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { 20 encrypt = [encrypt stringByAppendingString:[NSString stringWithFormat:@"%02x", result[i]]]; 21 } 22 23 NSLog(@"%@", [encrypt uppercaseString]); 24 }
SHA256加密
1 /* 2 @string 要加密的字符串 3 @algorith 要使用的加密算法 4 @key 加密时的秘钥 5 HMAC_SHA256和SHA256的区别:“HMAC是密钥相关的哈希运算消息认证码(Hash-based Message Authentication Code),HMAC运算利用哈希算法,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。”HMAC是需要一个密钥的。所以,HMAC算法系列需要秘钥而SHA系列不需要秘钥 6 enum { 7 kCCHmacAlgSHA1, 8 kCCHmacAlgMD5, 9 kCCHmacAlgSHA256, 10 kCCHmacAlgSHA384, 11 kCCHmacAlgSHA512, 12 kCCHmacAlgSHA224 13 }; 14 */ 15 - (void)ddk_encryptHMACWithString:(NSString *)string algorithm:(CCHmacAlgorithm)algorith key:(NSString *)key 16 { 17 NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding]; 18 NSData *keyString = [string dataUsingEncoding:NSUTF8StringEncoding]; 19 // 加密后保存的位置 20 unsigned char buf[CC_SHA256_DIGEST_LENGTH]; 21 // 加密 22 CCHmac(algorith, keyData.bytes, [keyData length], keyString.bytes, [keyString length], buf); 23 // 将加密后的数据转化为字符串。 24 NSMutableString *mstr = [NSMutableString string]; 25 for (int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { 26 [mstr appendString:[NSString stringWithFormat:@"%02x", buf[i]]]; 27 } 28 NSLog(@"++++++++ %@", mstr); 29 }
Base64编码解码
1 /// base64 编码 2 - (NSString *)ddk_base64EncryptWithString:(NSString *)string 3 { 4 NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding]; 5 NSData *encryptData = [data base64EncodedDataWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]; 6 NSString *test = [[NSString alloc] initWithData:encryptData encoding:NSUTF8StringEncoding]; 7 NSLog(@"--- %@", test); 8 return test; 9 } 10 /// base64 解码 11 - (NSString *)ddk_base64DecryptWithString:(NSString *)string 12 { 13 NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters]; 14 NSString *tempStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 15 NSLog(@"----- %@", tempStr); 16 return tempStr; 17 }
AES加解密
进制转换
1 /** 2 * 将二进制数据转换成十六进制字符串 3 * 4 * @param data 二进制数据 5 * 6 * @return 十六进制字符串 7 */ 8 + (NSString *)data2Hex:(NSData *)data { 9 if (!data) { 10 return nil; 11 } 12 Byte *bytes = (Byte *)[data bytes]; 13 NSMutableString *str = [NSMutableString stringWithCapacity:data.length * 2]; 14 for (int i=0; i < data.length; i++){ 15 [str appendFormat:@"%02x", bytes[i]]; 16 } 17 return str; 18 } 19 /// 转成二进制。 20 + (NSData *)hex2data:(NSString *)hex { 21 NSMutableData *data = [NSMutableData dataWithCapacity:hex.length / 2]; 22 unsigned char whole_byte; 23 char byte_chars[3] = {'\0','\0','\0'}; 24 int i; 25 for (i=0; i < hex.length / 2; i++) { 26 byte_chars[0] = [hex characterAtIndex:i*2]; 27 byte_chars[1] = [hex characterAtIndex:i*2+1]; 28 whole_byte = strtol(byte_chars, NULL, 16); 29 [data appendBytes:&whole_byte length:1]; 30 } 31 return data; 32 }
1 // AES256加密 2 //CCCryptorStatus CCCrypt( 3 // CCOperation op, /* kCCEncrypt, etc. 进行加密还是解密 */ 4 // CCAlgorithm alg, /* kCCAlgorithmAES128, etc. 选择使用的算法 */ 5 // CCOptions options, /* kCCOptionPKCS7Padding, etc. 填充模式PKCS7(iPhone) */ 6 // const void *key, /* 密钥串 */ 7 // size_t keyLength, 8 // const void *iv, /* optional initialization vector. 工作模式。传nil为ECB(电子密码本)模式,传值(密钥偏移量,长度与密钥串长度相等。)为CBC(加密块链)模式。 */ 9 // const void *dataIn, /* optional per op and alg */ 10 // size_t dataInLength, 11 // void *dataOut, /* data RETURNED here */ 12 // size_t dataOutAvailable, /* The size of the dataOut buffer in bytes */ 13 // size_t *dataOutMoved /* 获取加密后的二进制数据的长度 */) 14 - (void)ddk_AESEncryptWithString:(NSString *)string alg:(CCAlgorithm)alg key:(NSString *)key iv:(NSString *)iv 15 { 16 NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding]; 17 NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding]; 18 NSData *strData = [string dataUsingEncoding:NSUTF8StringEncoding]; 19 size_t length = strData.length + kCCKeySizeAES128; 20 void *buf = malloc(length); 21 if (ivData.length != 0) { 22 return; 23 } 24 size_t decryptsize = 0; 25 CCCryptorStatus status = CCCrypt(kCCEncrypt, alg, kCCOptionPKCS7Padding, keyData.bytes, (size_t)keyData.length, ivData.bytes, strData.bytes, (size_t)strData.length, buf, length, &decryptsize); 26 if (status == kCCSuccess) { 27 NSData *re = [NSData dataWithBytes:buf length:decryptsize]; 28 free(buf); 29 NSLog(@"++++ %@", [ViewController data2Hex:re]); 30 NSLog(@"---- %@", [re base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]); 31 }else { 32 free(buf); 33 } 34 }
1 // AES256解密 2 - (void)ddk_AESDecryptWithString:(NSString *)string alg:(CCAlgorithm)alg key:(NSString *)key iv:(NSString *)iv 3 { 4 NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding]; 5 NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding]; 6 NSData *strData = [string dataUsingEncoding:NSUTF8StringEncoding]; 7 strData = [[NSData alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters]; 8 size_t length = strData.length + kCCBlockSizeAES128; 9 void *buf = malloc(length); 10 if (ivData.length != 0) { 11 return; 12 } 13 size_t decryptsize = 0; 14 CCCryptorStatus status = CCCrypt(kCCDecrypt, alg, kCCOptionPKCS7Padding, keyData.bytes, (size_t)keyData.length, ivData.bytes, strData.bytes, (size_t)strData.length, buf, length, &decryptsize); 15 if (status == kCCSuccess) { 16 NSData *re = [NSData dataWithBytes:buf length:decryptsize]; 17 free(buf); 18 // NSLog(@"++++ %@", [ViewController data2Hex:re]); 19 NSString * mm = [[NSString alloc] initWithData:re encoding:NSUTF8StringEncoding]; 20 NSLog(@"+++++ %@", mm); 21 NSLog(@"---- %@", [re base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn]); 22 }else { 23 free(buf); 24 } 25 26 }