美文网首页
iOS加密算法之RSA公钥加密

iOS加密算法之RSA公钥加密

作者: Peak_Liang | 来源:发表于2018-12-02 19:05 被阅读0次

RSA加密算法是一种非对称加密,即采用不同密钥进行加密解密操作的加密算法.这里不说公钥加密私钥解密是因为,在算法中,公钥和私钥都可以进行加密和解密操作,既可以公钥加密私钥解密,也可以私钥加密公钥解密.

iOS

对于移动端大部分的需求都是要对采集到的特殊数据进行加密上传,所以本文只介绍公钥加密的过程步骤,其余内容以后会做补充,首先感谢大神在github上的分享https://github.com/ideawu/Objective-C-RSA,很完善的工具,可以直接拿来用

1.处理密钥

首先我们会拿到一份公钥用来加密,我们要先对公钥进行处理,因为我们拿到的公钥是介个样子的

"public_key": "-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtjqeWqj5aW8aPlleLxoj\n6o82Eq4+v/B1+/x2dm6/HOf5lD0GzC/i326BIMzNVbBc2NiEWxju1t+mTlk5ko0Q\nG8KnF6f653QtHxqJVQEVJK3yKzOp45lU6ayOnNQn5aE8klc9fqj5CrKMIpdpH/Oq\n5J+/KxEWOuAtoNYVdI5NR52dUHKnv3mNIblDmfoiz53+d93Io39tEYfDmO8mDMa6\nNgu1oKQJmHWVrW+pDChleO/Cin7eeD2GEBoSQ5cG4CRJO0ouLUoZ9PtsvkZToxHU\nTSSEmqsgb7P9W6OQ4e2phNHQ/aKftWzem7jmISgPaFJan5fw+vGGoeBtxpRZJY+C\n0KdtkEG3jpV+TmCuLJHxMFoN+6kcy+NSFos7CSCyJM+35HPKfQAdtwLH7zLSJ9Rg\nb7n7QmUsTNfesBPLpNrL/o8EcpbV/xa8onTS/JJC3B6RTXSvkkbvBsLZNTk/wXEX\nsLTPo+0CWPDUBw1gBknZK7rV72TtuQ1pYoDe+wDhSEuXWG+XjdJDdOYQAXlg/JJV\nZqhacnyIilFyw194bACuj5KvzpUijOBj7U2J/GYFgKbYz+AaaOUovAOlEdLgqWs3\n95GhNbMPFVfV787kosvoJMwLOYt1TPQ0ZcJB3DEBiEqKL8KNNnq33TAMYQt+8nPQ\nTGmlp3qNkMmTcosR5jg3mtMCAwEAAQ==\n-----END PUBLIC KEY-----\n"

我这里从后台拿到是4096位的公钥,RSA中公钥位数越大,加密等级越高.从公钥内容中可以看出,里面有头有尾有转义字符,一眼看过去满是不靠谱的样子,而且,整个密钥是经过base64编码的,所以我们还要经过解码,才能拿到可用的密钥.然而这还不是我们可用的公钥,我们需要把他存到钥匙串中,然后取出可用的SecKeyRef作为加密密钥使用,具体操作如下:

 + (SecKeyRef)addPublicKey:(NSString *)key{

      NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];

      NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];

      if(spos.location != NSNotFound && epos.location != NSNotFound){

          NSUInteger s = spos.location + spos.length;

          NSUInteger e = epos.location;

          NSRange range = NSMakeRange(s, e-s);

          key = [key substringWithRange:range];
      }

      key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];

      key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];

      key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];

      key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];

    // This will be base64 encoded, decode it.

       NSData *data = [NSData dataFromBase64String:key];

      data = [FTZAbnormalReport stripPublicKeyHeader:data];

      if(!data){

        return nil;

       }

       //a tag to read/write keychain storage

      NSString *tag = @"RSAUtil_PubKey";

      NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

      // Delete any old lingering key with the same tag

      NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];

      [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];

      [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

      [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];

      SecItemDelete((__bridge CFDictionaryRef)publicKey);

      // Add persistent version of the key to system keychain

      [publicKey setObject:data forKey:(__bridge id)kSecValueData];

      [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)  kSecAttrKeyClass];

      [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id) kSecReturnPersistentRef];

      CFTypeRef persistKey = nil;

      OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);

      if (persistKey != nil){

          CFRelease(persistKey);

      }

      if ((status != noErr) && (status != errSecDuplicateItem)) {

           return nil;

      }

      [publicKey removeObjectForKey:(__bridge id)kSecValueData];

      [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];

      [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];

      [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

       // Now fetch the SecKeyRef version of the key

     SecKeyRef keyRef = nil;

      status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);

      if(status != noErr){

          return nil;

      }

      return keyRef;
  }

  + (NSData *)stripPublicKeyHeader:(NSData *)d_key{

      // Skip ASN.1 public key header

      if (d_key == nil) return(nil);

      unsigned long len = [d_key length];

      if (!len) return(nil);

      unsigned char *c_key = (unsigned char *)[d_key bytes];

      unsigned int  idx    = 0;

      if (c_key[idx++] != 0x30) return(nil);

      if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;

      else idx++;

      // PKCS #1 rsaEncryption szOID_RSA_RSA

      static unsigned char seqiod[] =

      { 0x30,  0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,  0x0d,0x01, 0x01,  0x01, 0x05, 0x00 };

      if (memcmp(&c_key[idx], seqiod, 15)) return(nil);

      idx += 15;

      if (c_key[idx++] != 0x03) return(nil);

      if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;

      else idx++;

      if (c_key[idx++] != '\0') return(nil);

      // Now make a new NSData from this buffer

      return([NSData dataWithBytes:&c_key[idx] length:len - idx]);

  }

