iOS非對稱加密RSA實現

前言:

我們講解了初級的對稱加密,我想信大家也對加密以及為什么要加密有了一定的理解,但是對稱加密有一個很大的缺點就是某人要是攔截到請求之后獲取密文又對你的api包進行反編譯得到了加密秘鑰和算法,你這個密文和明文也就么什么區別了,為了更好的解決此類問題我們偉大的先輩們又提出了一種新的概念RSA非對稱加密。

RSA非對稱加密介紹:

  • RSA加密是一種非對稱加密方式(以下內容摘自--百度百科)

1.A要向B發送信息,A和B都要產生一對用于加密和解密的公鑰和私鑰。
2.A的私鑰保密,A的公鑰告訴B;B的私鑰保密,B的公鑰告訴A。
3.A要給B發送信息時,A用B的公鑰加密信息,因為A知道B的公鑰。
4.A將這個消息發給B(已經用B的公鑰加密消息)。
5.B收到這個消息后,B用自己的私鑰解密A的消息。其他所有收到這個報文的人都無法解密,因為只有B才有B的私鑰。

其實我第一次看上面這段內容以及試圖去理解RSA非對稱加密的時候真是想罵人的,后來我忍住了,多讀了幾遍不行我又抄了幾遍功夫不負有心人終于是理解了。其他都是廢話,我來一步一步給大家實現。

第一步(生成私鑰和公鑰文件):

我使用的是MAC,上面自帶了OpenSSL,當然我刪除了,又用HomeBrew安裝了一個較新的版本。又看了下Linux上也自帶了openssl,windows上沒有,可以去官網下載安裝

1.終端輸入openssl,進入openssl狀態

2.生成一個1024位的私鑰:genrsa -out rsa_private_key.pem 1024

3.利用私鑰生成JAVA支持的PKCS8類型的私鑰:pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out pkcs8_private_key.pem

4.生成JAVA支持的PKCS8二進制類型的私鑰:pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform DER -nocrypt -out pkcs8_private_key.der

5.生成公鑰:rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem

6.生成iOS支持的der證書,其間用到了證書請求和自簽署根證書

6.1.創建證書請求:req -new -out cert.csr -key rsa_private_key.pem  (其間會要求填寫國家地區公司信息等,隨便填寫OR認真填寫都不影響證書使用)

6.2.創建X509的自簽署跟證書(iOS支持X509,有效期3650天):x509 -req -in cert.csr -out rsa_public_key.der -outform der -signkey rsa_private_key.pem -days 3650

完成了以上的步驟后應該在你所在的目錄下生成了6個文件


1416859-d09524d24befc11e.png

第二步(代碼的封裝):

  • 新建RSAEncryptor繼承NSObject
