RSA+Base64之RSA

根据个人项目经验:在项目中,使用RSA加密,用到的是RSA和Base64和SHA1。Base64进行编码。RSA进行加密解密。SHA1加签验签。

创建RSAEncryptor类,继承于NSObject。代码如下:

//

//  RSAEncryptor.h

//  CashLoan

//

//  Created by wzk on 2017/12/28.

//  Copyright © 2017年 com.shanlinfinance. All rights reserved.

//

#import

#define PublicKey @"PublicKey"

#define PrivateKey @"PrivateKey"

/*

 //使用body转成的字符串进行使用公钥加密

 NSString* RSAString = [RSAEncryptor encryptString:bodyString publicKey:PublicKey];

 //使用body转成的字符串 进行使用私钥SHA1加密

 NSString* signString = [RSAEncryptor signTheDataSHA1WithRSA:bodyString privateKey:PrivateKey];

 

 */

@interfaceRSAEncryptor :NSObject

/**

 *  加密方法

 *

 *  @paramstr  需要加密的字符串

 *  @parampath  '.der'格式的公钥文件路径

 */

+ (NSString*)encryptString:(NSString*)str publicKeyWithContentsOfFile:(NSString*)path;

/**

 *  解密方法

 *

 *  @paramstr      需要解密的字符串

 *  @parampath      '.p12'格式的私钥文件路径

 *  @parampassword  私钥文件密码

 */

+ (NSString*)decryptString:(NSString*)str privateKeyWithContentsOfFile:(NSString*)path password:(NSString*)password;

/**

 *  加密方法

 *

 *  @paramstr    需要加密的字符串

 *  @parampubKey 公钥字符串

 */

+ (NSString*)encryptString:(NSString*)str publicKey:(NSString*)pubKey;

/**

 *  解密方法

 *

 *  @paramstr    需要解密的字符串

 *  @paramprivKey 私钥字符串

 */

+ (NSString*)decryptString:(NSString*)str privateKey:(NSString*)privKey;

//签名

+ (NSString*)signTheDataSHA1WithRSA:(NSString*)plainText  privateKey:(NSString*)privateKey;

//验签

+ (BOOL)rsaSHA1VertifyingData:(NSString*)plainData withSignature:(NSString*)signature;

@end

//

//  RSAEncryptor.m

//  CashLoan

//

//  Created by wzk on 2017/12/28.

//  Copyright © 2017年 com.shanlinfinance. All rights reserved.

//

#import "RSAEncryptor.h"

#import

#import

#import

#import "NSData+Base64.h"

#import "NSString+Base64.h"

#define kChosenDigestLength CC_SHA1_DIGEST_LENGTH  // SHA-1消息摘要的数据位数160位

@implementation RSAEncryptor

staticNSString*base64_encode_data(NSData*data){

    data = [database64EncodedDataWithOptions:0];

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

    returnret;

}

staticNSData*base64_decode(NSString*str){

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

    returndata;

}

#pragma mark - 使用'.der'公钥文件加密

//加密

+ (NSString*)encryptString:(NSString*)str publicKeyWithContentsOfFile:(NSString*)path{

    if(!str || !path)  returnnil;

    return [self encryptString:str publicKeyRef:[self getPublicKeyRefWithContentsOfFile:path]];

}

//获取公钥

+ (SecKeyRef)getPublicKeyRefWithContentsOfFile:(NSString*)filePath{

    NSData*certData = [NSDatadataWithContentsOfFile:filePath];

    if(!certData) {

        returnnil;

    }

    SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);

    SecKeyRefkey =NULL;

    SecTrustReftrust =NULL;

    SecPolicyRefpolicy =NULL;

    if(cert !=NULL) {

        policy =SecPolicyCreateBasicX509();

        if(policy) {

            if(SecTrustCreateWithCertificates((CFTypeRef)cert, policy, &trust) ==noErr) {

                SecTrustResultTyperesult;

                if(SecTrustEvaluate(trust, &result) ==noErr) {

                    key =SecTrustCopyPublicKey(trust);

                }

            }

        }

    }

    if(policy)CFRelease(policy);

    if(trust)CFRelease(trust);

    if(cert)CFRelease(cert);

    returnkey;

}

