RSA基本原理
RSA使用”秘匙对”对数据进行加密解密.在加密解密数据前,需要先生成公钥(public key)和 私 钥(private key).
公钥(public key): 用于加密数据. 用于公开, 一般存放在数据提供方, 例如iOS客户端
私钥(private key): 用于解密数据. 必须保密, 私钥泄露会造成安全问题.
一、首先,打开Terminal, 生成必要的公钥、私钥、证书:
openssl genrsa -out private_key.pem 1024 // 生成模长为1024bit的私钥文件private_key.pem
openssl req -new -key private_key.pem -out rsaCertReq.csr // 生成证书请求文件rsaCertReq.csr 注意:这一步会提示输入国家、省份、mail等信息,可以根据实际情况填写,或者全部不用填写,直接全部敲回车.
openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt //生成证书rsaCert.crt,并设置有效时间为1年
openssl x509 -outform der -in rsaCert.crt -out public_key.der //创建iOS使用的public_key.der 公钥文件
openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt //创建iOS端用于解密的private_key.p12私钥文件 这一步,请记住你输入的密码,IOS代码里会用到
openssl rsa -in private_key.pem -out rsa_public_key.pem -pubout // Create 创建 Java 使用的rsa_public_key.pem 公钥
openssl pkcs8 -topk8 -in private_key.pem -out pkcs8_private_key.pem -nocrypt // Create 创建 Java 使用的private_key.pem 私钥
上面七个步骤,总共生成7个文件。其中 public_key.der 和 private_key.p12 这对公钥私钥是给IOS用的, rsa_public_key.pem 和 pkcs8_private_key.pem 是给JAVA用的。
它们的源都来自一个私钥:private_key.pem , 所以IOS端加密的数据,是可以被JAVA端解密的,反过来也一样。
二、IOS 代码:
先把 public_key.der 和 private_key.p12 拖进你的Xcode项目里去
新建一个名字叫做RSAEncryptor的类
.h中
+(NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path;
+(NSString *)decryptString:(NSString *)str privateKeyWithContentsOfFile:(NSString *)path password:(NSString *)password;
+(NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
+(NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey;
.m中
static NSString *base64_encode_data(NSData *data){
data = [data base64EncodedDataWithOptions:0];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return ret;
}
static NSData *base64_decode(NSString *str){
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
return data;
}
#pragma mark - 使用'.der'公钥文件加密
//加密
+ (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path{
if (!str || !path) return nil;
return [self encryptString:str publicKeyRef:[self getPublicKeyRefWithContentsOfFile:path]];
}
//获取公钥
+ (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{
if(![str dataUsingEncoding:NSUTF8StringEncoding]){
return nil;
}
if(!publicKeyRef){
return nil;
}
NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] withKeyRef:publicKeyRef];
NSString *ret = base64_encode_data(data);
return re