序言
Base64 编码
原理
Base64 编码会把 3 字节的二进制数据编码为 4 字节的数据,长度增加 33% 。如果要编码的二进制数据不是 3 的倍数,Base64 会用 \x00 字节在末尾补齐,然后在末尾加上1、2个 = 号,表示补的字节数。例如:
需要加密的数据:s 1 3
对应的 ascii:115 49 51
2进制: 01110011 00110001 00110011
转换:每三个字节转换成四个字节
转换后: 011100.11 0011.0001 00.110011 (标点处分割)
转换后: 011100 110011 000100 110011
高两位自动补0
最终数据: 00011100 00110011 00000100 00110011
得到 28 51 4 51
查对下照表 c z E z
iOS下有两种比较常见的 Base64 编码方式
第一种:iOS自带的编码方式
这里我写了一个分类,可以直接对字符串编码、解码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #import "NSString+VCHBase64.h"
@implementation NSString (VCHBase64)
- (NSString *)vch_base64Encode { NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; return [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; }
- (NSString *)vch_base64Decode { NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:NSDataBase64DecodingIgnoreUnknownCharacters]; return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; } @end
|
第二种:用 Google 的 GTMBase64
可以直接在GitHub上搜索。下面的 Demo 里面也有。
MD5 加密
加密代码
1 2 3 4 5 6 7 8 9 10 11 12
| #import <CommonCrypto/CommonDigest.h>
- (NSString *)vch_md5 { const char *cStr = [self UTF8String]; unsigned char digest[CC_MD5_DIGEST_LENGTH]; CC_MD5(cStr, (uint32_t)strlen(cStr), digest); NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2]; for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { [output appendFormat:@"%02x", digest[i]]; } return output; }
|
MD5 加密一般是不可解密的,但可以通过穷举法解密(就是一个一个去匹配)。我们可以给 MD5 加个数字,然后再加密一次,那么这样加密后就基本无法再解密出来了。
AES 加密
AES 加密、解密需要同一个密钥,这种加密方法称为单密钥加密,也称对称加密。
AES 有多种加密方式(ECB、CBC、CFB、OFB),如果使用 CBC 方式加密,那么还需要提供密钥偏移量 IV 这个值。
AES 可以采用128位 或者 256位的加密方式。
下面代码采用了 AES256 CBC 模式。
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
| #import "NSString+VCHAES.h" #import <CommonCrypto/CommonCryptor.h>
@implementation NSString (VCHAES)
- (NSString *)vch_AESEncryptWithKey:(NSString *)key iv:(NSString *)iv { NSData *data = [self dataUsingEncoding:NSUTF8StringEncoding]; NSData *encryptData = [self AES256operation:kCCEncrypt data:data key:key iv:iv]; NSString *encryptString = [encryptData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; return encryptString; }
- (NSString *)vch_AESDecryptWithKey:(NSString *)key iv:(NSString *)iv { NSData *data = [[NSData alloc] initWithBase64EncodedString:self options:NSDataBase64DecodingIgnoreUnknownCharacters]; NSData *decryptData = [self AES256operation:kCCDecrypt data:data key:key iv:iv]; NSString *decryptString = [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding]; return decryptString; }
- (NSData *)AES256operation:(CCOperation)operation data:(NSData *)data key:(NSString *)key iv:(NSString *)iv { char keyPtr[kCCKeySizeAES256 + 1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; char ivPtr[kCCKeySizeAES256 + 1]; bzero(ivPtr, sizeof(ivPtr)); [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; size_t bufferSize = [data length] + kCCKeySizeAES256; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptorStatus = CCCrypt(operation, kCCAlgorithmAES, kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES256, ivPtr, [data bytes], [data length], buffer, bufferSize, &numBytesEncrypted); if(cryptorStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); return nil; } @end
|
这里的 key 和 iv ,是由加密者提供的。
Demo
Github Demo