+ (NSString*)encryptString:(NSString*)str publicKeyRef:(SecKeyRef)publicKeyRef{

    if(![str dataUsingEncoding:NSUTF8StringEncoding]){

        returnnil;

    }

    if(!publicKeyRef){

        returnnil;

    }

    NSData*data = [selfencryptData:[strdataUsingEncoding:NSUTF8StringEncoding]withKeyRef:publicKeyRef];

    NSString*ret =base64_encode_data(data);

    returnret;

}

#pragma mark - 使用'.12'私钥文件解密

//解密

+ (NSString*)decryptString:(NSString*)str privateKeyWithContentsOfFile:(NSString*)path password:(NSString*)password{

    if(!str || !path)returnnil;

    if(!password) password =@"";

    return [self decryptString:str privateKeyRef:[self getPrivateKeyRefWithContentsOfFile:path password:password]];

}

//获取私钥

+ (SecKeyRef)getPrivateKeyRefWithContentsOfFile:(NSString*)filePath password:(NSString*)password{


    NSData*p12Data = [NSDatadataWithContentsOfFile:filePath];

    if(!p12Data) {

        returnnil;

    }

    SecKeyRefprivateKeyRef =NULL;

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

    [optionssetObject: passwordforKey:(__bridgeid)kSecImportExportPassphrase];

    CFArrayRefitems =CFArrayCreate(NULL,0,0,NULL);

    OSStatussecurityError =SecPKCS12Import((__bridgeCFDataRef) p12Data, (__bridgeCFDictionaryRef)options, &items);

    if(securityError ==noErr&&CFArrayGetCount(items) >0) {

        CFDictionaryRefidentityDict =CFArrayGetValueAtIndex(items,0);

        SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);

        securityError =SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);

        if(securityError !=noErr) {

            privateKeyRef =NULL;

        }

    }

    CFRelease(items);


    returnprivateKeyRef;

}

+ (NSString*)decryptString:(NSString*)str privateKeyRef:(SecKeyRef)privKeyRef{

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

    if(!privKeyRef) {

        returnnil;

    }

    data = [selfdecryptData:datawithKeyRef:privKeyRef];

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

    returnret;

}

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

/* START: Encryption with RSA public keyn */

//使用公钥字符串加密

+ (NSString*)encryptString:(NSString*)str publicKey:(NSString*)pubKey{

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

    NSString*ret =base64_encode_data(data);

    returnret;

}

