開篇應(yīng)該先說明一下這是我寫的第一篇技術(shù)博客贮喧,水平高低的大家多提寶貴意見筒狠。
最近做的一個(gè)和藍(lán)牙交互的iOS APP,其中中用到了各種各樣的加密和驗(yàn)證箱沦,包括:Base64 加解密辩恼、MD5 加密、DES 加解密谓形、AES加解密灶伊、CRC驗(yàn)證等,其中還有16進(jìn)制寒跳,ASCII碼聘萨,NSdata 等各種數(shù)據(jù)之間的轉(zhuǎn)換,而且也還用到了Socket 傳輸數(shù)據(jù)童太,涉及到的技術(shù)點(diǎn)比較多米辐,這篇文章就簡單總結(jié)一下加解密之間的問題吧。
- Base 64 加解密
Base 64 加解密 沒有什么好說的书释,系統(tǒng)自帶的辦法就可以解決了翘贮,或者使用 第三方GTMBase64
//Base64加密
+(NSString *)encodeBase64:(NSString *)input{
NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
data = [GTMBase64 encodeData:data];
NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"encodeBase64 == %@",base64String);
return base64String;
}
//Base64編碼
+(NSString *)base64EncodeString:(NSString *)string
{
//1.先把字符串轉(zhuǎn)換為二進(jìn)制數(shù)據(jù)
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
//2.對二進(jìn)制數(shù)據(jù)進(jìn)行base64編碼,返回編碼后的字符串
//這是蘋果已經(jīng)給我們提供的方法
NSString *str = [data base64EncodedStringWithOptions:0];
return str;
}
//Base64解密
+(NSString *)decodeBase64:(NSString *)input{
NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
data = [GTMBase64 decodeData:data];
NSString *base64String = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"decodeBase64 == %@",base64String);
return base64String;
}
//對base64編碼后的字符串進(jìn)行解碼
+(NSString *)base64DecodeString:(NSString *)string
{
//1.將base64編碼后的字符串『解碼』為二進(jìn)制數(shù)據(jù)
//這是蘋果已經(jīng)給我們提供的方法
NSData *data = [[NSData alloc]initWithBase64EncodedString:string options:0];
//2.把二進(jìn)制數(shù)據(jù)轉(zhuǎn)換為字符串返回
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
return str;
}
//Base64 字符串解碼成 字符串
+(NSString *)decodeBase64ToHexString:(NSString *)input{
//1.將base64編碼后的字符串『解碼』為二進(jìn)制數(shù)據(jù)
//這是蘋果已經(jīng)給我們提供的方法
NSData *myD = [[NSData alloc]initWithBase64EncodedString:input options:0];
Byte *bytes = (Byte *)[myD bytes];
//下面是Byte 轉(zhuǎn)換為16進(jìn)制征冷。
NSString *hexStr=@"";
for(int i=0;i<[myD length];i++)
{
NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];///16進(jìn)制數(shù)
if([newHexStr length]==1)
hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
else
hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
}
return hexStr;
}
- DES加解密
DES 加密的原理網(wǎng)上有好多解釋择膝,在這里就不在多說检激。
可以參考: https://www.zhihu.com/question/36767829
要使用DES加密肴捉,首先必須要引入 <CommonCrypto/CommonCrypto.h>
我們常用的無非就是下面的這種加密方法:其中 plainText 使我們要傳的 數(shù)據(jù) Nsdata , key 是我們加密的 秘鑰,是Byte格式的脖卖。
//DES 加密
+(NSData *)encryptUseDES:(NSData *)plainText key:(Byte *)key
{
NSData *textData = plainText;
NSUInteger dataLength = [textData length];
unsigned char buffer[1024];
memset(buffer, 0, sizeof(char));
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
kCCOptionECBMode,
key, kCCKeySizeDES,
nil,
[textData bytes], dataLength,
buffer, 1024,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];
return data;
}
return nil;
}
//DES 解密
+(NSData *)decrypUseDES:(NSData *)plainText key:(Byte *)key{
NSData *cipherdata = plainText;
unsigned char buffer[1024];
memset(buffer, 0, sizeof(char));
size_t numBytesDecrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES,
kCCOptionECBMode,
key, kCCKeySizeDES,
nil,
[cipherdata bytes], [cipherdata length],
buffer, 1024,
&numBytesDecrypted);
if(cryptStatus == kCCSuccess)
{
NSData *plaindata = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesDecrypted];
return plaindata;
}
return nil;
}
- MD5加密
MD5 (Message Digest Algorithm MD5)是一種不可逆的加密方式围俘,用于確保信息傳輸完整一致。是計(jì)算機(jī)廣泛使用的雜湊算法之一楷拳。網(wǎng)上那些可以看到的解密MD5的都是自建了一個(gè)龐大的MD5加密之后結(jié)果的數(shù)據(jù)庫绣夺,當(dāng)解密的時(shí)候去查找吏奸,而并不是真正的解密欢揖。
MD5其實(shí)進(jìn)過算法產(chǎn)生的是固定的128bit,即128個(gè)0和1的二進(jìn)制位奋蔚,而在實(shí)際應(yīng)用開發(fā)中她混,通常是以16進(jìn)制輸出的,所以正好就是32位的16進(jìn)制泊碑,說白了也就是32個(gè)16進(jìn)制的數(shù)字坤按。
如下,是MD5的 返回Nsdata 的加密方法馒过。
//MD5加密返回Nsdata
+(NSData *)encodeMD5:(NSData *)input{
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(input.bytes, (CC_LONG)input.length, result);
NSData *data =[[NSData alloc] initWithBytes:result length:CC_MD5_DIGEST_LENGTH];
return data;
}
如下臭脓,生成是小寫的MD5的字符串,如果要生成大寫的腹忽,只需要把
[ret appendFormat:@"%02X",result[i]];
中的 "%02X"
的 X
改成小寫的 x
即可来累。
//MD5加密返回Nsstring
+(NSString *)MD5HexDigest:(NSData *)input {
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(input.bytes, (CC_LONG)input.length, result);
NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
for (int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
[ret appendFormat:@"%02X",result[i]];
}
return ret;
}
如上窘奏, 其中%02x是格式控制符:‘x’表示以16進(jìn)制輸出嘹锁,‘02’表示不足兩位,前面補(bǔ)0着裹;如‘f’輸出為0f,‘1f3’則輸出1f3; 其實(shí)
CC_MD5_DIGEST_LENGTH
等于16面粮,也就是說我們定義了一個(gè)字符數(shù)組result但金,并且是 16位的。那為什么是[16]呢梦裂,這是因?yàn)镸D5算法最后生成的是128位,而在計(jì)算機(jī)的最小存儲(chǔ)單位為字節(jié)年柠,1個(gè)字節(jié)是8位答憔,對應(yīng)一個(gè)char類型,計(jì)算可得需要16個(gè)char虐拓。所以result是[16]。
那么為什么輸出的格式一定是%02x呢态兴,而不是其它呢瞻润。這也是有原因的:因?yàn)榧s定MD5一般是以16進(jìn)制的格式輸出绍撞,那么其實(shí)這個(gè)問題就轉(zhuǎn)換為把128個(gè)0和1以16進(jìn)制來表示,每4位二進(jìn)制對應(yīng)一個(gè)16進(jìn)制的元素矾柜,則需要32個(gè)16進(jìn)制的元素里覆,如果元素全部為0喧枷,放到char的數(shù)組中弓坞,正常是不會(huì)輸出渡冻,如00001111帽借,以%x輸出砍艾,則是f,那么就會(huì)丟失0;但如果以%02x表示則輸出結(jié)果是0f禀综,正好是轉(zhuǎn)換的正確結(jié)果定枷。
- 補(bǔ)充:NSdata 和 Byte 互相轉(zhuǎn)換
Nsdata ->Byte
NSData *testData = [[NSData alloc]init];
Byte *testByte = (Byte *)[testData bytes];
Byte ->NSdata
Byte bytes[]= {0X01,0X02,0X03,0X04,0X05,0X06};
NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)];
代碼已經(jīng)上傳到GitHub:https://github.com/AmdyTeng/iOS-Encrypt
歡迎提出寶貴意見欠窒,不吝嗇的話來個(gè)Star岖妄,哈哈