iOS 实际项目出现的问题

RSA加密

2020-04-21  本文已影响0人  江河_ios

#import "RSAEncryptor.h"

@implementation RSAEncryptor

static NSString *base64_encode_data(NSData *data){

 data = [database64EncodedDataWithOptions:0];

 NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

 returnret;

}

static NSData *base64_decode(NSString *str){

 NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];

 returndata;

}

#pragma mark- 使用公钥字符串加密

/* START: Encryption with RSA public key */

//使用公钥字符串加密

+ (NSString*)encryptString:(NSString*)strpublicKey:(NSString*)pubKey{

    NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];

  NSString *ret = base64_encode_data(data);

    returnret;

}

+ (NSData*)encryptData:(NSData*)datapublicKey:(NSString*)pubKey{

    if(!data || !pubKey){

    return nil;

    }

    SecKeyRefkeyRef = [selfaddPublicKey:pubKey];

    if(!keyRef){

    return nil;

    }

    return[selfencryptData:datawithKeyRef: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){

        NSUIntegers = spos.location+ spos.length;

        NSUIntegere = epos.location;

        NSRangerange =NSMakeRange(s, e-s);

        key = [keysubstringWithRange:range];

    }

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

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

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

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

    // This will be base64 encoded, decode it.

   NSData *data = base64_decode(key);

    data = [selfstripPublicKeyHeader:data];

    if(!data){

        returnnil;

    }

    //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];

    [publicKeysetObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];

    [publicKeysetObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    [publicKeysetObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];

    SecItemDelete((__bridgeCFDictionaryRef)publicKey);

    // Add persistent version of the key to system keychain

    [publicKeysetObject:data forKey:(__bridge id)kSecValueData];

    [publicKeysetObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)

    kSecAttrKeyClass];

    [publicKeysetObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)

    kSecReturnPersistentRef];

    CFTypeRefpersistKey =nil;

    OSStatusstatus =SecItemAdd((__bridgeCFDictionaryRef)publicKey, &persistKey);

    if(persistKey !=nil){

        CFRelease(persistKey);

    }

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

        returnnil;

    }

    [publicKeyremoveObjectForKey:(__bridge id)kSecValueData];

    [publicKeyremoveObjectForKey:(__bridge id)kSecReturnPersistentRef];

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

    [publicKeysetObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    // Now fetch the SecKeyRef version of the key

    SecKeyRefkeyRef =nil;

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

    if(status !=noErr){

    return nil;

    }

    returnkeyRef;

}

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

     // Skip ASN.1 public key header

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

     unsignedlonglen = [d_keylength];

     if(!len)return(nil);

     unsignedchar*c_key = (unsignedchar*)[d_keybytes];

     unsignedintidx =0;

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

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

     elseidx++;

     // PKCS #1 rsaEncryption szOID_RSA_RSA

     staticunsignedcharseqiod[] =

     {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;

     elseidx++;

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

     // Now make a new NSData from this buffer

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

}

+ (NSData*)encryptData:(NSData*)datawithKeyRef:(SecKeyRef) keyRef

{

     constuint8_t*srcbuf = (constuint8_t*)[databytes];

     size_tsrclen = (size_t)data.length;

     size_tblock_size =SecKeyGetBlockSize(keyRef) *sizeof(uint8_t);

     void*outbuf =malloc(block_size);

     size_tsrc_block_size = block_size -11;

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

     for(intidx=0; idx

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

     size_tdata_len = srclen - idx;

     if(data_len > src_block_size){

      data_len = src_block_size;

     }

     size_toutlen = block_size;

     OSStatusstatus =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{

      [retappendBytes:outbuflength:outlen];

     }

     }

     free(outbuf);

     CFRelease(keyRef);

     returnret;

}

/* END: Encryption with RSA public key */

#pragma mark- 使用私钥字符串解密

/* START: Decryption with RSA private key */

//使用私钥字符串解密