RSAEncryptor.h實現:
   /**
   *  加密方法
   *
   *  @param str   需要加密的字符串
   *  @param path  '.der'格式的公鑰文件路徑
   *  @param Base64  是否編碼為Base64
   */
  + (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path isBase64:(BOOL)Base64;
  /**
   *  解密方法
   *
   *  @param str       需要解密的字符串
   *  @param path      '.p12'格式的私鑰文件路徑
   *  @param password  私鑰文件密碼
   *  @param Base64  是否編碼為Base64
   */
  + (NSString *)decryptString:(NSString *)str privateKeyWithContentsOfFile:(NSString *)path password:(NSString *)password isBase64:(BOOL)Base64;
  /**
   *  加密方法
   *
   *  @param str    需要加密的字符串
   *  @param pubKey 公鑰字符串
   *  @param Base64  是否編碼為Base64
   */
  + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey isBase64:(BOOL)Base64;
  /**
   *  解密方法
   *
   *  @param str     需要解密的字符串
   *  @param privKey 私鑰字符串
   *  @param Base64  是否編碼為Base64
   */
  + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey isBase64:(BOOL)Base64;
RSAEncryptor.m實現:
  #pragma mark - 64位編碼 -加密
  static NSString *base64_encode_data(NSData *data){
      data = [data base64EncodedDataWithOptions:0];
      NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      return ret;
  }
  #pragma mark - 64位編碼 -解密
  static NSData *base64_decode(NSString *str){
      NSData *data = [[NSData alloc] initWithBase64EncodedString:str    options:NSDataBase64DecodingIgnoreUnknownCharacters];
      return data;
  }
  #pragma mark - 16位編碼 -加密
  + (NSString *)dataTohexString:(NSData*)data
  {
      Byte *bytes = (Byte *)[data bytes];
      NSString *hexStr=@"";
      for(int i=0;i<[data length];i++)
      {
          NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];//16進制數
          if([newHexStr length]==1)
              hexStr = [NSString  stringWithFormat:@"%@0%@",hexStr,newHexStr];
          else
              hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
      }
      return hexStr;
  }
  #pragma mark - 16位編碼 -解密
  + (NSData*)hexStringToData:(NSString*)hexString
  {
      int j=0;
      Byte bytes[hexString.length];  ///3ds key的Byte 數組, 128位
      for(int i=0;i<[hexString length];i++)
      {
          int int_ch;  /// 兩位16進制數轉化后的10進制數     
          unichar hex_char1 = [hexString characterAtIndex:i]; ////兩位16進制數中的第一位(高位*16)
          int int_ch1;
          if(hex_char1 >= '0' && hex_char1 <='9')
              int_ch1 = (hex_char1-48)*16;   //// 0 的Ascll - 48
          else if(hex_char1 >= 'A' && hex_char1 <='F')
              int_ch1 = (hex_char1-55)*16; //// A 的Ascll - 65
          else
              int_ch1 = (hex_char1-87)*16; //// a 的Ascll - 97
          i++;    
          unichar hex_char2 = [hexString characterAtIndex:i]; ///兩位16進制數中的第二位(低位)
          int int_ch2;
          if(hex_char2 >= '0' && hex_char2 <='9')
              int_ch2 = (hex_char2-48); //// 0 的Ascll - 48
          else if(hex_char1 >= 'A' && hex_char1 <='F')
              int_ch2 = hex_char2-55; //// A 的Ascll - 65
          else
              int_ch2 = hex_char2-87; //// a 的Ascll - 97
              int_ch = int_ch1+int_ch2;
              //NSLog(@"int_ch=%x",int_ch);
              bytes[j] = int_ch;  ///將轉化后的數放入Byte數組里
              j++;
          }
       //    NSData *newData = [[NSData alloc] initWithBytes:bytes length:j];
      NSData *newData = [[NSData alloc] initWithBytes:bytes length:j];
      //NSLog(@"newData=%@",newData);
      return newData;
  }
  #pragma mark - 使用'.der'公鑰文件加密
  + (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path isBase64:   (BOOL)Base64{
      if (!str || !path)  return nil;
      return [self encryptString:str publicKeyRef:[self getPublicKeyRefWithContentsOfFile:path] isBase64:Base64];
  }
  //獲取公鑰
  + (SecKeyRef)getPublicKeyRefWithContentsOfFile:(NSString *)filePath{
      NSData *certData = [NSData dataWithContentsOfFile:filePath];
      if (!certData) {
          return nil;
      }
      SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);
      SecKeyRef key = NULL;
      SecTrustRef trust = NULL;
      SecPolicyRef policy = NULL;
      if (cert != NULL) {
          policy = SecPolicyCreateBasicX509();
          if (policy) {
              if (SecTrustCreateWithCertificates((CFTypeRef)cert, policy, &trust) == noErr) {
                  SecTrustResultType result;
                  if (SecTrustEvaluate(trust, &result) == noErr) {
                      key = SecTrustCopyPublicKey(trust);
                  }
              }
          }
      }
      if (policy) CFRelease(policy);
      if (trust) CFRelease(trust);
      if (cert) CFRelease(cert);
      return key;
  }
  + (NSString *)encryptString:(NSString *)str publicKeyRef:(SecKeyRef)publicKeyRef isBase64:(BOOL)Base64{
      if(![str dataUsingEncoding:NSUTF8StringEncoding]){
          return nil;
      }
      if(!publicKeyRef){
          return nil;
      }
      NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] withKeyRef:publicKeyRef];
      NSString *ret = nil;
      if (Base64) {
          //64位編碼
          ret = base64_encode_data(data);
      }else{
          //16位編碼
          ret = [self dataTohexString:data];
      }
      return ret;
  }
  #pragma mark - 使用'.12'私鑰文件解密
  + (NSString *)decryptString:(NSString *)str privateKeyWithContentsOfFile:(NSString *)path password:(NSString *)password isBase64:(BOOL)Base64{
      if (!str || !path) return nil;
      if (!password) password = @"";
      return [self decryptString:str privateKeyRef:[self getPrivateKeyRefWithContentsOfFile:path password:password] isBase64:Base64];
  }
  //獲取私鑰
  + (SecKeyRef)getPrivateKeyRefWithContentsOfFile:(NSString *)filePath password:(NSString*)password{   
      NSData *p12Data = [NSData dataWithContentsOfFile:filePath];
      if (!p12Data) {
          return nil;
      }
      SecKeyRef privateKeyRef = NULL;
      NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
      [options setObject: password 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;
          }
      }
      CFRelease(items);   
      return privateKeyRef;
  }
  + (NSString *)decryptString:(NSString *)str privateKeyRef:(SecKeyRef)privKeyRef isBase64:(BOOL)Base64{    
      NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
      if (!privKeyRef) {
          return nil;
      }
      if (Base64) {
          //64位編碼
          data = [self decryptData:data withKeyRef:privKeyRef];
      }else{
          //16位編碼
          data = [self decryptData:[self hexStringToData:str] withKeyRef:privKeyRef];    
      } 
      NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      return ret;
  }
  #pragma mark - 使用公鑰字符串加密
  /* START: Encryption with RSA public key */
  //使用公鑰字符串加密
  + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey isBase64:(BOOL)Base64{
      NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
      NSString * ret = nil;    
      if (Base64) {
          //64位編碼
          ret = base64_encode_data(data);
      }else{
          //16位編碼
          ret = [self dataTohexString:data];
      }
      return ret;
  }
  + (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
      if(!data || !pubKey){
          return nil;
      }
      SecKeyRef keyRef = [self addPublicKey:pubKey];
      if(!keyRef){
          return nil;
      }      
      return [self encryptData:data withKeyRef:keyRef];
  }
  + (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 = base64_decode(key);
      data = [self 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]);
  }
  + (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
      const uint8_t *srcbuf = (const uint8_t *)[data bytes];
      size_t srclen = (size_t)data.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);
      return ret;
  }
  /* END: Encryption with RSA public key */
  #pragma mark - 使用私鑰字符串解密
  /* START: Decryption with RSA private key */
  //使用私鑰字符串解密
  + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey isBase64:(BOOL)Base64{
      if (!str) return nil;      
      NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
      data = [self decryptData:data privateKey:privKey       isBase64:Base64];
      NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      return ret;
  }
  + (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey isBase64:(BOOL)Base64{
      if(!data || !privKey){
          return nil;
      }
      SecKeyRef keyRef = [self addPrivateKey:privKey];
      if(!keyRef){
          return nil;
      }
      if (Base64) {
          //64位編碼
          data = [self decryptData:data withKeyRef:keyRef];
      }else{
          //16位編碼
          data = [self decryptData:data withKeyRef:keyRef];
      }
      return data;
  }
  + (SecKeyRef)addPrivateKey:(NSString *)key{
      NSRange spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
      NSRange epos = [key rangeOfString:@"-----END RSA PRIVATE 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 = base64_decode(key);
      data = [self stripPrivateKeyHeader:data];
      if(!data){
          return nil;
      }    
      //a tag to read/write keychain storage
      NSString *tag = @"RSAUtil_PrivKey";
      NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];  
      // Delete any old lingering key with the same tag
      NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
      [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
      [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
      [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
      SecItemDelete((__bridge CFDictionaryRef)privateKey);
      // Add persistent version of the key to system keychain
      [privateKey setObject:data forKey:(__bridge id)kSecValueData];
      [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
       kSecAttrKeyClass];
      [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
       kSecReturnPersistentRef];
      CFTypeRef persistKey = nil;
      OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
      if (persistKey != nil){
          CFRelease(persistKey);
      }
      if ((status != noErr) && (status != errSecDuplicateItem)) {
          return nil;
      }
      [privateKey removeObjectForKey:(__bridge id)kSecValueData];
      [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
      [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
      [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
      // Now fetch the SecKeyRef version of the key
      SecKeyRef keyRef = nil;
      status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
      if(status != noErr){
          return nil;
      }
      return keyRef;
  }
  + (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
      // Skip ASN.1 private 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     = 22; //magic byte at offset 22    
      if (0x04 != c_key[idx++]) return nil;    
      //calculate length of the key
      unsigned int c_len = c_key[idx++];
      int det = c_len & 0x80;
      if (!det) {
          c_len = c_len & 0x7f;
      } else {
          int byteCount = c_len & 0x7f;
          if (byteCount + idx > len) {
              //rsa length field longer than buffer
              return nil;
          }
          unsigned int accum = 0;
          unsigned char *ptr = &c_key[idx];
          idx += byteCount;
          while (byteCount) {
              accum = (accum << 8) + *ptr;
              ptr++;
              byteCount--;
          }
          c_len = accum;
      }
      // Now make a new NSData from this buffer
      return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
  }
  + (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
      const uint8_t *srcbuf = (const uint8_t *)[data bytes];
      size_t srclen = (size_t)data.length;    
      size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
      UInt8 *outbuf = malloc(block_size);
      size_t src_block_size = block_size;    
      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 = SecKeyDecrypt(keyRef,
                           kSecPaddingNone,
                                 srcbuf + idx,
                                 data_len,
                                 outbuf,
                                 &outlen
                                 );
          if (status != 0) {
              NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
              ret = nil;
        break;      
          }else{
              //the actual decrypted data is in the middle, locate it!
              int idxFirstZero = -1;
              int idxNextZero = (int)outlen;
              for ( int i = 0; i < outlen; i++ ) {
                  if ( outbuf[i] == 0 ) {
                      if ( idxFirstZero < 0 ) {
                          idxFirstZero = i;
                      } else {
                          idxNextZero = i;
                          break;
                      }
                  }
              }
              [ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
          }
      } 
      free(outbuf);
      CFRelease(keyRef);
      return ret;
  }
  • 上面代碼我進行了簡單的封裝,基本實現功能:
    1.公鑰文件加密
    2.私鑰文件解密
    3.公鑰字符串加密
    4.私鑰字符串解密
  • 以上加密解密編碼格式有Base64和16位編碼,按照需求傳入參數便可;但是千萬注意,采用那種編碼之后的密文就用什么編碼解密。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容