IOS 加密、解密

首先罗列一些知识点:

1.加密算法通常分为对称性加密算法和非对称性加密算法:对于对称性加密算法,信息接收双方都需事先知道密匙和加解密算法且其密匙是相同的,之后便是对数据进行 加解密了。非对称算法与之不同,发送双方A,B事先均生成一堆密匙,然后A将自己的公有密匙发送给B,B将自己的公有密匙发送给A,如果A要给B发送消息,则先需要用B的公有密匙进行消息加密,然后发送给B端,此时B端再用自己的私有密匙进行消息解密,B向A发送消息时为同样的道理。

2.关于公钥私钥和数字签名, 通过一个发送邮件的故事让大家有一个深刻的理解,非常棒的案例:

http://www.blogjava.net/yxhxj2006/archive/2012/10/15/389547.html

看完这个之后, 相信你会明白非对称加密在网络传输中的安全性的体现, 当然就是之前谈到的https。

总而言之:公钥与私钥的作用是:用公钥加密的内容只能用私钥解密,用私钥加密的内容只能 用公钥解密。公钥加密私钥解密, 没问题,也可以说是"公共密钥加密系统"私钥加密公钥解密,一般不这么说,应叫"私钥签名,公钥验证",也可以说是“公共密钥签名系统”

引用一段总结的话:

