天天看點

ios android 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 *)derFilePath4 {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 *)derData17 {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 *)text35 {36 NSData *encryptedData =[self rsaEncryptData:[text dataUsingEncoding:NSUTF8StringEncoding]];37 NSString *base64EncryptedString = [encryptedData base64EncodedStringWithOptions:0];38 returnbase64EncryptedString;39 }40

41

42 //分段再加密資料

43 - (NSData *)rsaEncryptData:(NSData *)data44 {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 } returnnil;67 }68

69 }70 if(cipherBuffer)71 {72 free(cipherBuffer);73

74 }75 returnencryptedData;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:(__bridgeid)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];returnresult;

}//用私鑰解密的方法,被上面方法調用

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

{returnnil;

}

NSData*decryptedData = [[NSData alloc] initWithBytes:(const void *)plain length:plainLen];returndecryptedData;

}

第四步: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 }

效果圖

ios android rsa加密解密,iOS常用加密之RSA加密解密(示例代碼)