• iOS常用加密之RSA加密解密


    前言:

    iOS常用的加密有很多种,前两天在工作中遇到了RSA加密,现在把代吗分享出来。

    RSA基本原理

    RSA使用"秘匙对"对数据进行加密解密.在加密解密数据前,需要先生成公钥(public key)和私钥(private key).

    • 公钥(public key): 用于加密数据. 用于公开, 一般存放在数据提供方, 例如iOS客户端.
    • 私钥(private key): 用于解密数据. 必须保密, 私钥泄露会造成安全问题

    第一步:公钥、私钥的生成

    iOS开发者可直接在Mac终端生成,命令如下,生成公钥der文件的时候需要填写国家地区等基本信息,也可直接忽略不填。生成私p12文件的时候需要填写密码,这个必填而且要记住,后面会用得着。

    // 生成1024位私钥
    openssl genrsa -out private_key.pem 1024
    // 根据私钥生成CSR文件
    openssl req -new -key private_key.pem -out rsaCertReq.csr
    // 根据私钥和CSR文件生成crt文件
    openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt

    // 为IOS端生成公钥der文件
    openssl x509 -outform der -in rsaCert.crt -out public_key.der

    // 将私钥导出为这p12文件
    openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt

    第二步:加密相关的代码

    在加密加密的时候需要定义公有变量公钥和私钥

        SecKeyRef _publicKey;
        SecKeyRef _privateKey;

    加密相关的代码

     1 #pragma mark - 加密相关
     2 //用本地证书加载公钥
     3 - (void)loadPublicKeyWithPath:(NSString *)derFilePath
     4 {
     5     NSData *derData = [[NSData alloc] initWithContentsOfFile:derFilePath];
     6     if (derData.length > 0)
     7     {
     8         [self loadPublicKeyWithData:derData];
     9     }
    10     else
    11     {
    12         NSLog(@"load public key fail with path: %@", derFilePath);
    13     }
    14 }
    15 //加载公钥方法
    16 - (void)loadPublicKeyWithData:(NSData *)derData
    17 {
    18     SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)derData);
    19     SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
    20     SecTrustRef myTrust;
    21     OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
    22     SecTrustResultType trustResult;
    23     if (status == noErr) {
    24         status = SecTrustEvaluate(myTrust, &trustResult);
    25     }
    26     
    27     SecKeyRef securityKey = SecTrustCopyPublicKey(myTrust);  CFRelease(myCertificate);  CFRelease(myPolicy);  CFRelease(myTrust);
    28     
    29     _publicKey = securityKey;
    30 }
    31 
    32 
    33 //将文本内容加密
    34 - (NSString *)rsaEncryptText:(NSString *)text
    35 {
    36     NSData *encryptedData = [self rsaEncryptData:[text dataUsingEncoding:NSUTF8StringEncoding]];
    37     NSString *base64EncryptedString = [encryptedData base64EncodedStringWithOptions:0];
    38     return base64EncryptedString;
    39 }
    40 
    41 
    42 //分段再加密数据
    43 - (NSData *)rsaEncryptData:(NSData *)data
    44 {
    45     SecKeyRef key = _publicKey;
    46     
    47     size_t cipherBufferSize = SecKeyGetBlockSize(key);
    48     uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
    49     size_t blockSize = cipherBufferSize - 11;
    50     size_t blockCount = (size_t)ceil([data length] / (double)blockSize);
    51     NSMutableData *encryptedData = [[NSMutableData alloc] init] ;
    52     for (int i = 0; i < blockCount; i++)
    53     {
    54         size_t bufferSize = MIN(blockSize,[data length] - i * blockSize);
    55         NSData *buffer = [data subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];
    56         OSStatus status = SecKeyEncrypt(key, kSecPaddingPKCS1,(const uint8_t *)[buffer bytes],[buffer length],cipherBuffer,&cipherBufferSize);
    57         if (status == noErr)
    58         {
    59             NSData *encryptedBytes = [[NSData alloc] initWithBytes:(const void *)cipherBuffer length: cipherBufferSize];
    60             [encryptedData appendData:encryptedBytes];
    61         }
    62         else
    63         {
    64             if (cipherBuffer) {
    65                 free(cipherBuffer);
    66             }      return nil;
    67         }
    68         
    69     }
    70     if (cipherBuffer)
    71     {
    72         free(cipherBuffer);
    73         
    74     }
    75     return encryptedData;
    76 }

    第三步:解密相关代码

    #pragma mark - 解密相关
    - (void)loadPrivateKeyWithPath:(NSString *)p12FilePath password:(NSString *)p12Password
    {
        NSData *data = [NSData dataWithContentsOfFile:p12FilePath];
        if (data.length > 0)
        {
            [self loadPrivateKeyWithData:data password:p12Password];
    }
        else
        {    NSLog(@"load private key fail with path: %@", p12FilePath);
    }
    }
    //生成私钥
    - (void)loadPrivateKeyWithData:(NSData *)p12Data password:(NSString *)p12Password
    {
        SecKeyRef privateKeyRef = NULL;
        NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
        
        [options setObject:p12Password forKey:(__bridge id)kSecImportExportPassphrase];  CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
        OSStatus securityError = SecPKCS12Import((__bridge CFDataRef)p12Data,
                                                 (__bridge CFDictionaryRef)options,
                                                 &items);  if (securityError == noErr && CFArrayGetCount(items) > 0) {    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
            SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                                                              kSecImportItemIdentity);
            securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);    if (securityError != noErr) {
                privateKeyRef = NULL;
            }
        }
        
        _privateKey = privateKeyRef;
        CFRelease(items);
    }
    
    
    //调用下面方法进行解密,最后返回一个字符串
    - (NSString *)rsaDecryptText:(NSString *)text
    {
        NSData *data = [[NSData alloc] initWithBase64EncodedString:text options:0];
        NSData *decryptData = [self rsaDecryptData:data];
        NSString *result = [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding];
        return result;
    }
    
    
    //用私钥解密的方法,被上面方法调用
    - (NSData *)rsaDecryptData:(NSData *)data
    {
        SecKeyRef key = _privateKey;
        
        size_t cipherLen = [data length];
        void *cipher = malloc(cipherLen);
        
        [data getBytes:cipher length:cipherLen];
        size_t plainLen = SecKeyGetBlockSize(key) - 12;
        void *plain = malloc(plainLen);
        OSStatus status = SecKeyDecrypt(key, kSecPaddingPKCS1, cipher, cipherLen, plain, &plainLen);
        if (status != noErr)
        {
            return nil;
        }
        NSData *decryptedData = [[NSData alloc] initWithBytes:(const void *)plain length:plainLen];
        return decryptedData;
    }

    第四步:RSA加密解密的应用

    在加密活解密之前一定要闲加载证书,然后再调用加密方法,直接上代码

     1 - (IBAction)decryptionBtnClick:(id)sender {
     2     
     3     NSString *path = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];
     4     [self loadPublicKeyWithPath:path];
     5     path = [[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"];
     6     [self loadPrivateKeyWithPath:path password:@"bestnet"];
     7     
     8     NSString *encryptStr = self.encryptTextFeild.text;
     9     if (encryptStr.length > 0)
    10     {
    11         NSString *miwen = [self rsaEncryptText:encryptStr];
    12         self.miWenLabel.text = [NSString stringWithFormat:@"加密结果:%@", miwen];
    13         if (miwen.length > 0)
    14         {
    15             self.decryptionTextFeild.text = [self rsaDecryptText:miwen];
    16         }
    17     }
    18 }

    效果图

  • 相关阅读:
    利用outlook发送邮件的代码,其实就一句话,哈哈~~
    一个或多个数据库无法访问,因而不会在数据库访问选项卡中显示
    窗口碰壁弹回的浮动广告代码
    DataFormatString格式化数据及格式化时间失效的问题
    弹出并转向代码
    常用运行命令
    post和get
    自己总结的手动生成gridview导出excel的方法
    Spring boot download file
    RESTful WebService 入门实例
  • 原文地址:https://www.cnblogs.com/francisblogs/p/7447330.html
Copyright © 2020-2023  润新知