In the past few days, I have been struggling with how to use RSA for encryption on iOS. There is no direct RSA encryption API on iOS. However, iOS provides the x509 API, and x509 supports RSA encryption. Therefore, we can create a self-signed x509 certificate (due to low security requirements, we do not need to use a CA-certified certificate), and then call the relevant API of x509 for encryption. Next, record the entire process.
The first step is to create a self-signed certificate
1. The simplest and fastest way is to open Terminal and use openssl (included with Mac OS X) to generate the private key and self-signed certificate. x509 certificate.
openssl req -x509 -out public_key.der -outform der -new -newkey rsa:1024 -keyout private_key.pem -days 3650
Just enter the content according to the command line prompts. .
A few notes:
public_key.der is the output self-signed x509 certificate, which is what we want to use.
private_key.pem is the output private key, which is used for decryption. Please keep it properly.
rsa:1024 where 1024 is the key length, 1024 is relatively secure. If you need more security, you can use 2048, but the encryption and decryption costs will also increase.
-days: Certificate expiration time, this parameter must be added. The default certificate expiration time is 30 days. Generally, we do not want the certificate to expire in such a short time, so write a more appropriate number of days, for example here of 3650 (10 years).
In fact, this line of command contains several steps (the reason why I study the following steps is that I already have a private_key.pem private key on hand, and I want to use this directly to generate an x509 certificate, that is The following 2-3 is used)
1) Create a private key
openssl genrsa -out private_key.pem 1024
2) Create a certificate request (follow the prompts Enter information)
openssl req -new -out cert.csr -key private_key.pem
3) Self-signed root certificate
openssl x509 -req -in cert.csr -out public_key.der -outform der -signkey private_key.pem -days 3650
2. Verify the certificate. Drag public_key.der into xcode. If there is no problem with the file, you can open it directly in xcode and see various information about the certificate.
The second step is to use public_key.der for encryption.
1. Import Security.framework.
2. Put public_key.der into mainBundle (usually just drag it directly to Xcode).
3. Read the public key from public_key.der.
4. Encryption.
The following is the reference code (can only be used to encrypt content with a length of less than or equal to 116 bytes, suitable for encrypting passwords.
ARC is used, but it should be noted that some resources need to be released using CFRealse)
RSA.h
//
// RSA.h
//
#import Foundation.h>
@interface RSA : NSObject {
SecKeyRef publicKey;
SecCertificateRef certificate;
SecPolicyRef policy;
SecTrustRef trust;
size_t maxPlainLen;
}
- (NSData *) encryptWithData:(NSData *)content;
- (NSData *) encryptWithString:(NSString *)content;
@end
RSA.m< /p>
//
// RSA.m
//
#import "RSA.h"
@implementation RSA
- (id)init {
self = [super init];
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@" public_key"
ofType:@"der"];
if (publicKeyPath == nil) {
NSLog(@"Can not find pub.der" );
return nil;
}
NSDate *publicKeyFileContent = [NSData dataWithContentsOfFile:publicKeyPath];
if (publicKeyFileContent == nil) {
NSLog(@"Can not read from pub.der");
return nil;
}
certificate = SecCertificateCreateWithData(kCFAllocatorDefault, ( __bridge CFDataRef)publicKeyFileContent);
if (certificate == nil) {
NSLog(@"Can not read certificate from pub.der");< /p>
return nil;
}
policy = SecPolicyCreateBasicX509();
OSStatus returnCode = SecTrustCreateWithCertificates(certificate, policy, &trust);< /p>
if (returnCode != 0) {
NSLog(@"SecTrustCreateWithCertificates fail. Error Code: %ld", returnCode);
return nil; p>
}
SecTrustResultType trustResultType;
returnCode = SecTrustEvaluate(trust, &trustResultType);
if (returnCode != 0) {
NSLog(@"SecTrustEvaluate fail. Error Code: %ld", returnCode);
return nil;
}
publicKey = SecTrustCopyPublicKey( trust);
if (publicKey == nil) {
NSLog(@"SecTrustCopyPublicKey fail");
return nil;
}
maxPlainLen = SecKeyGetBlockSize(publicKey) - 12;
return self;
}
- (NSData *) encryptWithData: (NSData *)content {
size_t plainLen = [content length];
if (plainLen > maxPlainLen) {
NSLog(@"content(%ld ) is too long, must < %ld", plainLen, maxPlainLen);
return nil;
}
void *plain = malloc(plainLen);
[content getBytes:plain
length:plainLen];
size_t cipherLen = 128; // The current RSA key length is 128 bytes
p>void *cipher = malloc(cipherLen);
OSStatus returnCode = SecKeyEncrypt(publicKey, kSecPaddingPKCS1, plain,
plainLen, cipher, &cipherLen);
NSData *result = nil;
if (returnCode != 0) {
NSLog(@"SecKeyEncrypt fail. Error Code: %ld", returnCode);
p>}
else {
result = [NSData dataWithBytes:cipher
length:cipherLen];
}< /p>
free(plain);
free(cipher);
return result;
}
- ( NSData *) encryptWithString:(NSString *)content {
return [self encryptWithData:[content dataUsingEncoding:NSUTF8StringEncoding]];
}
- (void) dealloc{
CFRelease(certificate);
CFRelease(trust);
CFRelease(policy);
CFRelease(publicKey);
}
@end
Usage:
RSA *rsa = [[RSA alloc] init];
if (rsa != nil) {
NSLog(@"%@",[rsa encryptWithString:@"test"]);
}
< p>else {NSLog(@"init rsa error");
}