美文网首页
iOS 常见加密方式 - Base64

iOS 常见加密方式 - Base64

作者: 猴子的饼干 | 来源:发表于2019-04-16 22:42 被阅读0次

    Base64常用于字符的编码,将原始数据加密为不可读的字符,因其编码方式是完全公开的,所以称作“编码”更为贴切。

    详细的介绍可以参见:https://zh.wikipedia.org/wiki/Base64

    原理

    "3*8 = 4*6 "
    这是百度百科上的一句精简概括。具体可以理解为将数据每3个字符分为一组,转为二进制,每个字符为8bit。编码过程中,将二进制数据每6bit分割为一条,最后一条不足6bit时在低位补齐0,每4条为1组。
    通常情况下一个字节为8bit,所以分好组后还需要在每个字节的高位补齐0。当一组不够4个字符时,用“=”代替缺失的字符,最后再将转换后的二进制数据根据Base64对照表翻译成编码后的数据。
    所以,Base64加密后的数据比加密前的数据长了约4/3。

    Base64编码对照表如下:

    数值 字符 数值 字符 数值 字符 数值 字符
    0 A 16 Q 32 g 48 w
    1 B 17 R 33 h 49 x
    2 C 18 S 34 i 50 y
    3 D 19 T 35 j 51 z
    4 E 20 U 36 k 52 0
    5 F 21 V 37 l 53 1
    6 G 22 W 38 m 54 2
    7 H 23 X 39 n 55 3
    8 I 24 Y 40 o 56 4
    9 J 25 Z 41 p 57 5
    10 K 26 a 42 q 58 6
    11 L 27 b 43 r 59 7
    12 M 28 c 44 s 60 8
    13 N 29 d 45 t 61 9
    14 O 30 e 46 u 62 +
    15 P 31 f 47 v 63 /
    示例1 - 【编码】

    原始字符:
    Abc123*

    1.根据ascii码表翻译:
    65 98 99 49 50 51 42

    2.转换为二进制:
    01000001 01100010 01100011 00110001 00110010 00110011 00101010

    3.将数据以每6位分割为一项,不足6位的低位用0补齐,每四项为一组

    1 2 3 4
    010000 010110 001001 100011
    001100 010011 001000 110011
    001010 100000

    4.每项数据高位用“0”补齐至8位

    1 2 3 4
    00010000 00010110 00001001 00100011
    00001100 00010011 00001000 00110011
    00001010 00100000

    5.根据Base64码表将新的二进制翻译成数据,并将不足四项的组用‘=’补齐,得到加密后的数据

    1 2 3 4
    Q W J j
    M T I z
    K g = =

    加密后的数据: QWJjMTIzKg==

    示例2 - 【解码】

    熟悉了编码过程,想要得到原始数据只需逆向执行就好
    待解密数据:
    QWJjMTIzKg==

    1.将待解密的数字分组并根据Base64码表翻译成原始数据的二进制,并去掉补位用的"="以及高位补位所加上的0

    1 2 3 4
    010000 010110 001001 100011
    001100 010011 001000 110011
    001010 100000

    2.将数据每8位分割为一条,若有剩下不够分的部分直接舍弃掉,这是加密过程中为了补位所添加的

    01000001 01100010 01100011
    00110001 00110010 00110011
    00101010 0000

    3.将解密出来的二进制根据Ascii码表翻译出来就得到了原始数据
    65 98 99 49 50 51 42
    根据Ascii码表翻译为:
    Abc123*

    Tips:
    1、Base64的加密方式简易透明,容易被破解。在数据敏感时,通常会在加密前后添加各种处理,稍稍加大逆向解码的难度(毕竟不能指望仅仅依靠Base64来保证数据的安全)。
    2、为了适应多种环境,Base64编码也有多种版本(UTF-7, IRCu, URL)。

    iOS中的应用

    iOS中提供了系统方法予以支持,使用方式十分简便:

    编码

            NSString * string = @"Abc123*";
            NSData * data = [string dataUsingEncoding:NSUTF8StringEncoding];
            NSString * encodeString = [data base64EncodedStringWithOptions:0];
            NSLog(@"%@", encodeString);
            //输出: QWJjMTIzKg==
    
    

    解码

            NSData * decodeData = [[NSData alloc] initWithBase64EncodedString:encodeString
                                                                       options:0];
            NSString * decodeString = [[NSString alloc] initWithData:decodeData
                                                             encoding:NSUTF8StringEncoding];
            NSLog(@"%@", decodeString);
            //输出: Abc123*
    

    自己实现一个Base64编码器

    以下代码比较粗糙,仅供参考

    // NSString+Base64.h
    @interface NSString (Base64)
    - (NSString *)encodeWithBase64;
    - (NSString *)decodeWithBase64;
    @end
    
    
    // NSString+Base64.m
    @implementation NSString (Base64)
    - (NSString *)encodeWithBase64 {
        
        //转换成二进制串
        const char * cString = [self cStringUsingEncoding:NSASCIIStringEncoding];
        char * tempData = malloc(sizeof(cString) * 9 * sizeof(char *));
        for (int index = 0; index < strlen(cString); index += 1) {
            
            int asciiCode = cString[index] ;
            char * binaryCode = [self convertBinaryCodeWithValue:asciiCode];
            strcat(tempData, binaryCode);
            free(binaryCode);
        }
        
        //按照 "6 * 3 = 8 * 4"的规则进行划分
        char * tempBuff = malloc(self.length * sizeof(char *));;
        int lenth = (int)strlen(tempData);
        for (int index = 0; index < lenth; index += 6) {
            char temp6[7];
            strncpy(temp6, tempData+index, 6);
            temp6[6] = '\0';
            
            char * temp8 = malloc(9 * sizeof(char *));
            temp8[0] = '0';
            temp8[1] = '0';
            temp8[2] = '\0';
            strcat(temp8, temp6);
            
            int lenth = (int)strlen(temp8);
            //不足8位补齐
            if (lenth < 8) {
                char * blank = "00000000";
                char * blankBuff = malloc(9 * sizeof(char *));
                strncpy(blankBuff, blank+lenth, 8 - lenth);
                strcat(temp8, blankBuff);
                free(blankBuff);
            }
            
            //对照Base64编码表转码
            tempBuff[index / 6] = [self transformBase64CodeWithValue:temp8];
            
            if (index + 6 > lenth) {
                tempBuff[index / 6 + 1] = '\0';
            }
            free(temp8);
        }
        
        NSString * base64String = [NSString stringWithCString:tempBuff encoding:NSUTF8StringEncoding];
        int equlNum = base64String.length % 4;
        if (equlNum != 0) {
            NSString * equlString = equlNum == 1 ? @"=" : (equlNum == 2 ? @"==" : @"===");
            return [base64String stringByAppendingString:equlString];
        }
        return base64String;
    }
    
    - (NSString *)decodeWithBase64 {
        //转换成二进制串
        NSString * string = [self stringByReplacingOccurrencesOfString:@"=" withString:@""];
        const char * cString = [string cStringUsingEncoding:NSASCIIStringEncoding];
        char * tempData = malloc(sizeof(cString) * 6 * sizeof(char *));
        for (int index = 0; index < strlen(cString); index += 1) {
            //根据base64编码表查询出对应的编号
            char base64Character = [self getNumWithBase64Character:cString[index]];
            //获取编号的二进制
            char * binaryCode = [self convertBinaryCodeWithValue:base64Character];
            //去掉编码时补位的0
            char * code = &binaryCode[2];
            strcat(tempData, code);
            free(binaryCode);
        }
        
        //获取原始数据的二进制并转换出原始字符
        char * tempBuff = malloc(self.length * sizeof(char *));
        for (int index = 0; index < strlen(tempData); index += 8) {
            char * tureBinaryCode = malloc(8 * sizeof(char *));
            strncpy(tureBinaryCode, tempData+index, 8);
            int asciiCode = [self convertValueWithBinaryCode:tureBinaryCode];
            char asciiCharacter = (char)asciiCode;
            tempBuff[index / 8] = asciiCharacter;
            if (index + 8 > strlen(tempData)) {
                tempBuff[index + 1] = '\0';
            }
        }
        
        NSString * resourceString = [NSString stringWithCString:tempBuff encoding:NSUTF8StringEncoding];
        return resourceString;
    }
    
    - (char)transformBase64CodeWithValue:(char *)value {
        int num = [self convertValueWithBinaryCode:value];
        char data = [self getBase64CodeWithNum:num];
        return data;
    }
    
    
    ///////////////////////////////////////////////////////////
    //Tools
    
    
    //base64码表
    - (char)getBase64CodeWithNum:(int)num {
        char * codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmoopqrstuvwxyz+/";
        return codes[num];
    }
    
    - (int)getNumWithBase64Character:(char)character {
        char * codes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmoopqrstuvwxyz+/";
        int index = -1;
        int lenth = (int)strlen(codes);
        while(index < lenth) {
            char value = codes[index];
            if (value == character) {
                return index;
            }
            index += 1;
        }
        return index;
    }
    
    
    //十进制转换为二进制
    - (char *)convertBinaryCodeWithValue:(int)value {
        char * tempCode = malloc(9 * sizeof(char *));
        int tempValue = value;
        
        int index = 0;
        while (index <= 7) {
            if (tempValue != 0) {
                char value = tempValue % 2 + '0';
                tempCode[7 - index] = value;
                tempValue = tempValue / 2;
            } else {
                tempCode[7 - index] = '0';
            }
            index += 1;
        }
        tempCode[index] = '\0';
        return tempCode;
    }
    
    //将二进制转换为十进制
    - (int)convertValueWithBinaryCode:(char *)value {
        int lenth = (int)strlen(value);
        int tempValue = 0;
        
        for (int index = 1; index <= lenth; index += 1) {
            char numChar = value[index];
            int num = atoi(&numChar);
            if (num == 1) {
                tempValue += pow(2, lenth - index - 1);
            }
        }
    
        return tempValue;
    }
    @end
    

    都看到这里了,觉得还行的话就点个赞吧 : )

    相关文章

      网友评论

          本文标题:iOS 常见加密方式 - Base64

          本文链接:https://www.haomeiwen.com/subject/jswtwqtx.html