最近公司项目有个需求,在客户端实现利用私钥进行RSA加密,公钥进行解密的需求。之前做过的都是公钥加密私钥解密,而且也在别人的文章中看到过不建议用私钥做加密,不过公司需求如此,只能硬着头皮上了。
经过初步排查,基本确定了iOS源生框架是没有提供相应的API接口的,只有常规的公钥加密私钥解密。于是开始Google,看了N多文章和问答,锁定了OpenSSL库可以实现这个需求,不过这个是C写的,用起来稍微麻烦点,于是又顺藤摸瓜找到了MIHCrypto这个库,有两个注意的地方记录如下:
- 如果使用密钥串来进行加密解密,在传递 私钥给MIHCrypto时,要在首尾添加-----BEGIN RSA PRIVATE KEY-----\n和\n-----END RSA PRIVATE KEY-----,公钥不需要,库中会自行添加。如果是使用证书来加密解密,则要在传递公钥时去掉首尾的-----BEGIN PUBLIC KEY-----\n和\n-----END PUBLIC KEY-----,不然会抛异常。
- MIHRSAPublicKey在初始化时采用了MIH_base64EncodedStringWithWrapWidth:的方法来处理传过来的data,之前解密一直不成功就是因为这个导致的,替换成常规方法[[NSStringalloc]initWithData:dataValueencoding:NSUTF8StringEncoding]就解密成功了。
代码
@interface CCRSAUtil :NSObject
/**
初始化方法
@param privateKey 私钥
@param publicKey 公钥
@return RSA加密工具实例
*/
- (instancetype)initWithPrivate:(NSString*)privateKey public:(NSString*)publicKey;
/**
私钥加密
@param string 需要加密的字符串
@return 加密后经过Base64编码的字符串
*/
- (NSString*)privateEncryptWithString:(NSString*)string;
/**
公钥解密
@param encryptString 经过私钥加密的字符串
@return 解密后的明文
*/
- (NSString*)publicDecrypt:(NSString*)encryptString;
@end
@interface CCRSAUtil()
@property(strong,nonatomic)MIHKeyPair*keyPair;
@end
@implementationCCRSAUtil
- (instancetype)initWithPrivate:(NSString *)privateKey public:(NSString *)publicKey {
self = [super init];
if (self) {
if (![privateKey hasPrefix:@"-----BEGIN RSA PRIVATE KEY-----"]) {
privateKey = [@"-----BEGIN RSA PRIVATE KEY-----\n" stringByAppendingString:privateKey];
privateKey = [privateKey stringByAppendingString:@"\n-----END RSA PRIVATE KEY-----"];
}
MIHKeyPair *keyPair = [[MIHKeyPair alloc] init];
MIHRSAPrivateKey *rsaPrivate = [[MIHRSAPrivateKey alloc] initWithData:[privateKey dataUsingEncoding:NSUTF8StringEncoding]];
rsaPrivate.rsaPadding = RSA_PKCS1_PADDING;
keyPair.private = rsaPrivate;
MIHRSAPublicKey *rsaPublic = [[MIHRSAPublicKey alloc] initWithData:[publicKey dataUsingEncoding:NSUTF8StringEncoding]];
rsaPublic.rsaPadding = RSA_PKCS1_PADDING;
keyPair.public = rsaPublic;
self.keyPair = keyPair;
}
return self;
}
#pragma mark -
- (NSString *)privateEncryptWithString:(NSString *)string {
//私钥加密
NSError *signingError = nil;
NSData *message = [string dataUsingEncoding:NSUTF8StringEncoding];// load something to sign from somewhere
NSData *signature = [self.keyPair.private encrypt:message error:&signingError];
if (signingError == nil) {
return [signature MIH_base64EncodedString];
}
return nil;
}
- (NSString *)publicDecrypt:(NSString *)encryptString {
//公钥解密
//*******注意,如果从证书读取公钥,要去掉证书本身自带的头和尾字符*******
NSError *signingError = nil;
NSData *message = [NSData MIH_dataByBase64DecodingString:encryptString];// load something to sign from somewhere
NSData *signature = [self.keyPair.public decrypt:message error:&signingError];
if (signingError == nil) {
return [[NSString alloc] initWithData:signature encoding:NSUTF8StringEncoding];
}
return nil;
}
@end
MIHCrypto支持Cocoapods导入,我fork的一份,把data处理改了一下,需要的同学可以直接使用