美文网首页
iOS 逆向开发10:对称加密

iOS 逆向开发10:对称加密

作者: differ_iOSER | 来源:发表于2021-08-19 15:28 被阅读0次

    iOS 逆向开发 文章汇总

    一、对称加密

    对称加密方式:明文通过密钥加密得到密文。密文通过相同的密钥解密得到明文。

    1.1 常见的对称加密算法

    • DES:数据加密标准(用得少,因为强度不够)
    • 3DES:使用3个密钥,对相同的数据执行3次加密,强度增强(很少使用)
    • AES:高级密码标准(苹果钥匙串访问使用)

    1.2 应用模式

    • ECB(Electronic Code Book):电子密码本模式。每一块数据,独立加密。
      • 最基本的加密模式,也就是通常理解的加密,相同的明文将永远加密成相同的密文,无初始向量,容易受到密码本重放攻击,一般情况下很少用。
    • CBC(Cipher Block Chaining):密码分组链接模式。使用一个密钥和一个初始化向量[IV]对数据执行加密。
      • 明文被加密前要与前面的密文进行异或运算后再加密,因此只要选择不同的初始向量,相同的密文加密后会形成不同的密文,这是目前应用最广泛的模式。CBC加密后的密文是上下文相关的,如果一个分组丢失,后面的分组将全部作废(同步错误)。
      • CBC可以有效的保证密文的完整性,如果一个数据块在传递是丢失或改变,后面的数据将无法正常解密。

    1.3 DES / AES 终端命令:

    /**
     *  终端测试指令
     *
     *  DES(ECB)加密“hello”字符串
     *  $ echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64
     *
     *  DES(CBC)加密“hello”字符串
     *  $ echo -n hello | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
     *
     *  AES(ECB)加密
     *  $ echo -n hello | openssl enc -aes-128-ecb -K 616263 -nosalt | base64
     *
     *  AES(CBC)加密
     *  $ echo -n hello | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt | base64
     *
     *  DES(ECB)解密
     *  $ echo -n HQr0Oij2kbo= | base64 -D | openssl enc -des-ecb -K 616263 -nosalt -d
     *
     *  DES(CBC)解密
     *  $ echo -n alvrvb3Gz88= | base64 -D | openssl enc -des-cbc -iv 0102030405060708 -K 616263 -nosalt -d
     *
     *  AES(ECB)解密
     *  $ echo -n d1QG4T2tivoi0Kiu3NEmZQ== | base64 -D | openssl enc -aes-128-ecb -K 616263 -nosalt -d
     *
     *  AES(CBC)解密
     *  $ echo -n u3W/N816uzFpcg6pZ+kbdg== | base64 -D | openssl enc -aes-128-cbc -iv 0102030405060708 -K 616263 -nosalt -d
     *
     *  提示:
     *      1> 加密过程是先加密,再base64编码
     *      2> 解密过程是先base64解码,再解密
     */
    

    1.3 DES / AES 代码加密:

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 指定算法为AES
        [EncryptionTools sharedEncryptionTools].algorithm = kCCAlgorithmAES;
        
        /** AES - ECB加密 */
        NSString *key = @"abc";
        NSString *encStr = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:nil];
        NSLog(@"加密的结果是%@",encStr);
        
        //AES - CBC 加密
        uint8_t iv[8] = {1,2,3,4,5,6,7,8};
        NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
        
        
        NSLog(@"加密的结果是%@",[[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:key iv:ivData]);
        
        NSLog(@"解密的结果是%@",[[EncryptionTools sharedEncryptionTools] decryptString:@"u3W/N816uzFpcg6pZ+kbdg==" keyString:key iv:ivData]);
    }
    

    #import "EncryptionTools.h" --->文末

    使用系统CCCrypt加密算法安全隐患:改变系统函数实现和断住系统函数非常容易。1.可以在入参之前将明文按位异或,解密后再异或一次;2.OC方法名混淆









    EncryptionTools.h

    @interface EncryptionTools : NSObject
        
    + (instancetype)sharedEncryptionTools;
        
        /**
         @constant   kCCAlgorithmAES     高级加密标准,128位(默认)
         @constant   kCCAlgorithmDES     数据加密标准
         */
        @property (nonatomic, assign) uint32_t algorithm;
        
        /**
         *  加密字符串并返回base64编码字符串
         *
         *  @param string    要加密的字符串
         *  @param keyString 加密密钥
         *  @param iv        初始化向量(8个字节)
         *
         *  @return 返回加密后的base64编码字符串
         */
    - (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
        
        /**
         *  解密字符串
         *
         *  @param string    加密并base64编码后的字符串
         *  @param keyString 解密密钥
         *  @param iv        初始化向量(8个字节)
         *
         *  @return 返回解密后的字符串
         */
    - (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv;
    
    @end
    

    EncryptionTools.m

    @interface EncryptionTools()
    @property (nonatomic, assign) int keySize;
    @property (nonatomic, assign) int blockSize;
    @end
    
    @implementation EncryptionTools
        
    + (instancetype)sharedEncryptionTools {
        static EncryptionTools *instance;
        
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[self alloc] init];
            instance.algorithm = kCCAlgorithmAES;
        });
        
        return instance;
    }
        
    - (void)setAlgorithm:(uint32_t)algorithm {
        _algorithm = algorithm;
        switch (algorithm) {
            case kCCAlgorithmAES:
            self.keySize = kCCKeySizeAES128;
            self.blockSize = kCCBlockSizeAES128;
            break;
            case kCCAlgorithmDES:
            self.keySize = kCCKeySizeDES;
            self.blockSize = kCCBlockSizeDES;
            break;
            default:
            break;
        }
    }
        
    - (NSString *)encryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
        
        
        // 设置秘钥
        NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
        uint8_t cKey[self.keySize];
        bzero(cKey, sizeof(cKey));
        [keyData getBytes:cKey length:self.keySize];
        
        // 设置iv
        uint8_t cIv[self.blockSize];
        bzero(cIv, self.blockSize);
        int option = 0;
        if (iv) {
            [iv getBytes:cIv length:self.blockSize];
            option = kCCOptionPKCS7Padding;
        } else {
            /**
             kCCOptionPKCS7Padding | kCCOptionECBMode  ECB 的模式
             kCCOptionPKCS7Padding                     CBC 的加密
             */
            option = kCCOptionPKCS7Padding | kCCOptionECBMode;
        }
        
        // 设置输出缓冲区
        NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
        size_t bufferSize = [data length] + self.blockSize;
        void *buffer = malloc(bufferSize);
        
        // 开始加密
        size_t encryptedSize = 0;
        //加密解密都是它 -- CCCrypt
        
        /**
         1.kCCEncrypt 加密/kCCDecrypt解密
         2.加密算法
         3.加密选项  ECB/CBC
         4.KEY 的地址
         5.KEY 的长度
         6.iv 初始化向量
         7.加密的数据(地址)
         8.加密的数据长度
         9.密文的内存地址
         10.密文缓冲区的大小
         11.加密结果大小
         */
        CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                              self.algorithm,
                                              option,
                                              cKey,
                                              self.keySize,
                                              cIv,
                                              [data bytes],
                                              [data length],
                                              buffer,
                                              bufferSize,
                                              &encryptedSize);
        
        NSData *result = nil;
        if (cryptStatus == kCCSuccess) {
            result = [NSData dataWithBytesNoCopy:buffer length:encryptedSize];
        } else {
            free(buffer);
            NSLog(@"[错误] 加密失败|状态编码: %d", cryptStatus);
        }
        
        return [result base64EncodedStringWithOptions:0];
    }
        
    - (NSString *)decryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
        
        // 设置秘钥
        NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
        uint8_t cKey[self.keySize];
        bzero(cKey, sizeof(cKey));
        [keyData getBytes:cKey length:self.keySize];
        
        // 设置iv
        uint8_t cIv[self.blockSize];
        bzero(cIv, self.blockSize);
        int option = 0;
        if (iv) {
            [iv getBytes:cIv length:self.blockSize];
            option = kCCOptionPKCS7Padding;
        } else {
            option = kCCOptionPKCS7Padding | kCCOptionECBMode;
        }
        
        // 设置输出缓冲区
        NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
        size_t bufferSize = [data length] + self.blockSize;
        void *buffer = malloc(bufferSize);
        
        // 开始解密
        size_t decryptedSize = 0;
        CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                              self.algorithm,
                                              option,
                                              cKey,
                                              self.keySize,
                                              cIv,
                                              [data bytes],
                                              [data length],
                                              buffer,
                                              bufferSize,
                                              &decryptedSize);
        
        NSData *result = nil;
        if (cryptStatus == kCCSuccess) {
            result = [NSData dataWithBytesNoCopy:buffer length:decryptedSize];
        } else {
            free(buffer);
            NSLog(@"[错误] 解密失败|状态编码: %d", cryptStatus);
        }
        
        return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
    }
        
    @end
    

    相关文章

      网友评论

          本文标题:iOS 逆向开发10:对称加密

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