+ (NSString*)decryptString:(NSString*)strprivateKey:(NSString*)privKey{

 if(!str)returnnil;

 NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];

 data = [selfdecryptData:dataprivateKey:privKey];

 NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

 returnret;

}

+ (NSData*)decryptData:(NSData*)dataprivateKey:(NSString*)privKey{

    if(!data || !privKey){

    return nil;

    }

    SecKeyRefkeyRef = [selfaddPrivateKey:privKey];

    if(!keyRef){

    return nil;

    }

    return[selfdecryptData:datawithKeyRef:keyRef];

}

+ (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){

        NSUIntegers = spos.location+ spos.length;

        NSUIntegere = epos.location;

        NSRangerange =NSMakeRange(s, e-s);

        key = [keysubstringWithRange:range];

    }

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

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

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

    key = [keystringByReplacingOccurrencesOfString:@" " 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];

    [privateKeysetObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];

    [privateKeysetObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    [privateKeysetObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];

    SecItemDelete((__bridgeCFDictionaryRef)privateKey);

    // Add persistent version of the key to system keychain

    [privateKeysetObject:dataforKey:(__bridgeid)kSecValueData];

    [privateKeysetObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)

    kSecAttrKeyClass];

    [privateKeysetObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)

    kSecReturnPersistentRef];

    CFTypeRefpersistKey =nil;

    OSStatusstatus =SecItemAdd((__bridgeCFDictionaryRef)privateKey, &persistKey);

    if(persistKey !=nil){

    CFRelease(persistKey);

    }

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

    return nil;

    }

    [privateKeyremoveObjectForKey:(__bridge id)kSecValueData];

    [privateKeyremoveObjectForKey:(__bridge id)kSecReturnPersistentRef];

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

    [privateKeysetObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    // Now fetch the SecKeyRef version of the key

    SecKeyRefkeyRef =nil;

    status =SecItemCopyMatching((__bridgeCFDictionaryRef)privateKey, (CFTypeRef*)&keyRef);

    if(status !=noErr){

    return nil;

    }

    returnkeyRef;

}

+ (NSData *)stripPrivateKeyHeader:(NSData *)d_key

{

 // Skip ASN.1 private key header

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

 unsignedlonglen = [d_keylength];

 if(!len)return(nil);

 unsignedchar*c_key = (unsignedchar*)[d_keybytes];

 unsigned int idx = 22; //magic byte at offset 22

 if(0x04!= c_key[idx++])returnnil;

 //calculate length of the key

 unsignedintc_len = c_key[idx++];

 intdet = c_len &0x80;

 if(!det) {

 c_len = c_len &0x7f;

 }else{

 intbyteCount = c_len &0x7f;

 if(byteCount + idx > len) {

  //rsa length field longer than buffer

  return nil;

 }

 unsignedintaccum =0;

 unsignedchar*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*)datawithKeyRef:(SecKeyRef) keyRef{

 constuint8_t*srcbuf = (constuint8_t*)[databytes];

 size_tsrclen = (size_t)data.length;

 size_tblock_size =SecKeyGetBlockSize(keyRef) *sizeof(uint8_t);

 UInt8*outbuf =malloc(block_size);

 size_tsrc_block_size = block_size;

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

 for(intidx=0; idx

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

 size_tdata_len = srclen - idx;

 if(data_len > src_block_size){

  data_len = src_block_size;

 }

 size_toutlen = block_size;

 OSStatusstatus =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!

  intidxFirstZero = -1;

  intidxNextZero = (int)outlen;

  for(inti =0; i < outlen; i++ ) {

  if( outbuf[i] ==0) {

   if( idxFirstZero <0) {

   idxFirstZero = i;

   }else{

   idxNextZero = i;

   break;

   }

  }

  }

  [retappendBytes:&outbuf[idxFirstZero+1]length:idxNextZero-idxFirstZero-1];

 }

 }

 free(outbuf);

 CFRelease(keyRef);

 returnret;

}

/* END: Decryption with RSA private key */

@end

上一篇下一篇

猜你喜欢

热点阅读