4 |
5 | @interface NSString (Hash)
6 |
7 | #pragma mark - 散列函数
8 | /**
9 | * 计算MD5散列结果
10 | *
11 | * 终端测试命令:
12 | * @code
13 | * md5 -s "string"
14 | * @endcode
15 | *
16 | * 提示:随着 MD5 碰撞生成器的出现,MD5 算法不应被用于任何软件完整性检查或代码签名的用途。
17 | *
18 | * @return 32个字符的MD5散列字符串
19 | */
20 | - (NSString *)md5String;
21 |
22 | /**
23 | * 计算SHA1散列结果
24 | *
25 | * 终端测试命令:
26 | * @code
27 | * echo -n "string" | openssl sha -sha1
28 | * @endcode
29 | *
30 | * @return 40个字符的SHA1散列字符串
31 | */
32 | - (NSString *)sha1String;
33 |
34 | /**
35 | * 计算SHA256散列结果
36 | *
37 | * 终端测试命令:
38 | * @code
39 | * echo -n "string" | openssl sha -sha256
40 | * @endcode
41 | *
42 | * @return 64个字符的SHA256散列字符串
43 | */
44 | - (NSString *)sha256String;
45 |
46 | /**
47 | * 计算SHA 512散列结果
48 | *
49 | * 终端测试命令:
50 | * @code
51 | * echo -n "string" | openssl sha -sha512
52 | * @endcode
53 | *
54 | * @return 128个字符的SHA 512散列字符串
55 | */
56 | - (NSString *)sha512String;
57 |
58 | #pragma mark - HMAC 散列函数
59 | /**
60 | * 计算HMAC MD5散列结果
61 | *
62 | * 终端测试命令:
63 | * @code
64 | * echo -n "string" | openssl dgst -md5 -hmac "key"
65 | * @endcode
66 | *
67 | * @return 32个字符的HMAC MD5散列字符串
68 | */
69 | - (NSString *)hmacMD5StringWithKey:(NSString *)key;
70 |
71 | /**
72 | * 计算HMAC SHA1散列结果
73 | *
74 | * 终端测试命令:
75 | * @code
76 | * echo -n "string" | openssl sha -sha1 -hmac "key"
77 | * @endcode
78 | *
79 | * @return 40个字符的HMAC SHA1散列字符串
80 | */
81 | - (NSString *)hmacSHA1StringWithKey:(NSString *)key;
82 |
83 | /**
84 | * 计算HMAC SHA256散列结果
85 | *
86 | * 终端测试命令:
87 | * @code
88 | * echo -n "string" | openssl sha -sha256 -hmac "key"
89 | * @endcode
90 | *
91 | * @return 64个字符的HMAC SHA256散列字符串
92 | */
93 | - (NSString *)hmacSHA256StringWithKey:(NSString *)key;
94 |
95 | /**
96 | * 计算HMAC SHA512散列结果
97 | *
98 | * 终端测试命令:
99 | * @code
100 | * echo -n "string" | openssl sha -sha512 -hmac "key"
101 | * @endcode
102 | *
103 | * @return 128个字符的HMAC SHA512散列字符串
104 | */
105 | - (NSString *)hmacSHA512StringWithKey:(NSString *)key;
106 |
107 | #pragma mark - 文件散列函数
108 |
109 | /**
110 | * 计算文件的MD5散列结果
111 | *
112 | * 终端测试命令:
113 | * @code
114 | * md5 file.dat
115 | * @endcode
116 | *
117 | * @return 32个字符的MD5散列字符串
118 | */
119 | - (NSString *)fileMD5Hash;
120 |
121 | /**
122 | * 计算文件的SHA1散列结果
123 | *
124 | * 终端测试命令:
125 | * @code
126 | * openssl sha -sha1 file.dat
127 | * @endcode
128 | *
129 | * @return 40个字符的SHA1散列字符串
130 | */
131 | - (NSString *)fileSHA1Hash;
132 |
133 | /**
134 | * 计算文件的SHA256散列结果
135 | *
136 | * 终端测试命令:
137 | * @code
138 | * openssl sha -sha256 file.dat
139 | * @endcode
140 | *
141 | * @return 64个字符的SHA256散列字符串
142 | */
143 | - (NSString *)fileSHA256Hash;
144 |
145 | /**
146 | * 计算文件的SHA512散列结果
147 | *
148 | * 终端测试命令:
149 | * @code
150 | * openssl sha -sha512 file.dat
151 | * @endcode
152 | *
153 | * @return 128个字符的SHA512散列字符串
154 | */
155 | - (NSString *)fileSHA512Hash;
156 |
157 | @end
158 |
--------------------------------------------------------------------------------
/08-动态密码(时间戳密码)/08-动态密码(时间戳密码)/Security/NSString+Hash.h:
--------------------------------------------------------------------------------
1 | // 01-数据安全
2 |
3 | #import
4 |
5 | @interface NSString (Hash)
6 |
7 | #pragma mark - 散列函数
8 | /**
9 | * 计算MD5散列结果
10 | *
11 | * 终端测试命令:
12 | * @code
13 | * md5 -s "string"
14 | * @endcode
15 | *
16 | * 提示:随着 MD5 碰撞生成器的出现,MD5 算法不应被用于任何软件完整性检查或代码签名的用途。
17 | *
18 | * @return 32个字符的MD5散列字符串
19 | */
20 | - (NSString *)md5String;
21 |
22 | /**
23 | * 计算SHA1散列结果
24 | *
25 | * 终端测试命令:
26 | * @code
27 | * echo -n "string" | openssl sha -sha1
28 | * @endcode
29 | *
30 | * @return 40个字符的SHA1散列字符串
31 | */
32 | - (NSString *)sha1String;
33 |
34 | /**
35 | * 计算SHA256散列结果
36 | *
37 | * 终端测试命令:
38 | * @code
39 | * echo -n "string" | openssl sha -sha256
40 | * @endcode
41 | *
42 | * @return 64个字符的SHA256散列字符串
43 | */
44 | - (NSString *)sha256String;
45 |
46 | /**
47 | * 计算SHA 512散列结果
48 | *
49 | * 终端测试命令:
50 | * @code
51 | * echo -n "string" | openssl sha -sha512
52 | * @endcode
53 | *
54 | * @return 128个字符的SHA 512散列字符串
55 | */
56 | - (NSString *)sha512String;
57 |
58 | #pragma mark - HMAC 散列函数
59 | /**
60 | * 计算HMAC MD5散列结果
61 | *
62 | * 终端测试命令:
63 | * @code
64 | * echo -n "string" | openssl dgst -md5 -hmac "key"
65 | * @endcode
66 | *
67 | * @return 32个字符的HMAC MD5散列字符串
68 | */
69 | - (NSString *)hmacMD5StringWithKey:(NSString *)key;
70 |
71 | /**
72 | * 计算HMAC SHA1散列结果
73 | *
74 | * 终端测试命令:
75 | * @code
76 | * echo -n "string" | openssl sha -sha1 -hmac "key"
77 | * @endcode
78 | *
79 | * @return 40个字符的HMAC SHA1散列字符串
80 | */
81 | - (NSString *)hmacSHA1StringWithKey:(NSString *)key;
82 |
83 | /**
84 | * 计算HMAC SHA256散列结果
85 | *
86 | * 终端测试命令:
87 | * @code
88 | * echo -n "string" | openssl sha -sha256 -hmac "key"
89 | * @endcode
90 | *
91 | * @return 64个字符的HMAC SHA256散列字符串
92 | */
93 | - (NSString *)hmacSHA256StringWithKey:(NSString *)key;
94 |
95 | /**
96 | * 计算HMAC SHA512散列结果
97 | *
98 | * 终端测试命令:
99 | * @code
100 | * echo -n "string" | openssl sha -sha512 -hmac "key"
101 | * @endcode
102 | *
103 | * @return 128个字符的HMAC SHA512散列字符串
104 | */
105 | - (NSString *)hmacSHA512StringWithKey:(NSString *)key;
106 |
107 | #pragma mark - 文件散列函数
108 |
109 | /**
110 | * 计算文件的MD5散列结果
111 | *
112 | * 终端测试命令:
113 | * @code
114 | * md5 file.dat
115 | * @endcode
116 | *
117 | * @return 32个字符的MD5散列字符串
118 | */
119 | - (NSString *)fileMD5Hash;
120 |
121 | /**
122 | * 计算文件的SHA1散列结果
123 | *
124 | * 终端测试命令:
125 | * @code
126 | * openssl sha -sha1 file.dat
127 | * @endcode
128 | *
129 | * @return 40个字符的SHA1散列字符串
130 | */
131 | - (NSString *)fileSHA1Hash;
132 |
133 | /**
134 | * 计算文件的SHA256散列结果
135 | *
136 | * 终端测试命令:
137 | * @code
138 | * openssl sha -sha256 file.dat
139 | * @endcode
140 | *
141 | * @return 64个字符的SHA256散列字符串
142 | */
143 | - (NSString *)fileSHA256Hash;
144 |
145 | /**
146 | * 计算文件的SHA512散列结果
147 | *
148 | * 终端测试命令:
149 | * @code
150 | * openssl sha -sha512 file.dat
151 | * @endcode
152 | *
153 | * @return 128个字符的SHA512散列字符串
154 | */
155 | - (NSString *)fileSHA512Hash;
156 |
157 | @end
158 |
--------------------------------------------------------------------------------
/05-POST加密(登录业务逻辑)/04-POST加密(保存本地数据)/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // 04-POST加密(保存本地数据)
4 | //
5 | // Created by 王鹏飞 on 16/2/16.
6 | // Copyright © 2016年 王鹏飞. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | #define kUserNameKey @"kUserNameKey"
12 | #define kPasswordKey @"kPasswordKey"
13 |
14 | @interface AppDelegate ()
15 |
16 | @end
17 |
18 | @implementation AppDelegate
19 |
20 |
21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
22 |
23 | // 1. 注册登录成功的通知观察者
24 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loginSuccess) name:@"loginSuccess" object:nil];
25 |
26 | // 2. 注册登录成功的通知观察者
27 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutSuccess) name:@"logoutSuccess" object:nil];
28 |
29 | // 每次app打开后,应该展示给用户哪个界面
30 | // 3. 利用偏好设置中用户保存的信息来判断用户的登录状态
31 | NSString *userName = [[NSUserDefaults standardUserDefaults] objectForKey:kUserNameKey];
32 |
33 | NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:kPasswordKey];
34 |
35 | if (userName && password) {
36 | // 显示app 主界面
37 | [self loginSuccess];
38 | } else {
39 |
40 | [self logoutSuccess];
41 | }
42 |
43 | return YES;
44 | }
45 |
46 | // 登录成功
47 | - (void)loginSuccess {
48 |
49 | NSLog(@"登录成功!");
50 |
51 | // 获取主界面
52 | UIStoryboard *mainSb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
53 |
54 | // 切换控制器
55 | self.window.rootViewController = mainSb.instantiateInitialViewController;
56 | }
57 |
58 | // 注销成功
59 | - (void)logoutSuccess {
60 | NSLog(@"注销成功!");
61 |
62 | // 获取登录界面
63 | UIStoryboard *loginSb = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
64 |
65 | // 切换控制器
66 | self.window.rootViewController = loginSb.instantiateInitialViewController;
67 | }
68 |
69 | - (void)applicationWillResignActive:(UIApplication *)application {
70 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
71 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
72 | }
73 |
74 | - (void)applicationDidEnterBackground:(UIApplication *)application {
75 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
76 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
77 | }
78 |
79 | - (void)applicationWillEnterForeground:(UIApplication *)application {
80 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
81 | }
82 |
83 | - (void)applicationDidBecomeActive:(UIApplication *)application {
84 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
85 | }
86 |
87 | - (void)applicationWillTerminate:(UIApplication *)application {
88 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
89 | }
90 |
91 | @end
92 |
--------------------------------------------------------------------------------
/06-POST加密(Token值)/04-POST加密(保存本地数据)/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.m
3 | // 04-POST加密(保存本地数据)
4 | //
5 | // Created by 王鹏飞 on 16/2/16.
6 | // Copyright © 2016年 王鹏飞. All rights reserved.
7 | //
8 |
9 | #import "AppDelegate.h"
10 |
11 | #define kUserNameKey @"kUserNameKey"
12 | #define kPasswordKey @"kPasswordKey"
13 |
14 | @interface AppDelegate ()
15 |
16 | @end
17 |
18 | @implementation AppDelegate
19 |
20 |
21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
22 |
23 | // 1. 注册登录成功的通知观察者
24 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loginSuccess) name:@"loginSuccess" object:nil];
25 |
26 | // 2. 注册登录成功的通知观察者
27 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(logoutSuccess) name:@"logoutSuccess" object:nil];
28 |
29 | // 每次app打开后,应该展示给用户哪个界面
30 | // 3. 利用偏好设置中用户保存的信息来判断用户的登录状态
31 | NSString *userName = [[NSUserDefaults standardUserDefaults] objectForKey:kUserNameKey];
32 |
33 | NSString *password = [[NSUserDefaults standardUserDefaults] objectForKey:kPasswordKey];
34 |
35 | if (userName && password) {
36 | // 显示app 主界面
37 | [self loginSuccess];
38 | } else {
39 |
40 | [self logoutSuccess];
41 | }
42 |
43 | return YES;
44 | }
45 |
46 | // 登录成功
47 | - (void)loginSuccess {
48 |
49 | NSLog(@"登录成功!");
50 |
51 | // 获取主界面
52 | UIStoryboard *mainSb = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
53 |
54 | // 切换控制器
55 | self.window.rootViewController = mainSb.instantiateInitialViewController;
56 | }
57 |
58 | // 注销成功
59 | - (void)logoutSuccess {
60 | NSLog(@"注销成功!");
61 |
62 | // 获取登录界面
63 | UIStoryboard *loginSb = [UIStoryboard storyboardWithName:@"Login" bundle:nil];
64 |
65 | // 切换控制器
66 | self.window.rootViewController = loginSb.instantiateInitialViewController;
67 | }
68 |
69 | - (void)applicationWillResignActive:(UIApplication *)application {
70 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
71 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
72 | }
73 |
74 | - (void)applicationDidEnterBackground:(UIApplication *)application {
75 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
76 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
77 | }
78 |
79 | - (void)applicationWillEnterForeground:(UIApplication *)application {
80 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
81 | }
82 |
83 | - (void)applicationDidBecomeActive:(UIApplication *)application {
84 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
85 | }
86 |
87 | - (void)applicationWillTerminate:(UIApplication *)application {
88 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
89 | }
90 |
91 | @end
92 |
--------------------------------------------------------------------------------
/04-POST加密(保存本地数据)/04-POST加密(保存本地数据)/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // 04-POST加密(保存本地数据)
4 | //
5 | // Created by 王鹏飞 on 16/2/16.
6 | // Copyright © 2016年 王鹏飞. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 |
11 | #define kUserNameKey @"kUserNameKey"
12 | #define kPasswordKey @"kPasswordKey"
13 |
14 | @interface ViewController ()
15 |
16 | @property (weak, nonatomic) IBOutlet UITextField *userName;
17 | @property (weak, nonatomic) IBOutlet UITextField *password;
18 | @end
19 |
20 | @implementation ViewController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 |
25 | /*
26 | 登录的业务逻辑:
27 | 1> 首次登录,进入登录界面
28 | 2> 首次登录成功,则第二次直接进入app主界面
29 | 3> 首次登录失败,则第二次进入登录界面
30 | 4> 进行注销操作后,清除本地信息,进入登录界面
31 | */
32 | }
33 |
34 | - (IBAction)btnLoginDidClick:(UIButton *)sender {
35 |
36 | // 如果两个文本框均不为空,则进行登录操作
37 | if (self.userName.text.length && self.password.text.length) {
38 |
39 | // 1. 创建请求
40 | NSString *urlString = @"http://localhost/login/login.php";
41 |
42 | NSURL *url = [NSURL URLWithString:urlString];
43 |
44 | // POST 请求需要手动设置请求方法,因此为可变请求
45 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
46 |
47 | // 设置请求方法
48 | request.HTTPMethod = @"POST";
49 |
50 | // 设置请求参数
51 | NSString *body = [NSString stringWithFormat:@"username=%@&password=%@", self.userName.text, self.password.text];
52 |
53 | // 将字符串转为二进制数据
54 | NSData *bodyData = [body dataUsingEncoding:NSUTF8StringEncoding];
55 |
56 | // 设置请求主体(二进制数据)
57 | request.HTTPBody = bodyData;
58 |
59 | // 2. 发送请求
60 | [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
61 |
62 | // 打印请求结果
63 | NSLog(@"data:%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
64 |
65 | // 判断是否登录成功
66 | if (data && !error) {
67 | NSLog(@"网络请求成功!");
68 |
69 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
70 |
71 | if (dict[@"userID"]) {
72 | [self saveLocalUserInfo];
73 | }
74 | } else {
75 | NSLog(@"网络请求失败!");
76 | }
77 |
78 | }] resume];
79 | } else {
80 | NSLog(@"用户名或密码不能为空!");
81 | }
82 | }
83 |
84 | // 抽取出读取数据的方法
85 | - (void)readLocalUserInfo {
86 |
87 | // 1. 实例化偏好设置对象
88 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
89 |
90 | // 2. 取出数据进行赋值
91 | self.userName.text = [userDefaults objectForKey:kUserNameKey];
92 |
93 | // 此时读取的是加密后的密码
94 | self.password.text = [userDefaults objectForKey:kPasswordKey];
95 | }
96 |
97 | // 抽取出存储数据的方法
98 | - (void)saveLocalUserInfo {
99 |
100 | // 1. 实例化偏好设置对象
101 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
102 |
103 | // 2. 存储用户名
104 | [userDefaults setObject:self.userName.text forKey:kUserNameKey];
105 |
106 | // 3. 将密码进行base64 加密
107 | // 将密码转化为二进制数据
108 | NSData *data = [self.password.text dataUsingEncoding:NSUTF8StringEncoding];
109 |
110 | // 进行加密
111 | NSString *base64Str = [data base64EncodedStringWithOptions:0];
112 |
113 | // 4. 将加密后的密码存储到偏好设置
114 | [userDefaults setObject:base64Str forKey:kPasswordKey];
115 |
116 | // 5. 为了保证线程的一致性,无论是存储还是读取数据,都要进行同步
117 | [userDefaults synchronize];
118 | }
119 |
120 | @end
121 |
--------------------------------------------------------------------------------
/05-POST加密(登录业务逻辑)/04-POST加密(保存本地数据)/WPFTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WPFTableViewController.m
3 | // 04-POST加密(保存本地数据)
4 | //
5 | // Created by 王鹏飞 on 16/2/16.
6 | // Copyright © 2016年 王鹏飞. All rights reserved.
7 | //
8 |
9 | #import "WPFTableViewController.h"
10 |
11 | #define kUserNameKey @"kUserNameKey"
12 | #define kPasswordKey @"kPasswordKey"
13 |
14 | @interface WPFTableViewController ()
15 |
16 | @end
17 |
18 | @implementation WPFTableViewController
19 |
20 | - (IBAction)btnLogoutDidClick:(UIBarButtonItem *)sender {
21 |
22 | // 1. 清除本地信息
23 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kUserNameKey];
24 |
25 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kPasswordKey];
26 |
27 | // 同步信息
28 | [[NSUserDefaults standardUserDefaults] synchronize];
29 |
30 | // 2. 发送信息,切换控制器
31 | [[NSNotificationCenter defaultCenter] postNotificationName:@"logoutSuccess" object:nil];
32 |
33 | }
34 |
35 | - (void)viewDidLoad {
36 | [super viewDidLoad];
37 |
38 |
39 | }
40 |
41 | - (void)didReceiveMemoryWarning {
42 | [super didReceiveMemoryWarning];
43 | // Dispose of any resources that can be recreated.
44 | }
45 |
46 | #pragma mark - Table view data source
47 |
48 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
49 | #warning Incomplete implementation, return the number of sections
50 | return 0;
51 | }
52 |
53 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
54 | #warning Incomplete implementation, return the number of rows
55 | return 0;
56 | }
57 |
58 | /*
59 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
60 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<#@"reuseIdentifier"#> forIndexPath:indexPath];
61 |
62 | // Configure the cell...
63 |
64 | return cell;
65 | }
66 | */
67 |
68 | /*
69 | // Override to support conditional editing of the table view.
70 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
71 | // Return NO if you do not want the specified item to be editable.
72 | return YES;
73 | }
74 | */
75 |
76 | /*
77 | // Override to support editing the table view.
78 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
79 | if (editingStyle == UITableViewCellEditingStyleDelete) {
80 | // Delete the row from the data source
81 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
82 | } else if (editingStyle == UITableViewCellEditingStyleInsert) {
83 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
84 | }
85 | }
86 | */
87 |
88 | /*
89 | // Override to support rearranging the table view.
90 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
91 | }
92 | */
93 |
94 | /*
95 | // Override to support conditional rearranging of the table view.
96 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
97 | // Return NO if you do not want the item to be re-orderable.
98 | return YES;
99 | }
100 | */
101 |
102 | /*
103 | #pragma mark - Navigation
104 |
105 | // In a storyboard-based application, you will often want to do a little preparation before navigation
106 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
107 | // Get the new view controller using [segue destinationViewController].
108 | // Pass the selected object to the new view controller.
109 | }
110 | */
111 |
112 | @end
113 |
--------------------------------------------------------------------------------
/07-MD5加密/07-MD5加密.xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/07-MD5加密.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/03-base64加密/03-base64加密.xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/03-base64加密.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/10-钥匙串访问/10-钥匙串访问.xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/10-钥匙串访问.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/05-POST加密(登录业务逻辑)/04-POST加密(保存本地数据)/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // 04-POST加密(保存本地数据)
4 | //
5 | // Created by 王鹏飞 on 16/2/16.
6 | // Copyright © 2016年 王鹏飞. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 |
11 | #define kUserNameKey @"kUserNameKey"
12 | #define kPasswordKey @"kPasswordKey"
13 |
14 | @interface ViewController ()
15 |
16 | @property (weak, nonatomic) IBOutlet UITextField *userName;
17 | @property (weak, nonatomic) IBOutlet UITextField *password;
18 | @end
19 |
20 | @implementation ViewController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 |
25 | /*
26 | 登录的业务逻辑:
27 | 1> 首次登录,进入登录界面
28 | 2> 首次登录成功,则第二次直接进入app主界面
29 | 3> 首次登录失败,则第二次进入登录界面
30 | 4> 进行注销操作后,清除本地信息,进入登录界面
31 | */
32 | }
33 |
34 | - (IBAction)btnLoginDidClick:(UIButton *)sender {
35 |
36 | // 如果两个文本框均不为空,则进行登录操作
37 | if (self.userName.text.length && self.password.text.length) {
38 |
39 | // 1. 创建请求
40 | NSString *urlString = @"http://localhost/login/login.php";
41 |
42 | NSURL *url = [NSURL URLWithString:urlString];
43 |
44 | // POST 请求需要手动设置请求方法,因此为可变请求
45 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
46 |
47 | // 设置请求方法
48 | request.HTTPMethod = @"POST";
49 |
50 | // 设置请求参数
51 | NSString *body = [NSString stringWithFormat:@"username=%@&password=%@", self.userName.text, self.password.text];
52 |
53 | // 将字符串转为二进制数据
54 | NSData *bodyData = [body dataUsingEncoding:NSUTF8StringEncoding];
55 |
56 | // 设置请求主体(二进制数据)
57 | request.HTTPBody = bodyData;
58 |
59 | // 2. 发送请求
60 | [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
61 |
62 | // 打印请求结果
63 | NSLog(@"data:%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
64 |
65 | // 判断是否登录成功
66 | if (data && !error) {
67 | NSLog(@"网络请求成功!");
68 |
69 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
70 |
71 | if (dict[@"userId"]) {
72 | [self saveLocalUserInfo];
73 |
74 | // 跳转到app主界面,在主线程中发送通知
75 | dispatch_async(dispatch_get_main_queue(), ^{
76 | [[NSNotificationCenter defaultCenter] postNotificationName:@"loginSuccess" object:nil];
77 | });
78 | }
79 | } else {
80 | NSLog(@"网络请求失败!");
81 | }
82 |
83 | }] resume];
84 | } else {
85 | NSLog(@"用户名或密码不能为空!");
86 | }
87 | }
88 |
89 | // 抽取出读取数据的方法
90 | - (void)readLocalUserInfo {
91 |
92 | // 1. 实例化偏好设置对象
93 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
94 |
95 | // 2. 取出数据进行赋值
96 | self.userName.text = [userDefaults objectForKey:kUserNameKey];
97 |
98 | // 此时读取的是加密后的密码
99 | self.password.text = [userDefaults objectForKey:kPasswordKey];
100 | }
101 |
102 | // 抽取出存储数据的方法
103 | - (void)saveLocalUserInfo {
104 |
105 | // 1. 实例化偏好设置对象
106 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
107 |
108 | // 2. 存储用户名
109 | [userDefaults setObject:self.userName.text forKey:kUserNameKey];
110 |
111 | // 3. 将密码进行base64 加密
112 | // 将密码转化为二进制数据
113 | NSData *data = [self.password.text dataUsingEncoding:NSUTF8StringEncoding];
114 |
115 | // 进行加密
116 | NSString *base64Str = [data base64EncodedStringWithOptions:0];
117 |
118 | // 4. 将加密后的密码存储到偏好设置
119 | [userDefaults setObject:base64Str forKey:kPasswordKey];
120 |
121 | // 5. 为了保证线程的一致性,无论是存储还是读取数据,都要进行同步
122 | [userDefaults synchronize];
123 | NSLog(@"saveLocalUserInfo");
124 | }
125 |
126 | @end
127 |
--------------------------------------------------------------------------------
/06-POST加密(Token值)/04-POST加密(保存本地数据)/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.m
3 | // 04-POST加密(保存本地数据)
4 | //
5 | // Created by 王鹏飞 on 16/2/16.
6 | // Copyright © 2016年 王鹏飞. All rights reserved.
7 | //
8 |
9 | #import "ViewController.h"
10 |
11 | #define kUserNameKey @"kUserNameKey"
12 | #define kPasswordKey @"kPasswordKey"
13 |
14 | @interface ViewController ()
15 |
16 | @property (weak, nonatomic) IBOutlet UITextField *userName;
17 | @property (weak, nonatomic) IBOutlet UITextField *password;
18 | @end
19 |
20 | @implementation ViewController
21 |
22 | - (void)viewDidLoad {
23 | [super viewDidLoad];
24 |
25 | /*
26 | 登录的业务逻辑:
27 | 1> 首次登录,进入登录界面
28 | 2> 首次登录成功,则第二次直接进入app主界面
29 | 3> 首次登录失败,则第二次进入登录界面
30 | 4> 进行注销操作后,清除本地信息,进入登录界面
31 | */
32 | }
33 |
34 | - (IBAction)btnLoginDidClick:(UIButton *)sender {
35 |
36 | // 如果两个文本框均不为空,则进行登录操作
37 | if (self.userName.text.length && self.password.text.length) {
38 |
39 | // 1. 创建请求
40 | NSString *urlString = @"http://localhost/login/login.php";
41 |
42 | NSURL *url = [NSURL URLWithString:urlString];
43 |
44 | // POST 请求需要手动设置请求方法,因此为可变请求
45 | NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
46 |
47 | // 设置请求方法
48 | request.HTTPMethod = @"POST";
49 |
50 | // 设置请求参数
51 | NSString *body = [NSString stringWithFormat:@"username=%@&password=%@", self.userName.text, self.password.text];
52 |
53 | // 将字符串转为二进制数据
54 | NSData *bodyData = [body dataUsingEncoding:NSUTF8StringEncoding];
55 |
56 | // 设置请求主体(二进制数据)
57 | request.HTTPBody = bodyData;
58 |
59 | // 2. 发送请求
60 | [[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
61 |
62 | // 打印请求结果
63 | NSLog(@"data:%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
64 |
65 | // 判断是否登录成功
66 | if (data && !error) {
67 | NSLog(@"网络请求成功!");
68 |
69 | NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
70 |
71 | if (dict[@"userId"]) {
72 | [self saveLocalUserInfo];
73 |
74 | // 跳转到app主界面,在主线程中发送通知
75 | dispatch_async(dispatch_get_main_queue(), ^{
76 | [[NSNotificationCenter defaultCenter] postNotificationName:@"loginSuccess" object:nil];
77 | });
78 | }
79 | } else {
80 | NSLog(@"网络请求失败!");
81 | }
82 |
83 | }] resume];
84 | } else {
85 | NSLog(@"用户名或密码不能为空!");
86 | }
87 | }
88 |
89 | // 抽取出读取数据的方法
90 | - (void)readLocalUserInfo {
91 |
92 | // 1. 实例化偏好设置对象
93 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
94 |
95 | // 2. 取出数据进行赋值
96 | self.userName.text = [userDefaults objectForKey:kUserNameKey];
97 |
98 | // 此时读取的是加密后的密码
99 | self.password.text = [userDefaults objectForKey:kPasswordKey];
100 | }
101 |
102 | // 抽取出存储数据的方法
103 | - (void)saveLocalUserInfo {
104 |
105 | // 1. 实例化偏好设置对象
106 | NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
107 |
108 | // 2. 存储用户名
109 | [userDefaults setObject:self.userName.text forKey:kUserNameKey];
110 |
111 | // 3. 将密码进行base64 加密
112 | // 将密码转化为二进制数据
113 | NSData *data = [self.password.text dataUsingEncoding:NSUTF8StringEncoding];
114 |
115 | // 进行加密
116 | NSString *base64Str = [data base64EncodedStringWithOptions:0];
117 |
118 | // 4. 将加密后的密码存储到偏好设置
119 | [userDefaults setObject:base64Str forKey:kPasswordKey];
120 |
121 | // 5. 为了保证线程的一致性,无论是存储还是读取数据,都要进行同步
122 | [userDefaults synchronize];
123 | NSLog(@"saveLocalUserInfo");
124 | }
125 |
126 | @end
127 |
--------------------------------------------------------------------------------
/01-GET请求(附带参数)/01-GET请求(附带参数).xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/01-GET请求(附带参数).xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/02-POST请求(附带参数)/02-POST请求(附带参数).xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/02-POST请求(附带参数).xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/10-钥匙串访问/10-钥匙串访问/SSKeychain/SSKeychainQuery.h:
--------------------------------------------------------------------------------
1 | //
2 | // SSKeychainQuery.h
3 | // SSKeychain
4 | //
5 | // Created by Caleb Davenport on 3/19/13.
6 | // Copyright (c) 2013-2014 Sam Soffes. All rights reserved.
7 | //
8 |
9 | #import
10 | #import
11 |
12 | #if __IPHONE_7_0 || __MAC_10_9
13 | // Keychain synchronization available at compile time
14 | #define SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE 1
15 | #endif
16 |
17 | #ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE
18 | typedef NS_ENUM(NSUInteger, SSKeychainQuerySynchronizationMode) {
19 | SSKeychainQuerySynchronizationModeAny,
20 | SSKeychainQuerySynchronizationModeNo,
21 | SSKeychainQuerySynchronizationModeYes
22 | };
23 | #endif
24 |
25 | /**
26 | Simple interface for querying or modifying keychain items.
27 | */
28 | @interface SSKeychainQuery : NSObject
29 |
30 | /** kSecAttrAccount */
31 | @property (nonatomic, copy) NSString *account;
32 |
33 | /** kSecAttrService */
34 | @property (nonatomic, copy) NSString *service;
35 |
36 | /** kSecAttrLabel */
37 | @property (nonatomic, copy) NSString *label;
38 |
39 | #if __IPHONE_3_0 && TARGET_OS_IPHONE
40 | /** kSecAttrAccessGroup (only used on iOS) */
41 | @property (nonatomic, copy) NSString *accessGroup;
42 | #endif
43 |
44 | #ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE
45 | /** kSecAttrSynchronizable */
46 | @property (nonatomic) SSKeychainQuerySynchronizationMode synchronizationMode;
47 | #endif
48 |
49 | /** Root storage for password information */
50 | @property (nonatomic, copy) NSData *passwordData;
51 |
52 | /**
53 | This property automatically transitions between an object and the value of
54 | `passwordData` using NSKeyedArchiver and NSKeyedUnarchiver.
55 | */
56 | @property (nonatomic, copy) id passwordObject;
57 |
58 | /**
59 | Convenience accessor for setting and getting a password string. Passes through
60 | to `passwordData` using UTF-8 string encoding.
61 | */
62 | @property (nonatomic, copy) NSString *password;
63 |
64 |
65 | ///------------------------
66 | /// @name Saving & Deleting
67 | ///------------------------
68 |
69 | /**
70 | Save the receiver's attributes as a keychain item. Existing items with the
71 | given account, service, and access group will first be deleted.
72 |
73 | @param error Populated should an error occur.
74 |
75 | @return `YES` if saving was successful, `NO` otherwise.
76 | */
77 | - (BOOL)save:(NSError **)error;
78 |
79 | /**
80 | Delete keychain items that match the given account, service, and access group.
81 |
82 | @param error Populated should an error occur.
83 |
84 | @return `YES` if saving was successful, `NO` otherwise.
85 | */
86 | - (BOOL)deleteItem:(NSError **)error;
87 |
88 |
89 | ///---------------
90 | /// @name Fetching
91 | ///---------------
92 |
93 | /**
94 | Fetch all keychain items that match the given account, service, and access
95 | group. The values of `password` and `passwordData` are ignored when fetching.
96 |
97 | @param error Populated should an error occur.
98 |
99 | @return An array of dictionaries that represent all matching keychain items or
100 | `nil` should an error occur.
101 | The order of the items is not determined.
102 | */
103 | - (NSArray *)fetchAll:(NSError **)error;
104 |
105 | /**
106 | Fetch the keychain item that matches the given account, service, and access
107 | group. The `password` and `passwordData` properties will be populated unless
108 | an error occurs. The values of `password` and `passwordData` are ignored when
109 | fetching.
110 |
111 | @param error Populated should an error occur.
112 |
113 | @return `YES` if fetching was successful, `NO` otherwise.
114 | */
115 | - (BOOL)fetch:(NSError **)error;
116 |
117 |
118 | ///-----------------------------
119 | /// @name Synchronization Status
120 | ///-----------------------------
121 |
122 | #ifdef SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE
123 | /**
124 | Returns a boolean indicating if keychain synchronization is available on the device at runtime. The #define
125 | SSKEYCHAIN_SYNCHRONIZATION_AVAILABLE is only for compile time. If you are checking for the presence of synchronization,
126 | you should use this method.
127 |
128 | @return A value indicating if keychain synchronization is available
129 | */
130 | + (BOOL)isSynchronizationAvailable;
131 | #endif
132 |
133 | @end
134 |
--------------------------------------------------------------------------------
/05-POST加密(登录业务逻辑)/04-POST加密(保存本地数据)/Main.storyboard:
--------------------------------------------------------------------------------
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 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/06-POST加密(Token值)/04-POST加密(保存本地数据)/Main.storyboard:
--------------------------------------------------------------------------------
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 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/04-POST加密(保存本地数据)/04-POST加密(保存本地数据).xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/04-POST加密(保存本地数据).xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/05-POST加密(登录业务逻辑)/04-POST加密(保存本地数据).xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/04-POST加密(保存本地数据).xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/06-POST加密(Token值)/04-POST加密(保存本地数据).xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/04-POST加密(保存本地数据).xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/08-动态密码(时间戳密码)/08-动态密码(时间戳密码).xcodeproj/xcuserdata/wangpengfei.xcuserdatad/xcschemes/08-动态密码(时间戳密码).xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/06-POST加密(Token值)/04-POST加密(保存本地数据)/WPFTableViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | // WPFTableViewController.m
3 | // 04-POST加密(保存本地数据)
4 | //
5 | // Created by 王鹏飞 on 16/2/16.
6 | // Copyright © 2016年 王鹏飞. All rights reserved.
7 | //
8 |
9 | #import "WPFTableViewController.h"
10 |
11 | #define kUserNameKey @"kUserNameKey"
12 | #define kPasswordKey @"kPasswordKey"
13 |
14 | @interface WPFTableViewController ()
15 |
16 | @end
17 |
18 | @implementation WPFTableViewController
19 |
20 | - (IBAction)btnLogoutDidClick:(UIBarButtonItem *)sender {
21 |
22 | // 1. 清除本地信息
23 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kUserNameKey];
24 |
25 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:kPasswordKey];
26 |
27 | // 同步信息
28 | [[NSUserDefaults standardUserDefaults] synchronize];
29 |
30 | // 2. 发送信息,切换控制器
31 | [[NSNotificationCenter defaultCenter] postNotificationName:@"logoutSuccess" object:nil];
32 |
33 | }
34 |
35 | - (void)viewDidLoad {
36 | [super viewDidLoad];
37 |
38 | // token 值: 登录令牌.利用 token 值来判断用户的登录状态.类似于 MD5 加密之后的长字符串.
39 |
40 | // 用户登录成功之后,在后端(服务器端)会根据用户信息生成一个唯一的值.这个值就是 token 值.
41 |
42 | // 1. 在服务器端(数据库)会保存这个 token 值,以后利用这个 token 值来检索对应的用户信息,并且判断用户的登录状态.
43 |
44 | // 2. 用户登录成功之后,服务器会将生成的 token 值返回给 客户端,在客户端也会保存这个 token 值.(一般可以保存在 cookie 中,也可以自己手动确定保存位置(比如偏好设置.)).
45 |
46 | // 3. 以后客户端在发送新的网络请求的时候,会默认自动附带这个 token 值(作为一个参数传递给服务器.).服务器拿到客户端传递的 token 值跟保存在 数据库中的 token 值做对比,以此来判断用户身份和登录状态.
47 |
48 | // 判断登录状态:
49 |
50 | // 1. 如果客户端没有这个 token 值,意味着没有登录成功过,提示用户登录.
51 |
52 | // 2. 如果客户端有 token 值,一般会认为登录成功.不需要用户再次登录(输入账号和密码信息).
53 |
54 | // token 值扩展:
55 |
56 | // 1. token 值有失效时间; 一般的 app ,token值得失效时间都在 1 年以上.
57 | // 特殊的 app :银行类 app /支付类 app :token值失效时间 15 分钟左右.
58 |
59 | // 2. token 值改变: 可以做 唯一性登录的判断,也可以检查用户信息的改变.
60 |
61 | // 一旦用户信息改变(密码改变),会在服务器生成新的 token 值,原来的 token值就会失效.需要再次输入账号和密码,以得到生成的新的 token 值.
62 |
63 | // 唯一性判断: 每次登录,都会生成一个新的token值.原来的 token 值就会失效.利用时间来判断登录的差异性.
64 | }
65 |
66 | - (void)didReceiveMemoryWarning {
67 | [super didReceiveMemoryWarning];
68 | // Dispose of any resources that can be recreated.
69 | }
70 |
71 | #pragma mark - Table view data source
72 |
73 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
74 | #warning Incomplete implementation, return the number of sections
75 | return 0;
76 | }
77 |
78 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
79 | #warning Incomplete implementation, return the number of rows
80 | return 0;
81 | }
82 |
83 | /*
84 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
85 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<#@"reuseIdentifier"#> forIndexPath:indexPath];
86 |
87 | // Configure the cell...
88 |
89 | return cell;
90 | }
91 | */
92 |
93 | /*
94 | // Override to support conditional editing of the table view.
95 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
96 | // Return NO if you do not want the specified item to be editable.
97 | return YES;
98 | }
99 | */
100 |
101 | /*
102 | // Override to support editing the table view.
103 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
104 | if (editingStyle == UITableViewCellEditingStyleDelete) {
105 | // Delete the row from the data source
106 | [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
107 | } else if (editingStyle == UITableViewCellEditingStyleInsert) {
108 | // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
109 | }
110 | }
111 | */
112 |
113 | /*
114 | // Override to support rearranging the table view.
115 | - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
116 | }
117 | */
118 |
119 | /*
120 | // Override to support conditional rearranging of the table view.
121 | - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
122 | // Return NO if you do not want the item to be re-orderable.
123 | return YES;
124 | }
125 | */
126 |
127 | /*
128 | #pragma mark - Navigation
129 |
130 | // In a storyboard-based application, you will often want to do a little preparation before navigation
131 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
132 | // Get the new view controller using [segue destinationViewController].
133 | // Pass the selected object to the new view controller.
134 | }
135 | */
136 |
137 | @end
138 |
--------------------------------------------------------------------------------
/10-钥匙串访问/10-钥匙串访问/SSKeychain/SSKeychain.h:
--------------------------------------------------------------------------------
1 | //
2 | // SSKeychain.h
3 | // SSKeychain
4 | //
5 | // Created by Sam Soffes on 5/19/10.
6 | // Copyright (c) 2010-2014 Sam Soffes. All rights reserved.
7 | //
8 |
9 | #import "SSKeychainQuery.h"
10 |
11 | /**
12 | Error code specific to SSKeychain that can be returned in NSError objects.
13 | For codes returned by the operating system, refer to SecBase.h for your
14 | platform.
15 | */
16 | typedef NS_ENUM(OSStatus, SSKeychainErrorCode) {
17 | /** Some of the arguments were invalid. */
18 | SSKeychainErrorBadArguments = -1001,
19 | };
20 |
21 | /** SSKeychain error domain */
22 | extern NSString *const kSSKeychainErrorDomain;
23 |
24 | /** Account name. */
25 | extern NSString *const kSSKeychainAccountKey;
26 |
27 | /**
28 | Time the item was created.
29 |
30 | The value will be a string.
31 | */
32 | extern NSString *const kSSKeychainCreatedAtKey;
33 |
34 | /** Item class. */
35 | extern NSString *const kSSKeychainClassKey;
36 |
37 | /** Item description. */
38 | extern NSString *const kSSKeychainDescriptionKey;
39 |
40 | /** Item label. */
41 | extern NSString *const kSSKeychainLabelKey;
42 |
43 | /** Time the item was last modified.
44 |
45 | The value will be a string.
46 | */
47 | extern NSString *const kSSKeychainLastModifiedKey;
48 |
49 | /** Where the item was created. */
50 | extern NSString *const kSSKeychainWhereKey;
51 |
52 | /**
53 | Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system
54 | Keychain on Mac OS X and iOS.
55 |
56 | This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors.
57 | SSKeychain has since switched to a simpler implementation that was abstracted from [SSToolkit](http://sstoolk.it).
58 | */
59 | @interface SSKeychain : NSObject
60 |
61 | #pragma mark - Classic methods
62 |
63 | /**
64 | Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't have a
65 | password for the given parameters.
66 |
67 | @param serviceName The service for which to return the corresponding password.
68 |
69 | @param account The account for which to return the corresponding password.
70 |
71 | @return Returns a string containing the password for a given account and service, or `nil` if the Keychain doesn't
72 | have a password for the given parameters.
73 | */
74 | + (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;
75 | + (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
76 |
77 |
78 | /**
79 | Deletes a password from the Keychain.
80 |
81 | @param serviceName The service for which to delete the corresponding password.
82 |
83 | @param account The account for which to delete the corresponding password.
84 |
85 | @return Returns `YES` on success, or `NO` on failure.
86 | */
87 | + (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;
88 | + (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
89 |
90 |
91 | /**
92 | Sets a password in the Keychain.
93 |
94 | @param password The password to store in the Keychain.
95 |
96 | @param serviceName The service for which to set the corresponding password.
97 |
98 | @param account The account for which to set the corresponding password.
99 |
100 | @return Returns `YES` on success, or `NO` on failure.
101 | */
102 | + (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;
103 | + (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
104 |
105 |
106 | /**
107 | Returns an array containing the Keychain's accounts, or `nil` if the Keychain has no accounts.
108 |
109 | See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
110 | dictionaries returned by this method.
111 |
112 | @return An array of dictionaries containing the Keychain's accounts, or `nil` if the Keychain doesn't have any
113 | accounts. The order of the objects in the array isn't defined.
114 | */
115 | + (NSArray *)allAccounts;
116 |
117 |
118 | /**
119 | Returns an array containing the Keychain's accounts for a given service, or `nil` if the Keychain doesn't have any
120 | accounts for the given service.
121 |
122 | See the `NSString` constants declared in SSKeychain.h for a list of keys that can be used when accessing the
123 | dictionaries returned by this method.
124 |
125 | @param serviceName The service for which to return the corresponding accounts.
126 |
127 | @return An array of dictionaries containing the Keychain's accounts for a given `serviceName`, or `nil` if the Keychain
128 | doesn't have any accounts for the given `serviceName`. The order of the objects in the array isn't defined.
129 | */
130 | + (NSArray *)accountsForService:(NSString *)serviceName;
131 |
132 |
133 | #pragma mark - Configuration
134 |
135 | #if __IPHONE_4_0 && TARGET_OS_IPHONE
136 | /**
137 | Returns the accessibility type for all future passwords saved to the Keychain.
138 |
139 | @return Returns the accessibility type.
140 |
141 | The return value will be `NULL` or one of the "Keychain Item Accessibility
142 | Constants" used for determining when a keychain item should be readable.
143 |
144 | @see setAccessibilityType
145 | */
146 | + (CFTypeRef)accessibilityType;
147 |
148 | /**
149 | Sets the accessibility type for all future passwords saved to the Keychain.
150 |
151 | @param accessibilityType One of the "Keychain Item Accessibility Constants"
152 | used for determining when a keychain item should be readable.
153 |
154 | If the value is `NULL` (the default), the Keychain default will be used.
155 |
156 | @see accessibilityType
157 | */
158 | + (void)setAccessibilityType:(CFTypeRef)accessibilityType;
159 | #endif
160 |
161 | @end
162 |
--------------------------------------------------------------------------------
/07-MD5加密/07-MD5加密/Security/NSString+Hash.m:
--------------------------------------------------------------------------------
1 | // 01-数据安全
2 |
3 | #import "NSString+Hash.h"
4 | #import
5 |
6 | @implementation NSString (Hash)
7 |
8 | #pragma mark - 散列函数
9 | - (NSString *)md5String {
10 | const char *str = self.UTF8String;
11 | uint8_t buffer[CC_MD5_DIGEST_LENGTH];
12 |
13 | CC_MD5(str, (CC_LONG)strlen(str), buffer);
14 |
15 | return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
16 | }
17 |
18 | - (NSString *)sha1String {
19 | const char *str = self.UTF8String;
20 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
21 |
22 | CC_SHA1(str, (CC_LONG)strlen(str), buffer);
23 |
24 | return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
25 | }
26 |
27 | - (NSString *)sha256String {
28 | const char *str = self.UTF8String;
29 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
30 |
31 | CC_SHA256(str, (CC_LONG)strlen(str), buffer);
32 |
33 | return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
34 | }
35 |
36 | - (NSString *)sha512String {
37 | const char *str = self.UTF8String;
38 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
39 |
40 | CC_SHA512(str, (CC_LONG)strlen(str), buffer);
41 |
42 | return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
43 | }
44 |
45 | #pragma mark - HMAC 散列函数
46 | - (NSString *)hmacMD5StringWithKey:(NSString *)key {
47 | const char *keyData = key.UTF8String;
48 | const char *strData = self.UTF8String;
49 | uint8_t buffer[CC_MD5_DIGEST_LENGTH];
50 |
51 | CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
52 |
53 | return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
54 | }
55 |
56 | - (NSString *)hmacSHA1StringWithKey:(NSString *)key {
57 | const char *keyData = key.UTF8String;
58 | const char *strData = self.UTF8String;
59 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
60 |
61 | CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer);
62 |
63 | return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
64 | }
65 |
66 | - (NSString *)hmacSHA256StringWithKey:(NSString *)key {
67 | const char *keyData = key.UTF8String;
68 | const char *strData = self.UTF8String;
69 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
70 |
71 | CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer);
72 |
73 | return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
74 | }
75 |
76 | - (NSString *)hmacSHA512StringWithKey:(NSString *)key {
77 | const char *keyData = key.UTF8String;
78 | const char *strData = self.UTF8String;
79 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
80 |
81 | CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer);
82 |
83 | return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
84 | }
85 |
86 | #pragma mark - 文件散列函数
87 |
88 | #define FileHashDefaultChunkSizeForReadingData 4096
89 |
90 | - (NSString *)fileMD5Hash {
91 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
92 | if (fp == nil) {
93 | return nil;
94 | }
95 |
96 | CC_MD5_CTX hashCtx;
97 | CC_MD5_Init(&hashCtx);
98 |
99 | while (YES) {
100 | @autoreleasepool {
101 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
102 |
103 | CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
104 |
105 | if (data.length == 0) {
106 | break;
107 | }
108 | }
109 | }
110 | [fp closeFile];
111 |
112 | uint8_t buffer[CC_MD5_DIGEST_LENGTH];
113 | CC_MD5_Final(buffer, &hashCtx);
114 |
115 | return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
116 | }
117 |
118 | - (NSString *)fileSHA1Hash {
119 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
120 | if (fp == nil) {
121 | return nil;
122 | }
123 |
124 | CC_SHA1_CTX hashCtx;
125 | CC_SHA1_Init(&hashCtx);
126 |
127 | while (YES) {
128 | @autoreleasepool {
129 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
130 |
131 | CC_SHA1_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
132 |
133 | if (data.length == 0) {
134 | break;
135 | }
136 | }
137 | }
138 | [fp closeFile];
139 |
140 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
141 | CC_SHA1_Final(buffer, &hashCtx);
142 |
143 | return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
144 | }
145 |
146 | - (NSString *)fileSHA256Hash {
147 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
148 | if (fp == nil) {
149 | return nil;
150 | }
151 |
152 | CC_SHA256_CTX hashCtx;
153 | CC_SHA256_Init(&hashCtx);
154 |
155 | while (YES) {
156 | @autoreleasepool {
157 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
158 |
159 | CC_SHA256_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
160 |
161 | if (data.length == 0) {
162 | break;
163 | }
164 | }
165 | }
166 | [fp closeFile];
167 |
168 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
169 | CC_SHA256_Final(buffer, &hashCtx);
170 |
171 | return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
172 | }
173 |
174 | - (NSString *)fileSHA512Hash {
175 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
176 | if (fp == nil) {
177 | return nil;
178 | }
179 |
180 | CC_SHA512_CTX hashCtx;
181 | CC_SHA512_Init(&hashCtx);
182 |
183 | while (YES) {
184 | @autoreleasepool {
185 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
186 |
187 | CC_SHA512_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
188 |
189 | if (data.length == 0) {
190 | break;
191 | }
192 | }
193 | }
194 | [fp closeFile];
195 |
196 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
197 | CC_SHA512_Final(buffer, &hashCtx);
198 |
199 | return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
200 | }
201 |
202 | #pragma mark - 助手方法
203 | /**
204 | * 返回二进制 Bytes 流的字符串表示形式
205 | *
206 | * @param bytes 二进制 Bytes 数组
207 | * @param length 数组长度
208 | *
209 | * @return 字符串表示形式
210 | */
211 | - (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length {
212 | NSMutableString *strM = [NSMutableString string];
213 |
214 | for (int i = 0; i < length; i++) {
215 | [strM appendFormat:@"%02x", bytes[i]];
216 | }
217 |
218 | return [strM copy];
219 | }
220 |
221 | @end
222 |
--------------------------------------------------------------------------------
/08-动态密码(时间戳密码)/08-动态密码(时间戳密码)/Security/NSString+Hash.m:
--------------------------------------------------------------------------------
1 | // 01-数据安全
2 |
3 | #import "NSString+Hash.h"
4 | #import
5 |
6 | @implementation NSString (Hash)
7 |
8 | #pragma mark - 散列函数
9 | - (NSString *)md5String {
10 | const char *str = self.UTF8String;
11 | uint8_t buffer[CC_MD5_DIGEST_LENGTH];
12 |
13 | CC_MD5(str, (CC_LONG)strlen(str), buffer);
14 |
15 | return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
16 | }
17 |
18 | - (NSString *)sha1String {
19 | const char *str = self.UTF8String;
20 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
21 |
22 | CC_SHA1(str, (CC_LONG)strlen(str), buffer);
23 |
24 | return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
25 | }
26 |
27 | - (NSString *)sha256String {
28 | const char *str = self.UTF8String;
29 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
30 |
31 | CC_SHA256(str, (CC_LONG)strlen(str), buffer);
32 |
33 | return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
34 | }
35 |
36 | - (NSString *)sha512String {
37 | const char *str = self.UTF8String;
38 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
39 |
40 | CC_SHA512(str, (CC_LONG)strlen(str), buffer);
41 |
42 | return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
43 | }
44 |
45 | #pragma mark - HMAC 散列函数
46 | - (NSString *)hmacMD5StringWithKey:(NSString *)key {
47 | const char *keyData = key.UTF8String;
48 | const char *strData = self.UTF8String;
49 | uint8_t buffer[CC_MD5_DIGEST_LENGTH];
50 |
51 | CCHmac(kCCHmacAlgMD5, keyData, strlen(keyData), strData, strlen(strData), buffer);
52 |
53 | return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
54 | }
55 |
56 | - (NSString *)hmacSHA1StringWithKey:(NSString *)key {
57 | const char *keyData = key.UTF8String;
58 | const char *strData = self.UTF8String;
59 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
60 |
61 | CCHmac(kCCHmacAlgSHA1, keyData, strlen(keyData), strData, strlen(strData), buffer);
62 |
63 | return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
64 | }
65 |
66 | - (NSString *)hmacSHA256StringWithKey:(NSString *)key {
67 | const char *keyData = key.UTF8String;
68 | const char *strData = self.UTF8String;
69 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
70 |
71 | CCHmac(kCCHmacAlgSHA256, keyData, strlen(keyData), strData, strlen(strData), buffer);
72 |
73 | return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
74 | }
75 |
76 | - (NSString *)hmacSHA512StringWithKey:(NSString *)key {
77 | const char *keyData = key.UTF8String;
78 | const char *strData = self.UTF8String;
79 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
80 |
81 | CCHmac(kCCHmacAlgSHA512, keyData, strlen(keyData), strData, strlen(strData), buffer);
82 |
83 | return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
84 | }
85 |
86 | #pragma mark - 文件散列函数
87 |
88 | #define FileHashDefaultChunkSizeForReadingData 4096
89 |
90 | - (NSString *)fileMD5Hash {
91 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
92 | if (fp == nil) {
93 | return nil;
94 | }
95 |
96 | CC_MD5_CTX hashCtx;
97 | CC_MD5_Init(&hashCtx);
98 |
99 | while (YES) {
100 | @autoreleasepool {
101 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
102 |
103 | CC_MD5_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
104 |
105 | if (data.length == 0) {
106 | break;
107 | }
108 | }
109 | }
110 | [fp closeFile];
111 |
112 | uint8_t buffer[CC_MD5_DIGEST_LENGTH];
113 | CC_MD5_Final(buffer, &hashCtx);
114 |
115 | return [self stringFromBytes:buffer length:CC_MD5_DIGEST_LENGTH];
116 | }
117 |
118 | - (NSString *)fileSHA1Hash {
119 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
120 | if (fp == nil) {
121 | return nil;
122 | }
123 |
124 | CC_SHA1_CTX hashCtx;
125 | CC_SHA1_Init(&hashCtx);
126 |
127 | while (YES) {
128 | @autoreleasepool {
129 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
130 |
131 | CC_SHA1_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
132 |
133 | if (data.length == 0) {
134 | break;
135 | }
136 | }
137 | }
138 | [fp closeFile];
139 |
140 | uint8_t buffer[CC_SHA1_DIGEST_LENGTH];
141 | CC_SHA1_Final(buffer, &hashCtx);
142 |
143 | return [self stringFromBytes:buffer length:CC_SHA1_DIGEST_LENGTH];
144 | }
145 |
146 | - (NSString *)fileSHA256Hash {
147 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
148 | if (fp == nil) {
149 | return nil;
150 | }
151 |
152 | CC_SHA256_CTX hashCtx;
153 | CC_SHA256_Init(&hashCtx);
154 |
155 | while (YES) {
156 | @autoreleasepool {
157 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
158 |
159 | CC_SHA256_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
160 |
161 | if (data.length == 0) {
162 | break;
163 | }
164 | }
165 | }
166 | [fp closeFile];
167 |
168 | uint8_t buffer[CC_SHA256_DIGEST_LENGTH];
169 | CC_SHA256_Final(buffer, &hashCtx);
170 |
171 | return [self stringFromBytes:buffer length:CC_SHA256_DIGEST_LENGTH];
172 | }
173 |
174 | - (NSString *)fileSHA512Hash {
175 | NSFileHandle *fp = [NSFileHandle fileHandleForReadingAtPath:self];
176 | if (fp == nil) {
177 | return nil;
178 | }
179 |
180 | CC_SHA512_CTX hashCtx;
181 | CC_SHA512_Init(&hashCtx);
182 |
183 | while (YES) {
184 | @autoreleasepool {
185 | NSData *data = [fp readDataOfLength:FileHashDefaultChunkSizeForReadingData];
186 |
187 | CC_SHA512_Update(&hashCtx, data.bytes, (CC_LONG)data.length);
188 |
189 | if (data.length == 0) {
190 | break;
191 | }
192 | }
193 | }
194 | [fp closeFile];
195 |
196 | uint8_t buffer[CC_SHA512_DIGEST_LENGTH];
197 | CC_SHA512_Final(buffer, &hashCtx);
198 |
199 | return [self stringFromBytes:buffer length:CC_SHA512_DIGEST_LENGTH];
200 | }
201 |
202 | #pragma mark - 助手方法
203 | /**
204 | * 返回二进制 Bytes 流的字符串表示形式
205 | *
206 | * @param bytes 二进制 Bytes 数组
207 | * @param length 数组长度
208 | *
209 | * @return 字符串表示形式
210 | */
211 | - (NSString *)stringFromBytes:(uint8_t *)bytes length:(int)length {
212 | NSMutableString *strM = [NSMutableString string];
213 |
214 | for (int i = 0; i < length; i++) {
215 | [strM appendFormat:@"%02x", bytes[i]];
216 | }
217 |
218 | return [strM copy];
219 | }
220 |
221 | @end
222 |
--------------------------------------------------------------------------------
/04-POST加密(保存本地数据)/04-POST加密(保存本地数据)/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
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 |
28 |
29 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------