最近公司項目有個需求,在客戶端實現(xiàn)利用私鑰進行RSA加密,公鑰進行解密的需求。之前做過的都是公鑰加密私鑰解密,而且也在別人的文章中看到過不建議用私鑰做加密,不過公司需求如此,只能硬著頭皮上了。
經(jīng)過初步排查,基本確定了iOS源生框架是沒有提供相應的API接口的,只有常規(guī)的公鑰加密私鑰解密。于是開始Google,看了N多文章和問答,鎖定了OpenSSL庫可以實現(xiàn)這個需求,不過這個是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,之前解密一直不成功就是因為這個導致的,替換成常規(guī)方法[[NSStringalloc]initWithData:dataValueencoding:NSUTF8StringEncoding]就解密成功了。
代碼
@interface CCRSAUtil :NSObject
/**
初始化方法
@param privateKey 私鑰
@param publicKey 公鑰
@return RSA加密工具實例
*/
- (instancetype)initWithPrivate:(NSString*)privateKey public:(NSString*)publicKey;
/**
私鑰加密
@param string 需要加密的字符串
@return 加密后經(jīng)過Base64編碼的字符串
*/
- (NSString*)privateEncryptWithString:(NSString*)string;
/**
公鑰解密
@param encryptString 經(jīng)過私鑰加密的字符串
@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處理改了一下,需要的同學可以直接使用