+ (NSData*)encryptData:(NSData*)data publicKey:(NSString*)pubKey{

    if(!data || !pubKey){

        returnnil;

    }

    SecKeyRefkeyRef = [selfaddPublicKey:pubKey];

    if(!keyRef){

        returnnil;

    }

    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 = [self stripPublicKeyHeader: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:(__bridgeid)kSecClassKeyforKey:(__bridgeid)kSecClass];

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

    [publicKeysetObject:d_tagforKey:(__bridgeid)kSecAttrApplicationTag];

    SecItemDelete((__bridgeCFDictionaryRef)publicKey);


    // Add persistent version of the key to system keychain

    [publicKeysetObject:dataforKey:(__bridgeid)kSecValueData];

    [publicKeysetObject:(__bridgeid)kSecAttrKeyClassPublicforKey:(__bridgeid)

     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:(__bridgeid)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){

        returnnil;

    }

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

    unsignedint  idx    =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

    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;

    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*)data withKeyRef:(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

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

            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*)str privateKey:(NSString*)privKey{

    if(!str)returnnil;

    if(![strisKindOfClass:[NSStringclass]]) {

        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*)data privateKey:(NSString*)privKey{

    if(!data || !privKey){

        returnnil;

    }

    SecKeyRefkeyRef = [selfaddPrivateKey:privKey];

    if(!keyRef){

        returnnil;

    }

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

        returnnil;

    }


    //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:(__bridgeid)kSecClassKeyforKey:(__bridgeid)kSecClass];

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

    [privateKeysetObject:d_tagforKey:(__bridgeid)kSecAttrApplicationTag];

    SecItemDelete((__bridgeCFDictionaryRef)privateKey);


    // Add persistent version of the key to system keychain

    [privateKeysetObject:dataforKey:(__bridgeid)kSecValueData];

    [privateKeysetObject:(__bridgeid)kSecAttrKeyClassPrivateforKey:(__bridgeid)

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

        returnnil;

    }


    [privateKeyremoveObjectForKey:(__bridgeid)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){

        returnnil;

    }

    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

            returnnil;

        }

        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*)data withKeyRef:(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

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

            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 */

/*

 *加签

 */

//生成哈希数据

+ (NSData*)getHashBytes:(NSData*)plainText {

    CC_SHA1_CTX ctx;

    uint8_t* hashBytes =NULL;

    NSData* hash =nil;


    // Malloc a buffer to hold hash.

    hashBytes =malloc(kChosenDigestLength*sizeof(uint8_t) );

    memset((void *)hashBytes, 0x0, kChosenDigestLength);

    // Initialize the context.

    CC_SHA1_Init(&ctx);

    // Perform the hash.

    CC_SHA1_Update(&ctx, (void*)[plainTextbytes], [plainTextlength]);

    // Finalize the output.

    CC_SHA1_Final(hashBytes, &ctx);


    // Build up the SHA1 blob.

    hash = [NSDatadataWithBytes:(constvoid*)hashByteslength:(NSUInteger)kChosenDigestLength];

    if(hashBytes)free(hashBytes);


    returnhash;

}

//签名

+ (NSString*)signTheDataSHA1WithRSA:(NSString*)plainText  privateKey:(NSString*)privateKey

{

    uint8_t* signedBytes =NULL;

    size_tsignedBytesSize =0;

    OSStatussanityCheck =noErr;

    NSData* signedHash =nil;



    SecKeyRefprivateKeyRef = [selfaddPrivateKey:privateKey];

    if(!privateKeyRef){

        returnnil;

    }


    signedBytesSize =SecKeyGetBlockSize(privateKeyRef);


    NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];


    signedBytes =malloc( signedBytesSize *sizeof(uint8_t) );// Malloc a buffer to hold signature.

    memset((void*)signedBytes,0x0, signedBytesSize);


    sanityCheck =SecKeyRawSign(privateKeyRef,

                                kSecPaddingPKCS1SHA1,

                                (constuint8_t*)[[selfgetHashBytes:plainTextBytes]bytes],

                                kChosenDigestLength,

                                (uint8_t*)signedBytes,

                                &signedBytesSize);


    if(sanityCheck ==noErr)

    {

        signedHash = [NSDatadataWithBytes:(constvoid*)signedByteslength:(NSUInteger)signedBytesSize];

    }

    else

    {

        returnnil;

    }


    if(signedBytes)

    {

        free(signedBytes);

    }

    NSString*signatureResult=[NSStringstringWithFormat:@"%@",[signedHashbase64EncodedString]];

    returnsignatureResult;

}

/**

 验证签名


 @paramplainData plainData解密后的data

 @paramsignature 服务的签名

 @return是否验签成功


 将plainData转化成data,将signature签名base64解码,进行验证签名

 */

+ (BOOL)rsaSHA1VertifyingData:(NSString*)plainData withSignature:(NSString*)signature{

    NSData *plainTextBytes = [plainData dataUsingEncoding:NSUTF8StringEncoding];

    NSData*signatureBytes = [signaturebase64DecodedData];


    SecKeyRefpublicKey = [selfaddPublicKey:PublicKey];

    if((!publicKey)||(!signatureBytes)||(!plainTextBytes)){

        returnNO;

    }


    size_tsignedHashBytesSize =SecKeyGetBlockSize(publicKey);

    constvoid* signedHashBytes = [signatureBytesbytes];


    size_thashBytesSize =CC_SHA1_DIGEST_LENGTH;

    uint8_t* hashBytes =malloc(hashBytesSize);

    if(!CC_SHA1([plainTextBytesbytes], (CC_LONG)[plainTextByteslength], hashBytes)) {

        returnNO;

    }


    OSStatusstatus =SecKeyRawVerify(publicKey,

                                      kSecPaddingPKCS1SHA1,

                                      hashBytes,

                                      hashBytesSize,

                                      signedHashBytes,

                                      signedHashBytesSize);



    returnstatus ==errSecSuccess;

}

@end

你可能感兴趣的:(RSA+Base64之RSA)