美文网首页
iOS--对称加密的演示,终端和代码分别演示,AES,DES

iOS--对称加密的演示,终端和代码分别演示,AES,DES

作者: OXHO | 来源:发表于2019-05-07 02:01 被阅读0次

    终端演示

    OpenSSL

    以DES为例,列举

    DES-ecb加密“message.txt”

    message.txt内容如下:

    helloworld
    helloworld
    helloworld
    helloworld
    helloworld
    helloworld
    
    $ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg.bin
    

    -enc 代表对称加密算法
    -aes 表示算法;
    -ecb 表示模式
    -K 616263 表示密钥, 等同于小写的“abc”,为什么等于abc,ASCII码
    -nosalt 不加盐
    -out 输出
    -msg.bin 输出的文件名字

    DES加密“message1.txt”

    message.txt内容如下:

    helloworld
    helloworld
    helloworld
    helloworle
    helloworld
    helloworld
    
    $ openssl enc -des-ecb -K 616263 -nosalt -in message.txt -out msg1.bin
    

    利用命令xxd可以查看

    $ xxd msg1.bin
    
    图2

    观察图2,我们可以看到加密之后有哪些不同的地方。

    DES-cbc加密“message.txt”

    message.txt ,message1.txt 内容不变

    message.txt生成msg3.bin:
    $ openssl enc -des-cbc -iv 123456789  -K 616263 -nosalt -in message.txt -out msg3.bin
    

    和ecb相比,多了一个参数iv
    -iv 12345678 表示一个向量
    现代密码学里面,都会和几何有关,几何里面的变化,都是有规律,结果又是多变的。

    message1.txt生成msg4.bin:
    $ openssl enc -des-cbc -iv 123456789  -K 616263 -nosalt -in message1.txt -out msg4.bin
    
    图3

    观察图3,我们可以看到改变的数据之后,全部发生了变化。
    这就是cbc,所有的加密都依赖于前面数据,一个地方改变,后续的所有数据都变了。

    代码演示

    (注:苹果给我们提供的对称加密算法有很多,在此仅以AES,DES为例)

    苹果官方给出的枚举
    enum {
        /* AES */
        kCCBlockSizeAES128        = 16,
        /* DES */
        kCCBlockSizeDES           = 8,
        /* 3DES */
        kCCBlockSize3DES          = 8,
        /* CAST */
        kCCBlockSizeCAST          = 8,
        kCCBlockSizeRC2           = 8,
        kCCBlockSizeBlowfish      = 8,
    };
    

    EncryptionTools.h文件:

    #import <Foundation/Foundation.h>
    #import <CommonCrypto/CommonCrypto.h>
    
    /**
     *  终端测试指令
     *
     *  DES(ECB)加密
     *  $ echo -n hello | openssl enc -des-ecb -K 616263 -nosalt | base64
     *
     * DES(CBC)加密
     *  $ 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解码,再解密
     */
    @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文件:

    #import "EncryptionTools.h"
    
    @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 {
            option = kCCOptionPKCS7Padding | kCCOptionECBMode;
        }
        
        // 设置输出缓冲区
        NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
        size_t bufferSize = [data length] + self.blockSize;
        void *buffer = malloc(bufferSize);
        
        // 开始加密
        size_t encryptedSize = 0;
        //加密解密都是它 -- CCCrypt
        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
    
    

    演示例子:

    /**
         AES-ECB
         */
        NSString *key = @"abc";//终端演示的时候,616263
        NSString *encStrA = [[EncryptionTools sharedEncryptionTools]encryptString:@"hello" keyString:key iv:nil];//ECB没有向量,所以iv传nil
        NSLog(@"AES-ECB加密的结果:%@",encStrA);
        NSLog(@"AES-ECB解密的结果:%@",[[EncryptionTools sharedEncryptionTools] decryptString:encStrA keyString:key iv:nil]);
        /**
         AES-CBC
         */
        uint8_t iv[8] = {1,2,3,4,5,6,7,8};
        NSData *ivData = [NSData dataWithBytes:iv length:sizeof(iv)];
         NSString *encStrB = [[EncryptionTools sharedEncryptionTools] encryptString:@"hello" keyString:@"abc" iv:ivData];
         NSLog(@"AES-CBC加密的结果:%@",encStrB);
        NSLog(@"AES-CBC解密的结果:%@",[[EncryptionTools sharedEncryptionTools] decryptString:encStrB keyString:@"abc" iv:ivData]);
        
    

    重点!

    最最重要的一点,其中最重要的函数就是CCCrypt函数:
    iOS--CCCrypt函数

    相关文章

      网友评论

          本文标题:iOS--对称加密的演示,终端和代码分别演示,AES,DES

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