2.分段加密

对公钥处理之后我们要对需要加密的明文进行分段加密,原因是因为你的加密明文的长度不得超过你的密钥长度,我这里的密钥上面说过是4096位的也就是512字节,由于后台是PHP,解密使用的OPENSSL_PKCS1_PADDING长11字节,所以我使用公钥进行加密的单串明文长度为501字节.我这里的明文中存在少量汉字内容,所以为了省事,统一采用200字符标准进行分段.加密方式如下:

const uint8_t *srcbuf = (const uint8_t *)[sourceData bytes];

size_t srclen = (size_t)sourceData.length;

size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);

void *outbuf = malloc(block_size);

size_t src_block_size = block_size - 11;

NSMutableData *ret = [[NSMutableData alloc] init];

for(int idx=0; idx<srclen; idx+=src_block_size){

    //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);

    size_t data_len = srclen - idx;

    if(data_len > src_block_size){

        data_len = src_block_size;

    }

    size_t outlen = block_size;

    OSStatus status = noErr;

    status = SecKeyEncrypt(keyRef,kSecPaddingPKCS1,srcbuf + idx,data_len,outbuf,&outlen);

    if (status != 0) {

        NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);

        ret = nil;

        break;

    }else{

        [ret appendBytes:outbuf length:outlen];

    }

}

free(outbuf);

CFRelease(keyRef);

NSData *data = ret;

拿到密文之后我们只需要再对这串密文进行base64编码就可以存起来准备提交了

NSString *retStr = [data base64EncodedString];

以上只是对RSA公钥加密在OC中使用的简单整理,理解不到位的地方还请海涵,如果各位大佬有更深的理解也可以随时指教.

相关文章

  • # RSA 公钥加密算法

    # RSA 公钥加密算法 # RSA 公钥加密算法

  • RSA非对称加密算法

    RSA算法,经典非对称加密算法,通过生成公钥 私钥 进行加密解密 公钥加密 私钥解密 反之 私钥加密 公钥...

  • Linux配置免密登录

    1、公钥-私钥对: 称为非对称加密方式 2、生成公钥-私钥对命令: 参数:-t:加密算法 rsa:不对称加密算法...

  • iOS RSA加签和验签(SHA1WithRSA)

    RSA 简介 RSA是一种非对称加密算法,使用公钥加密就可以使用私钥解密,使用私钥加密就可以使用公钥解密。RSA公...

  • iOS RSA加签和验签

    RSA是一种非对称加密算法,使用公钥加密就可以使用私钥解密,使用私钥加密就可以使用公钥解密。RSA公钥对外公开,私...

  • RSA加密

    RSA基本原理: RSA加密算法是基于一个密钥对的,分为公钥和私钥,一般情况公钥加密,私钥解密,但也可私钥加密,公...

  • 家雀

    点赞!!!iOS RSA加签和验签RSA是一种非对称加密算法,使用公钥加密就可以使用私钥解密,使用私钥加密就可以使...

  • rsa加密

    看这里 1、RSA加密算法是目前最有影响力的公钥加密算法,并且被普遍认为是目前最优秀的公钥方案之一。RSA是第一个...

  • [ 加密 ] RSA 公认目前最优秀的公钥方案之一

    RSA 加密算法是目前最有影响力的公钥加密算法,并且被普遍认为是目前 最优秀的公钥方案之一 RSA 是第一个能同时...

  • RSA加密在Android中的使用

    1.RSA介绍 RSA是一种常用的非对称加密算法,所谓非对称加密是指使用一对密钥(公钥和私钥)进行加密和解密,公钥...

网友评论

      本文标题:iOS加密算法之RSA公钥加密

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