公钥加密私钥解密, 没问题,也可以说是"公共密钥加密系统"私钥加密公钥解密,一般不这么说,应叫"私钥签名,公钥验证",也可以说是“公共密钥签名系统”再来说一下"公共密钥签名系统"目的:(如果晕就多看几遍,这个没搞清,后面的代码就更晕)A欲传(信息)给B,但又怕B不确信该信息是A发的。1.A选计算(信息)的HASH值,如用MD5方式计算,得到:[MD5(信息)]2.然后用自已的私钥加密HASH值,得到:[私钥(MD5(信息))]3.最后将信息与密文一起传给B:传给B:[(信息) + 私钥(MD5(信息))]B接到 :[(信息) + 私钥(MD5(信息))]1.先用相同的HASH算法算出(信息)的HASH值,这里也使用MD5方式 得到: [MD5(信息)!]2. 再用A的公钥解密 [ 私钥(MD5(信息))] [公钥(私钥(MD5(信息)))] = [(MD5(信息)] 如能解开,证明该 [ 私钥(MD5(信息))]是A发送的3.再比效[MD5(信息)!]与[(MD5(信息)] 如果相同,表示(信息)在传递过程中没有被他人修改过

OK, 到现在为止, 你已经懂得了公钥, 私钥, 以及数字证书的概念了, 当然你也知道什么是对称加密和非对称加密,有可能你不是很清楚,为了让你更清楚,给你再讲个活生生的例子,这个例子还要从我的恋爱说起, 高中的时候喜欢上一个女生, 那时候青春年少,还喜欢用纸质给她写情书, 每天写一些“透明的”文字很繁琐,于是有一天,我忽然一个念想,把情书改成用汉语拼音写abcd……xyz, 原来字母是a就用z代替,b用y代替,c用x代替,……z用a代替, 这样,一个只有我们俩能看的懂的情书就这样诞生了。其实现在想想, 这不正是一种对称式加密么。哈哈。

说完了故事,再来普及下一点简单的知识喽

3几种对称性加密算法:AES,DES,3DES

DES是一种分组数据加密技术(先将数据分成固定长度的小数据块,之后进行加密),速度较快,适用于大量数据加密,而3DES是一种基于DES的加密算法,使用3个不同密匙对同一个分组数据块进行3次加密,如此以使得密文强度更高。

相较于DES和3DES算法而言,AES算法有着更高的速度和资源使用效率,安全级别也较之更高了,被称为下一代加密标准。对于具体的算法我们不做深入的了解, 之前有一篇文章写得很好, 由于时间问题, 我就不给大家找了。

4几种非对称性加密算法:RSA,DSA,ECC

RSA和DSA的安全性及其它各方面性能都差不多,而ECC较之则有着很多的性能优越,包括处理速度,带宽要求,存储空间等等

5几种线性散列算法(签名算法):MD5,SHA1,HMAC

这几种算法只生成一串不可逆的密文,经常用其效验数据传输过程中是否经过修改,因为相同的生成算法对于同一明文只会生成唯一的密文,若相同算法生成的密文不同,则证明传输数据进行过了修改。通常在数据传说过程前,使用MD5和SHA1算法均需要发送和接收数据双方在数据传送之前就知道密匙生成算法,而HMAC与之不同的是需要生成一个密匙,发送方用此密匙对数据进行摘要处理(生成密文),接收方再利用此密匙对接收到的数据进行摘要处理,再判断生成的密文是否相同。

6对于各种加密算法的选用

由于对称加密算法的密钥管理是一个复杂的过程,密钥的管理直接决定着他的安全性,因此当数据量很小时,我们可以考虑采用非对称加密算法。

在实际的操作过程中我们通常采用的方式是:采用非对称加密算法管理对称算法的密钥,然后用对称加密算法加密数据,这样我们就集成了两类加密算法的优点,既实现了加密速度快的优点,又实现了安全方便管理密钥的优点。如果在选定了加密算法后,那采用多少位的密钥呢?一般来说,密钥越长,运行的速度就越慢,应该根据的我们实际需要的安全级别来选择,一般来说,RSA建议采用1024位的数字,ECC建议采用160位,AES采用128为即可。

需要注意的是:

哈希函数,比如MD5,SHA,这些都不是加密算法。要注意他们的区别和用途,很多网友都把md5说成是加密算法,这是严重不正确的啊。哈希函数:MD5,SHA 是没有密钥的,相当与指纹的概念,因此也是不可逆的; md5是128位的,SHA有不同的算法,有128,256等位。。。如SHA-256,SHA-384然后 就是 Base64,这更加不属于加密算法的范围了,它只是将byte[]数组进行了转换,为什么要转换呢?就是因为很多加密后的密文后者一些特殊的byte[]数组需要显示出来,或者需要进行传递(电子邮件),但是直接转换就会导致很多不可显示的字符,会丢失一些信息,因此就转换位Base64编码,这些都是可显示的字符。所以转换后,长度会增加。它是可逆的。 再就是 3DES,DES 这才是加密算法,因此也是可逆的,加解密需要密钥,也就是你说的key最后是 RSA ,这是公钥密码,也就是加密和解密密钥不同,也是可逆的。

罗列了这么多知识点, 我想这篇文章你应该有收藏的必要了吧,为了更形象,更好玩, 我从网上找了一些在线工具:

1.1-Base64

http://www1.tc711.com/tool/BASE64.htm

blob.png

blob.png

可以按出来这是可逆的编解码,注意不是加密幺!!!

1.2-MD5

http://tool.chinaz.com/Tools/MD5.aspx?q=32324&md5type=1

blob.png

其实这个也不能叫加密工具幺,今晚写到这里吧, 眼睛很累了,明天把这篇文章写完。

1.3-SHA-1,SHA-2,SHA-256,SHA-512,SHA-3

好吧,哈希的工具找到了一个更好的工具连接,里面也有MD5.里面还有哈希的一些说明。

http://www.atool.org/hash.php 这个链接值的收藏一下, 主要是用到哈希的时候可以经常用。

blob.png

2.1 AES DES

以上我们主要说了哈希算法和数字证书的一些知识, 现在我们看一下对称加密的一些在线工具

DES http://e-file.arkoo.com/tools/des3.htm

这个链接可谓非常干净好用,形象直观可逆过程,哈哈。

blob.png

AES http://www.seacha.com/tools/aes.html

blob.png

忽然发现这个在线工具也还凑合http://encode.chahuo.com/

blob.png

如此般, 对称加密基本上都弄完了,现在我们只简单的了解下非对称加解密的RSA,上面的过程我们已经说的非常详细了吧。重点已经用黑色字体标注出来了。

加密数据

1
2
3
4
5
6
7
8
     RSAEncryptor *rsa = [[RSAEncryptor alloc] init];  
     NSLog(@ "encryptor using rsa" );  
     NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@ "public_key"  ofType:@ "der" ];  
     NSLog(@ "public key: %@" , publicKeyPath);  
     [rsa loadPublicKeyFromFile:publicKeyPath];  
     NSString *securityText = @ "hello ~" ;  
     NSString *encryptedString = [rsa rsaEncryptString:securityText];  
     NSLog(@ "encrypted data: %@" , encryptedString);

解密数据在

iOS下解码需要先加载private key, 之后在对数据解码. 解码的时候先进行Base64 decode, 之后在用private key decrypt加密数据.

1
2
3
4
     NSLog(@ "decryptor using rsa" );  
     [rsa loadPrivateKeyFromFile:[[NSBundle mainBundle] pathForResource:@ "private_key"  ofType:@ "p12" ] password:@ "123456" ];  
     NSString *decryptedString = [rsa rsaDecryptString:encryptedString];  
     NSLog(@ "decrypted data: %@" , decryptedString);

具体详细文章可以参考链接

http://witcheryne.iteye.com/blog/2171850

http://www.cocoachina.com/bbs/read.php?tid=166990

在支付宝支付过程中就使用了RSA加密。

在在这里有必要提醒下小编自己, 有时间需要研究下苹果证书的工作机制。

弄到这里, 我主要是找一些代码给大家用,看看我自己先建一个工程吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//  Created by Lcq on 15/12/16.
//  Copyright ? 2015年 Lcq. All rights reserved.
//
#import @interface Helper : NSObject
//MD5
+ (NSString *) md5:(NSString *)str;
//Base64
+ (NSString *)base64StringFromText:(NSString *)text;
+ (NSString *)textFromBase64String:(NSString *)base64;
+ (NSString *)base64EncodedStringFrom:(NSData *)data;
//DES加密
+(NSString *)encryptSting:(NSString *)sText key:(NSString *)key andDesiv:(NSString *)ivDes;
//DES解密
+(NSString *)decryptWithDESString:(NSString *)sText key:(NSString *)key andiV:(NSString *)iv;
//AES加密
+ (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data;
//AES解密
+ (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data;
@end
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
#import "Helper.h"
#import #importstatic const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define LocalStr_None  @""
@implementation Helper
//Md5
+ (NSString *) md5:(NSString *)str {
     if  (str == nil) {
         return  nil;
     }
     const char *cStr = [str UTF8String];
     unsigned char result[16];
     CC_MD5( cStr, strlen(cStr), result );
     return  [NSString stringWithFormat:
             @ "XXXXXXXXXXXXXXXX" ,
             result[0], result[1], result[2], result[3],
             result[4], result[5], result[6], result[7],
             result[8], result[9], result[10], result[11],
             result[12], result[13], result[14], result[15]
             ];
}
//转化为Base64
+ (NSString *)base64StringFromText:(NSString *)text
{
     if  (text && ![text isEqualToString:LocalStr_None]) {
         //取项目的bundleIdentifier作为KEY  改动了此处
         //NSString *key = [[NSBundle mainBundle] bundleIdentifier];
         NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
         //IOS 自带DES加密 Begin  改动了此处
         //data = [self DESEncrypt:data WithKey:key];
         //IOS 自带DES加密 End
         return  [self base64EncodedStringFrom:data];
     }
     else  {
         return  LocalStr_None;
     }
}
//由base64转化
+ (NSString *)textFromBase64String:(NSString *)base64
{
     if  (base64 && ![base64 isEqualToString:LocalStr_None]) {
         //取项目的bundleIdentifier作为KEY   改动了此处
         //NSString *key = [[NSBundle mainBundle] bundleIdentifier];
         NSData *data = [self dataWithBase64EncodedString:base64];
         //IOS 自带DES解密 Begin    改动了此处
         //data = [self DESDecrypt:data WithKey:key];
         //IOS 自带DES加密 End
         return  [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
     }
     else  {
         return  LocalStr_None;
     }
}
//DES加密
+(NSString *)encryptSting:(NSString *)sText key:(NSString *)key andDesiv:(NSString *)ivDes
{
     if  ((sText == nil || sText.length == 0)
         || (sText == nil || sText.length == 0)
         || (ivDes == nil || ivDes.length == 0)) {
         return  @ "" ;
     }
     //gb2312 编码
     NSStringEncoding encoding =CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
     NSData* encryptData = [sText dataUsingEncoding:encoding];
     size_t  dataInLength = [encryptData length];
     const void *   dataIn = (const void *)[encryptData bytes];
     CCCryptorStatus ccStatus = nil;
     uint8_t *dataOut = NULL;  //可以理解位type/typedef 的缩写(有效的维护了代码,比如:一个人用int,一个人用long。最好用typedef来定义)
     size_t dataOutMoved = 0;
     size_t    dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);  dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
     memset((void *)dataOut, 0x0, dataOutAvailable); //将已开辟内存空间buffer的首 1 个字节的值设为值 0
     const void *iv = (const void *) [ivDes cStringUsingEncoding:NSASCIIStringEncoding];
     //CCCrypt函数 加密/解密
     ccStatus = CCCrypt(kCCEncrypt, //  加密/解密
                        kCCAlgorithmDES, //  加密根据哪个标准(des,3des,aes。。。。)
                        kCCOptionPKCS7Padding, //  选项分组密码算法(des:对每块分组加一次密  3DES:对每块分组加三个不同的密)
                        [key UTF8String],   //密钥    加密和解密的密钥必须一致
                        kCCKeySizeDES, //   DES 密钥的大小(kCCKeySizeDES=8)
                        iv,  //  可选的初始矢量
                        dataIn,  // 数据的存储单元
                        dataInLength, // 数据的大小
                        (void *)dataOut, // 用于返回数据
                        dataOutAvailable,
                        &dataOutMoved);
     //编码 base64
     NSData *data = [NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved];
     Byte *bytes = (Byte *)[data bytes];
     //下面是Byte 转换为16进制。
     NSString *hexStr=@ "" ;
     for (int i=0;i<[data length];i++){
         NSString *newHexStr = [NSString stringWithFormat:@ "%x" ,bytes[i]&0xff]; ///16进制数
         if ([newHexStr length]==1)
             hexStr = [NSString stringWithFormat:@ "%@0%@" ,hexStr,newHexStr];
         else
             hexStr = [NSString stringWithFormat:@ "%@%@" ,hexStr,newHexStr];
     }
     free(dataOut);
     return  hexStr;
}
//DES解密
+(NSString *)decryptWithDESString:(NSString *)sText key:(NSString *)key andiV:(NSString *)iv
{
     if  ((sText == nil || sText.length == 0)
         || (sText == nil || sText.length == 0)
         || (iv == nil || iv.length == 0)) {
         return  @ "" ;
     }
     const void *dataIn;
     size_t dataInLength;
     char *myBuffer = (char *)malloc((int)[sText length] / 2 + 1);
     bzero(myBuffer, [sText length] / 2 + 1);
     for  (int i = 0; i < [sText length] - 1; i += 2) {
         unsigned int anInt;
         NSString * hexCharStr = [sText substringWithRange:NSMakeRange(i, 2)];
         NSScanner * scanner = [[NSScanner alloc] initWithString:hexCharStr];
         [scanner scanHexInt:&anInt];
         myBuffer[i / 2] = (char)anInt;
     }
     NSData *decryptData =[NSData dataWithBytes:myBuffer length:[sText length] / 2 ]; //转成utf-8并decode
     dataInLength = [decryptData length];
     dataIn = [decryptData bytes];
     free(myBuffer);
     CCCryptorStatus ccStatus = nil;
     uint8_t *dataOut = NULL;  //可以理解位type/typedef 的缩写(有效的维护了代码,比如:一个人用int,一个人用long。最好用typedef来定义)
     size_t dataOutAvailable = 0;  //size_t  是操作符sizeof返回的结果类型
     size_t dataOutMoved = 0;
     dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
     dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
     memset((void *)dataOut, 0x0, dataOutAvailable); //将已开辟内存空间buffer的首 1 个字节的值设为值 0
     const void *ivDes = (const void *) [iv cStringUsingEncoding:NSASCIIStringEncoding];
     //CCCrypt函数 加密/解密
     ccStatus = CCCrypt(kCCDecrypt, //  加密/解密
                        kCCAlgorithmDES, //  加密根据哪个标准(des,3des,aes。。。。)
                        kCCOptionPKCS7Padding, //  选项分组密码算法(des:对每块分组加一次密  3DES:对每块分组加三个不同的密)
                        [key UTF8String],   //密钥    加密和解密的密钥必须一致
                        kCCKeySizeDES, //   DES 密钥的大小(kCCKeySizeDES=8)
                        ivDes,  //  可选的初始矢量
                        dataIn,  // 数据的存储单元
                        dataInLength, // 数据的大小
                        (void *)dataOut, // 用于返回数据
                        dataOutAvailable,
                        &dataOutMoved);
     NSStringEncoding encoding =CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
     NSString *result  = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved] encoding:encoding];
     free(dataOut);
     return  result;
}
//AES加密
+ (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data
{
     char keyPtr[kCCKeySizeAES128+1];
     bzero(keyPtr, sizeof(keyPtr));
     [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
     char ivPtr[kCCKeySizeAES128+1];
     bzero(ivPtr, sizeof(ivPtr));
     [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
     NSUInteger dataLength = [data length];
     int diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
     int newSize = 0;
     if (diff > 0)
     {
         newSize = (int)(dataLength + diff);
     }
     char dataPtr[newSize];
     memcpy(dataPtr, [data bytes], [data length]);
     for (int i = 0; i < diff; i++)
     {
         dataPtr[i + dataLength] = 0x00;
     }
     size_t bufferSize = newSize + kCCBlockSizeAES128;
     void *buffer = malloc(bufferSize);
     size_t numBytesEncrypted = 0;
     CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                           kCCAlgorithmAES128,
                                           0x00,  //No padding
                                           keyPtr,
                                           kCCKeySizeAES128,
                                           ivPtr,
                                           dataPtr,
                                           sizeof(dataPtr),
                                           buffer,
                                           bufferSize,
                                           &numBytesEncrypted);
     if (cryptStatus == kCCSuccess)
     {
//        NSData *data =[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
//        NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
         return  [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
     }
     return  nil;
}
//AES解密
+ (NSData *)AES128DecryptWithKey:(NSString *)key iv:(NSString *)iv withNSData:(NSData *)data
{
     char keyPtr[kCCKeySizeAES128+1];
     bzero(keyPtr, sizeof(keyPtr));
     [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
     char ivPtr[kCCKeySizeAES128+1];
     bzero(ivPtr, sizeof(ivPtr));
     [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding];
     NSUInteger dataLength = [data length];
     size_t bufferSize = dataLength + kCCBlockSizeAES128;
     void *buffer = malloc(bufferSize);
     size_t numBytesEncrypted = 0;
     CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                           kCCAlgorithmAES128,
                                           0x00,  //No padding
                                           keyPtr,
                                           kCCKeySizeAES128,
                                           ivPtr,
                                           [data bytes],
                                           dataLength,
                                           buffer,
                                           bufferSize,
                                           &numBytesEncrypted);
     if (cryptStatus == kCCSuccess)
     {
//        NSData *data =[NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        // NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
         return  [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
     }
     return  nil;
}
/******************************************************************************
  函数名称 : + (NSData *)dataWithBase64EncodedString:(NSString *)string
  函数描述 : base64格式字符串转换为文本数据
  输入参数 : (NSString *)string
  输出参数 : N/A
  返回参数 : (NSData *)
  备注信息 :
  ******************************************************************************/
+ (NSData *)dataWithBase64EncodedString:(NSString *)string
{
     if  (string == nil)
         [NSException raise:NSInvalidArgumentException format:nil];
     if  ([string length] == 0)
         return  [NSData data];
     static char *decodingTable = NULL;
     if  (decodingTable == NULL)
     {
         decodingTable = malloc(256);
         if  (decodingTable == NULL)
             return  nil;
         memset(decodingTable, CHAR_MAX, 256);
         NSUInteger i;
         for  (i = 0; i < 64; i++)
             decodingTable[(short)encodingTable[i]] = i;
     }
     const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
     if  (characters == NULL)      //  Not an ASCII string!
         return  nil;
     char *bytes = malloc((([string length] + 3) / 4) * 3);
     if  (bytes == NULL)
         return  nil;
     NSUInteger length = 0;
     NSUInteger i = 0;
     while  (YES)
     {
         char buffer[4];
         short bufferLength;
         for  (bufferLength = 0; bufferLength < 4; i++)
         {
             if  (characters[i] ==  '\0' )
                 break ;
             if  (isspace(characters[i]) || characters[i] ==  '=' )
                 continue ;
             buffer[bufferLength] = decodingTable[(short)characters[i]];
             if  (buffer[bufferLength++] == CHAR_MAX)       //  Illegal character!
             {
                 free(bytes);
                 return  nil;
             }
         }
         if  (bufferLength == 0)
             break ;
         if  (bufferLength == 1)       //  At least two characters are needed to produce one byte!
         {
             free(bytes);
             return  nil;
         }
         //  Decode the characters in the buffer to bytes.
         bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
         if  (bufferLength > 2)
             bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
         if  (bufferLength > 3)
             bytes[length++] = (buffer[2] << 6) | buffer[3];
     }
     bytes = realloc(bytes, length);
     return  [NSData dataWithBytesNoCopy:bytes length:length];
}
/******************************************************************************
  函数名称 : + (NSString *)base64EncodedStringFrom:(NSData *)data
  函数描述 : 文本数据转换为base64格式字符串
  输入参数 : (NSData *)data
  输出参数 : N/A
  返回参数 : (NSString *)
  备注信息 :
  ******************************************************************************/
+ (NSString *)base64EncodedStringFrom:(NSData *)data
{
     if  ([data length] == 0)
         return  @ "" ;
     char *characters = malloc((([data length] + 2) / 3) * 4);
     if  (characters == NULL)
         return  nil;
     NSUInteger length = 0;
     NSUInteger i = 0;
     while  (i < [data length])
     {
         char buffer[3] = {0,0,0};
         short bufferLength = 0;
         while  (bufferLength < 3 && i < [data length])
             buffer[bufferLength++] = ((char *)[data bytes])[i++];
         //  Encode the bytes in the buffer to four characters, including padding "=" characters if necessary.
         characters[length++] = encodingTable[(buffer[0] & 0xFC) >> 2];
         characters[length++] = encodingTable[((buffer[0] & 0x03) << 4) | ((buffer[1] & 0xF0) >> 4)];
         if  (bufferLength > 1)
             characters[length++] = encodingTable[((buffer[1] & 0x0F) << 2) | ((buffer[2] & 0xC0) >> 6)];
         else  characters[length++] =  '=' ;
         if  (bufferLength > 2)
             characters[length++] = encodingTable[buffer[2] & 0x3F];
         else  characters[length++] =  '=' ;
     }
     return  [[NSString alloc] initWithBytesNoCopy:characters length:length encoding:NSASCIIStringEncoding freeWhenDone:YES];
}
@end

以上是接口和实现文件, 现在我们来看看调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
     //MD5
     NSString *md5Str = [Helper md5:@ "我爱你" ];
     NSLog(@ "md5Str is %@" ,md5Str); //Log is 4F2016C6B934D55BD7120E5D0E62CCE3
     //Base64
     NSString *Base64Str = [Helper base64StringFromText:@ "我爱你" ];
     NSLog(@ "Base64Str is %@" ,Base64Str); //Log is 5oiR54ix5L2g
     NSString *oriBase64Str = [Helper textFromBase64String:Base64Str];
     NSLog(@ "oriBase64Str is %@" ,oriBase64Str); //Log is  我爱你
     //DES
     NSString *desEnStr = [Helper encryptSting:@ "我爱你"  key:@ "521"  andDesiv:@ "521" ];
     NSLog(@ "desEnStr is %@" ,desEnStr); //Log is  389280aa791ee933
     NSString *desDeStr =[Helper decryptWithDESString:desEnStr key:@ "521"  andiV:@ "521" ];
     NSLog(@ "desDeStr is %@" ,desDeStr); //Log is  我爱你
     //AES
     NSData *aesEnData = [Helper AES128EncryptWithKey:@ "521"  iv:@ "521"  withNSData:[@ "我爱你"  dataUsingEncoding:NSUTF8StringEncoding]];
     NSString *aesEnStr = [Helper base64EncodedStringFrom:aesEnData];
     NSLog(@ "aesEnStr is %@" ,aesEnStr); //Log is HZKhnRLlQ8XjMjpelOAwsQ==
     NSData *aesDeData = [Helper AES128DecryptWithKey:@ "521"  iv:@ "521"  withNSData:aesEnData];
     NSString *aesDEStr = [Helper base64EncodedStringFrom:aesDeData];
     NSString *result = [Helper textFromBase64String:aesDEStr];
     NSLog(@ "aesDEStr is %@ and result is %@" ,aesDEStr,result); //Log is aesDEStr is 5oiR54ix5L2gAAAAAAAAAA== and result is 我爱你
     return  YES;
}

写到这里, 产生了一个问题, 就是上面的AES加密最终生成的Base64字符串和工具不一样 ,不知道是什么问题, 还请高手帮忙解答一下。

大家也可以尝试下网上其他人的代码

//AES可以参考一个链接 http://www.tuicool.com/articles/UVRjmyN

好了, 文章的最后,我们来简单学习和了解下cookie在客户端里的应用

首先带大家了解下什么是cookie吧

blob.png

这是维基百科里一段对cookie的描述,可见cookie是服务器生成的发给客户端,具体应用例如:我们打开淘宝的某一个页面,登陆了账号和密码, 当我们再跳转到其他淘宝界面的时候,我们不必每一次都重新登陆界面, 这就是cookie的作用, 其实cookie还能记录用户选的订单, 至于深一层的了解, 我还不是很清楚, 因为没有学过前端的开发,感兴趣的读者可以自行了解。

其实cookie也可以在客户端使用的。NSHTTPCookieStorage在iOS上是一个单例。那么首先我们通过代码的方式看看怎么添加cookie和删除cookie,

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
///增加cookies
+ (void)addCookiesToRequest:(NSMutableDictionary *)cookieDic
{
     NSEnumerator * enumeratorKey = [cookieDic keyEnumerator];
     for  (NSObject * key  in  enumeratorKey) {
         NSHTTPCookie *userInfoCookie = [NSHTTPCookie cookieWithProperties:
                                         [NSDictionary dictionaryWithObjectsAndKeys:
                                          @ ".baidu.com" , NSHTTPCookieDomain,
                                          @ "/" , NSHTTPCookiePath,
                                          [NSString stringWithFormat:@ "%@" ,key],  NSHTTPCookieName,
                                          [NSDate dateWithTimeIntervalSinceNow:30*24*3600], NSHTTPCookieExpires,
                                          [NSString stringWithFormat:@ "%@" ,[cookieDic objectForKey:key]], NSHTTPCookieValue,
                                          nil]];
         [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:userInfoCookie];
         NSHTTPCookie *txdaiCookie = [NSHTTPCookie cookieWithProperties:
                                         [NSDictionary dictionaryWithObjectsAndKeys:
                                          @ ".jingdong.com" , NSHTTPCookieDomain,
                                          @ "/" , NSHTTPCookiePath,
                                          [NSString stringWithFormat:@ "%@" ,key],  NSHTTPCookieName,
                                          [NSDate dateWithTimeIntervalSinceNow:30*24*3600], NSHTTPCookieExpires,
                                          [NSString stringWithFormat:@ "%@" ,[cookieDic objectForKey:key]], NSHTTPCookieValue,
                                          nil]];
         [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:txdaiCookie];
     }
}

同样删除cookie也非常简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
///删除基本cookies
+(void)deleteBaseCookie{
     NSHTTPCookie *passportCookie = [NSHTTPCookie cookieWithProperties:
                                     [NSDictionary dictionaryWithObjectsAndKeys:
                                      @ ".baidu.com" , NSHTTPCookieDomain,
                                      @ "/" , NSHTTPCookiePath,
                                      @ "sfut" ,  NSHTTPCookieName,
                                      @ "" , NSHTTPCookieValue,
                                      nil]];
     [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:passportCookie];
     NSHTTPCookie *txdaiCookie = [NSHTTPCookie cookieWithProperties:
                                  [NSDictionary dictionaryWithObjectsAndKeys:
                                   @ ".jingdong.com" , NSHTTPCookieDomain,
                                   @ "/" , NSHTTPCookiePath,
                                   @ "sfut" ,  NSHTTPCookieName,
                                   @ "" , NSHTTPCookieValue,
                                   nil]];
     [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:txdaiCookie];
}

那么最后一个问题就是我们在客户端什么情况下才添加或者删除cookie呢。

当我们的应用在加载一个wap页面的时候,可能wap需要知道客户端的一些信息, 比如你是登陆状态还是什么状态,因为这时候我们就可以设置cookie,wap可以拿到请求的cookie

当然需要注意的是在wap将要销毁的时候,要把cookie信息给移除掉。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/255384.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

iOS7以后,我们如何统计和跟踪用户

设备唯一标示&#xff0c;在App中&#xff0c;常用来统计和跟踪用户的行为。自从苹果在iOS5之后废弃掉了UDID后&#xff0c;找到一个稳定可用的设备标识一时成了业界棘手的问题&#xff0c;我们先看看目前的几种方案。 1 UDID UIDevice.uniqueIdentifier 接口在iOS 5.0被废弃 …

仿QQ变声功能的实现

Android ndk开发之QQ变声 要做出QQ变声的效果&#xff0c;用Android系统自带的MediaPlayer是无法实现的&#xff0c;只能另想他法了。听说汤姆猫是用SoundTouch实现的&#xff0c;而QQ是用FMOD实现的&#xff0c;就根据网上的教程&#xff0c;自己捣鼓ndk好几天&#xff0c;终…

iOS - 加解密(对称,非对称)(AES DES base64这里都有),数字签名,cookie

这篇文章不是研究性的东西&#xff0c;主要是简单的一些知识&#xff0c; 开篇如此&#xff0c; 我尽量不让读者失望。 首先罗列一些知识点&#xff1a; 1.加密算法通常分为对称性加密算法和非对称性加密算法&#xff1a;对于对称性加密算法&#xff0c;信息接收双方都需事先知…

ASP留言板(在一页里实现所有功能)

很久没发贴了&#xff0c;因为这些时间又在做&#xff21;&#xff33;&#xff30;的页面&#xff0c;没用dotnet&#xff0c;有时真有点过意不去了。唉&#xff01;中国现状呀&#xff01; 发一个&#xff21;&#xff33;&#xff30;留言板&#xff0c;当资料存着&#xff…

使用ffi-napi引入C++的dll

引言 这一篇将介绍如何在node.jselectron环境中, 使用node-ffi/ffi-napi调用C/C编写的动态链接库(即dll), 实现调用C/C代码。 本教程适用于electron 4.x-6.x版本。 如electron 4.2.10版本, electron 5.0.6版本, electron 6.0.10版本。 ffi 实现这个功能, 主要使用的插件是…

iOS各种设备识别码IDFA、UDID、UUID、MAC、OpenUDID、IDFV

今天在app服务端接口文档中看到2个接口名称&#xff0c;是和idfa相关的&#xff0c;就搜索了解了一下&#xff0c;顺便梳理了ios各种设备识别码。 *IDFA英文全称IdentifierforAdvertising&#xff0c;即广告标示符&#xff0c;目前是苹果生态内广告交易的主要标示符&#xff0…

RFID节点的编写

新项目开始咯&#xff0c;其实就是华清项目的换皮&#xff0c;增强了对传感器的控制加了大量的32采集与控制节点&#xff0c;由于时间紧迫先按照节点发布文章。以后有时间会发一些框架和整体数据流向分析的文章。 一、RFID节点框架 我的想法是使用超高频RFID技术&#xff0c;…

(七)DSP28335基础教程——I2C通信实验(OLED显示控制)

0 前言 本期实验目标&#xff1a;采用硬件I2C模块与OLED进行通信&#xff0c;完成显示控制。 目前发现28335比较缺乏关于I2C模块的实用例程&#xff0c;许多新手在配置使用该模块比较难上手&#xff0c;走弯路。那么通过该例程&#xff0c;大家则可以快速学会使用I2C的基本功…

安卓开发淘宝抢购界面!史上最全的Android面试题集锦,附带学习经验

前言 这是“拔剑金九银十”的第二篇文章&#xff0c;本文主要针对3年以上的Android开发者进阶面试中高级开发工程师而整理。 希望可以对你们有所帮助。不多废话&#xff0c;进入正题。 目录&#xff1a; Java中高级 计算机网络 Android高级面试—性能优化 Android优秀第三方…

Linux系统下imx6ull QT编程—— Ubuntu 下编写程序(一)

Linux QT编程 文章目录 Linux QT编程前言一、C简介二、C环境设置1.安装编译 C 语言和 C的环境。2.创建文件编写代码3.编译运行代码 总结 前言 绍在 Ubuntu 在终端窗口下使用 vi/vim 编辑一个 C源文件。通过编写最简单的示例“Hello,World QCX”。 一、C简介 C &#xff08;c…

0531最后的挣扎结束于传说中的段错误

部署训练后的缺陷检测模型 Linux Ubuntu18.04双机尝试 报错&#xff0c;Linux内核或是编译器版本不匹配&#xff0c;多次尝试更改18.04的gcc&#xff0c;g&#xff0c;gcc-arm-linux&#xff0c;garm-linux的代码&#xff0c;尝试在Makefile文件里更改编译器路径、添加LInux内…

用Python求最大公约数和最小公倍数(51)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 和猫妹学Python&#xff0c;一起趣味学编程。 今日主题 什么是最大公约数&#xff1f; 如何用Python求最大公约数&#xff1f; 什么是最小公倍数&#xff1f; 如何用Pyt…

PDF免费压缩、在线压缩

找了很多个网站&#xff0c;发现说是免费&#xff0c;其实不然。 在线上传&#xff0c;在线压缩&#xff0c;然后直接下载&#xff0c;没有任何套路。 PDF Compressor – Compress PDF Files OnlineThis online PDF compressor allows compressing PDF files without degradi…

PDF文件怎么压缩大小

PDF文件怎么压缩大小&#xff1f;3个办法实现一键压缩 相信大家在工作中&#xff0c;会收到许多的PDF文件&#xff0c;但随着时间的推移&#xff0c;PDF文件便会越积越多&#xff0c;最终导致我们的电脑内存严重不足&#xff0c;这时候只好把一些PDF文件删除&#xff0c;来释放…

【C#图解教程】第四章 类型、存储和变量 学习笔记总结

类型 C#是一组类型声明&#xff0c;这个与第三章&#xff1a;命名空间就是一组类型声明可以一起理解。类型是一个用来创建数据结构的模板&#xff1a; 使用这个模板创建对象的过程叫做实例化&#xff0c;所以创建的对象也叫实例 类型成员 简单类型可能只包含一个数据成员&…

chatgpt赋能python:Python中的%怎么用

Python中的%怎么用 Python中的%是一个非常重要的运算符&#xff0c;也称为格式化运算符。它用于将一个值插入到另一个字符串中。在本文中&#xff0c;我们将深入了解Python中的%运算符的使用。 %运算符的语法 先看下%运算符的语法&#xff1a; string % values其中&#xf…

Mongo帮助文档

来自&#xff1a;http://xiaoshan5634.iteye.com/blog/1117702 Mongo 适合场景&#xff1a; 网站数据&#xff1a;适合实时的插入&#xff0c;更新与查询&#xff0c;并具备网站实时数据存储所需的复制 及高度伸缩性。 缓存&#xff1a;适合作为信息基础设施的缓存层。在系…

Erlang/OTP设计原则(文档翻译)

http://erlang.org/doc/design_principles/des_princ.html 图和代码皆源自以上链接中Erlang官方文档&#xff0c;翻译时的版本为20.1。 这个设计原则&#xff0c;其实是说用户在设计系统的时候应遵循的标准和规范。阅读前我一直以为写的是作者在设计 Erlang/OTP 框架时的一些原…

Spring Cloud Alibaba 参考文档-2021.0.4.0

Spring Cloud Alibaba 简介依赖管理Spring Cloud Alibaba Nacos Discovery3.1 服务注册/发现&#xff1a;Nacos Discovery3.2 如何引入Nacos Discovery进行服务注册/发现3.3 使用Nacos Discovery进行服务注册/发现和调用的示例3.3.1 Nacos 服务器启动3.3.2. 启动供应商申请3.3.…

autojs 开发文档集合

加入我们的QQ群553908361,和各作者同群交流 教程会优先发布于收费脚本v群。 该代码选自于aj开发者的文档,群里有人反馈开发文档打开慢.所以做了这个.方便搜索.如有侵权,请私信我进行删除 同时也上传了一份源码到点击网站,供大家更快的查询代码 Auto.js Pro-8.1.0 文档 索引 | …