iOS RSA (Objc)
/* RSA.h
@author: ideawu
@link: https://github.com/ideawu/Objective-C-RSA
*/ #import <Foundation/Foundation.h> @interface RSA : NSObject // return base64 encoded string
+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
// return raw data
+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;
// return base64 encoded string
// enc with private key NOT working YET!
//+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey;
// return raw data
//+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey; // decrypt base64 encoded string, convert result to string(not base64 encoded)
+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey;
+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey;
+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey;
+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey; @end
/* RSA.m
@author: ideawu
@link: https://github.com/ideawu/Objective-C-RSA
*/ #import "RSA.h"
#import <Security/Security.h> @implementation RSA /*
static NSString *base64_encode(NSString *str){
NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
if(!data){
return nil;
}
return base64_encode_data(data);
}
*/ static NSString *base64_encode_data(NSData *data){
data = [data base64EncodedDataWithOptions:];
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;
} + (NSData *)stripPublicKeyHeader:(NSData *)d_key{
// Skip ASN.1 public key header
if (d_key == nil) return(nil); unsigned long len = [d_key length];
if (!len) return(nil); unsigned char *c_key = (unsigned char *)[d_key bytes];
unsigned int idx = ; if (c_key[idx++] != 0x30) return(nil); if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + ;
else idx++; // PKCS #1 rsaEncryption szOID_RSA_RSA
static unsigned char seqiod[] =
{ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
0x01, 0x05, 0x00 };
if (memcmp(&c_key[idx], seqiod, )) return(nil); idx += ; if (c_key[idx++] != 0x03) return(nil); if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + ;
else idx++; if (c_key[idx++] != '\0') return(nil); // Now make a new NSData from this buffer
return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
} //credit: http://hg.mozilla.org/services/fx-home/file/tip/Sources/NetworkAndStorage/CryptoUtils.m#l1036
+ (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
// Skip ASN.1 private key header
if (d_key == nil) return(nil); unsigned long len = [d_key length];
if (!len) return(nil); unsigned char *c_key = (unsigned char *)[d_key bytes];
unsigned int idx = ; //magic byte at offset 22 if (0x04 != c_key[idx++]) return nil; //calculate length of the key
unsigned int c_len = c_key[idx++];
int det = c_len & 0x80;
if (!det) {
c_len = c_len & 0x7f;
} else {
int byteCount = c_len & 0x7f;
if (byteCount + idx > len) {
//rsa length field longer than buffer
return nil;
}
unsigned int accum = ;
unsigned char *ptr = &c_key[idx];
idx += byteCount;
while (byteCount) {
accum = (accum << ) + *ptr;
ptr++;
byteCount--;
}
c_len = accum;
} // Now make a new NSData from this buffer
return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
} + (SecKeyRef)addPublicKey:(NSString *)key{
NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
if(spos.location != NSNotFound && epos.location != NSNotFound){
NSUInteger s = spos.location + spos.length;
NSUInteger e = epos.location;
NSRange range = NSMakeRange(s, e-s);
key = [key substringWithRange:range];
}
key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@" " withString:@""]; // This will be base64 encoded, decode it.
NSData *data = base64_decode(key);
data = [RSA stripPublicKeyHeader:data];
if(!data){
return nil;
} //a tag to read/write keychain storage
NSString *tag = @"RSAUtil_PubKey";
NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]]; // Delete any old lingering key with the same tag
NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
[publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
SecItemDelete((__bridge CFDictionaryRef)publicKey); // Add persistent version of the key to system keychain
[publicKey setObject:data forKey:(__bridge id)kSecValueData];
[publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
kSecAttrKeyClass];
[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
kSecReturnPersistentRef]; CFTypeRef persistKey = nil;
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
if (persistKey != nil){
CFRelease(persistKey);
}
if ((status != noErr) && (status != errSecDuplicateItem)) {
return nil;
} [publicKey removeObjectForKey:(__bridge id)kSecValueData];
[publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; // Now fetch the SecKeyRef version of the key
SecKeyRef keyRef = nil;
status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
if(status != noErr){
return nil;
}
return keyRef;
} + (SecKeyRef)addPrivateKey:(NSString *)key{
NSRange spos;
NSRange epos;
spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
if(spos.length > ){
epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];
}else{
spos = [key rangeOfString:@"-----BEGIN PRIVATE KEY-----"];
epos = [key rangeOfString:@"-----END PRIVATE KEY-----"];
}
if(spos.location != NSNotFound && epos.location != NSNotFound){
NSUInteger s = spos.location + spos.length;
NSUInteger e = epos.location;
NSRange range = NSMakeRange(s, e-s);
key = [key substringWithRange:range];
}
key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
key = [key stringByReplacingOccurrencesOfString:@" " withString:@""]; // This will be base64 encoded, decode it.
NSData *data = base64_decode(key);
data = [RSA stripPrivateKeyHeader:data];
if(!data){
return nil;
} //a tag to read/write keychain storage
NSString *tag = @"RSAUtil_PrivKey";
NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]]; // Delete any old lingering key with the same tag
NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
[privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
[privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
[privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
SecItemDelete((__bridge CFDictionaryRef)privateKey); // Add persistent version of the key to system keychain
[privateKey setObject:data forKey:(__bridge id)kSecValueData];
[privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
kSecAttrKeyClass];
[privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
kSecReturnPersistentRef]; CFTypeRef persistKey = nil;
OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
if (persistKey != nil){
CFRelease(persistKey);
}
if ((status != noErr) && (status != errSecDuplicateItem)) {
return nil;
} [privateKey removeObjectForKey:(__bridge id)kSecValueData];
[privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
[privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
[privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; // Now fetch the SecKeyRef version of the key
SecKeyRef keyRef = nil;
status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
if(status != noErr){
return nil;
}
return keyRef;
} /* START: Encryption & Decryption with RSA private key */ + (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
const uint8_t *srcbuf = (const uint8_t *)[data bytes];
size_t srclen = (size_t)data.length; size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
void *outbuf = malloc(block_size);
size_t src_block_size = block_size - ; NSMutableData *ret = [[NSMutableData alloc] init];
for(int idx=; idx<srclen; idx+=src_block_size){
//NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
size_t data_len = srclen - idx;
if(data_len > src_block_size){
data_len = src_block_size;
} size_t outlen = block_size;
OSStatus status = noErr;
status = SecKeyEncrypt(keyRef,
kSecPaddingPKCS1,
srcbuf + idx,
data_len,
outbuf,
&outlen
);
if (status != ) {
NSLog(@"SecKeyEncrypt fail. Error Code: %d", (int)status);
ret = nil;
break;
}else{
[ret appendBytes:outbuf length:outlen];
}
} free(outbuf);
CFRelease(keyRef);
return ret;
} + (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey{
NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] privateKey:privKey];
NSString *ret = base64_encode_data(data);
return ret;
} + (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey{
if(!data || !privKey){
return nil;
}
SecKeyRef keyRef = [RSA addPrivateKey:privKey];
if(!keyRef){
return nil;
}
return [RSA encryptData:data withKeyRef:keyRef];
} + (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
const uint8_t *srcbuf = (const uint8_t *)[data bytes];
size_t srclen = (size_t)data.length; size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
UInt8 *outbuf = malloc(block_size);
size_t src_block_size = block_size; NSMutableData *ret = [[NSMutableData alloc] init];
for(int idx=; idx<srclen; idx+=src_block_size){
//NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
size_t data_len = srclen - idx;
if(data_len > src_block_size){
data_len = src_block_size;
} size_t outlen = block_size;
OSStatus status = noErr;
status = SecKeyDecrypt(keyRef,
kSecPaddingNone,
srcbuf + idx,
data_len,
outbuf,
&outlen
);
if (status != ) {
NSLog(@"SecKeyEncrypt fail. Error Code: %d", (int)status);
ret = nil;
break;
}else{
//the actual decrypted data is in the middle, locate it!
int idxFirstZero = -;
int idxNextZero = (int)outlen;
for ( int i = ; i < outlen; i++ ) {
if ( outbuf[i] == ) {
if ( idxFirstZero < ) {
idxFirstZero = i;
} else {
idxNextZero = i;
break;
}
}
} [ret appendBytes:&outbuf[idxFirstZero+] length:idxNextZero-idxFirstZero-];
}
} free(outbuf);
CFRelease(keyRef);
return ret;
} + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
data = [RSA decryptData:data privateKey:privKey];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return ret;
} + (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
if(!data || !privKey){
return nil;
}
SecKeyRef keyRef = [RSA addPrivateKey:privKey];
if(!keyRef){
return nil;
}
return [RSA decryptData:data withKeyRef:keyRef];
} /* END: Encryption & Decryption with RSA private key */ /* START: Encryption & Decryption with RSA public key */ + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
NSString *ret = base64_encode_data(data);
return ret;
} + (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
if(!data || !pubKey){
return nil;
}
SecKeyRef keyRef = [RSA addPublicKey:pubKey];
if(!keyRef){
return nil;
}
return [RSA encryptData:data withKeyRef:keyRef];
} + (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{
NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
data = [RSA decryptData:data publicKey:pubKey];
NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return ret;
} + (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{
if(!data || !pubKey){
return nil;
}
SecKeyRef keyRef = [RSA addPublicKey:pubKey];
if(!keyRef){
return nil;
}
return [RSA decryptData:data withKeyRef:keyRef];
} /* END: Encryption & Decryption with RSA public key */ @end
转载请注明出处:http://www.cnblogs.com/ficow/p/7132266.html
iOS RSA (Objc)的更多相关文章
- iOS RSA加解密签名和验证
转自:http://www.jianshu.com/p/81b0b54436b8 Pre:在公司负责了一个项目,需要用到iOS RSA验证签名的功能.后台给我的仅仅是一个公钥的字符串.经过起初的一段时 ...
- iOS RSA非对称加密测试流程
非对称加密需要两把钥匙:公钥和秘钥. 单向加密:一般情况下服务器会持有秘钥和公钥,那该怎么使用呢?以注册场景为例,最初服务器持有公钥和密钥. 用户注册时不是直接发送用户名,密码,验证码等明文信息给服务 ...
- iOS RSA加密解密及签名验证
1.首先要下载openssl,这个不用说,直接官网下载或者用brew install openssl下载 2.终端生成私钥密钥 2.1生成私钥 openssl genrsa - 2.2生成密钥 ope ...
- IOS RSA 加密方式
采用RSA加密方式,主要是生成公钥和私钥,公钥用来加密,私钥用来解密,至于其中如何实现的,网上有很多原理. 参见如下: https://github.com/jslim89/RSA-objc PS: ...
- ios专题 - objc runtime 动态增加属性
objective-c中,有类别可以在不修改源码的基础上增加方法:近排在看别人的开源代码时,发现还可以动态增加属性.而且是在运行时,太牛B了. 使用运行时库,必须要先引入 objc/runtime.h ...
- iOS RSA 加密解密及签名验证
1.首先要下载openssl.这个不用说,直接官网下载或者用brew install openssl下载. 2.终端生成私钥密钥. 2.1生成私钥 openssl genrsa - 2.2生成密钥 o ...
- iOS RSA的加密和签名
1.RSA加密使用服务端给的公钥.pem,RSA签名使用客户端的私钥.pem. 参考文章:http://www.jianshu.com/p/4580bee4f62f 把文件夹导入项目中,然后配置这两个 ...
- ios RSA 验签加密解密
关于公钥和私钥的生成,网上有很多本地生产的方法,我遇到的问题是,按照网上生产的方式生成7个文件,本地使用没有问题,但是和后台交互就不行了. 发现生成公钥和私钥的没有那么麻烦,使用在线生产工具就能使用, ...
- iOS RSA 证书加密
#import "GLQyRsa.h" #import "GLSupprot.h" #import "GLLoginViewController.h& ...
随机推荐
- 基于SpringMVC框架使用ECharts3.0实现堆叠条形图的绘制(下篇)
<script type="text/javascript"> $().ready(function() { var myChart = echarts.init(do ...
- 记录魅族m1note编译TWRP recovery 3.1.0-0,包括mtk机型的处理方法
1.安装64位linux系统,我用的是deepin os 15.3 2.将系统升级到最新版本 sudo apt-get update && sudo apt-get upgrade 3 ...
- WPF DataGrid 获取选中 一行 或者 多行
WPF中DataGrid使用时,需要将其SelectedItem转换成DataRowView进行操作 然而SelectedItem 与SelectedItems DataGrid的SelectionU ...
- A JavaScript library for reading EXIF meta data from image files.
exif-js/exif-js: JavaScript library for reading EXIF image metadata https://github.com/exif-js/exif- ...
- 设置Android Studio工程布局文件的默认布局
每次创建新的工程后,布局文件的的布局总是ConstraintLayout,如何更改? 进入Android Studio安装目录,用文本编辑器打开文件plugins\android\lib\templa ...
- BZOJ2327: [HNOI2011]勾股定理
BZOJ2327: [HNOI2011]勾股定理 Description 题解Here! 这是一道神题... 我一开始把题目看错了,我以为是在$n$根木棒中选两个$i,j$满足$gcd(i,j)==1 ...
- js中的width问题
1.在jQuery中,width()方法用于获得元素宽度: innerWidth()方法用于获得包括内边界(padding)的元素宽度, outerWidth()方法用于获得包括内边界(padding ...
- asp.net cookie and session
客户端只保存session id,信息存在服务端 Session状态应该存储在两个地方,分别是客户端和服务器端. 客户端只负责保存相应网站的SessionID,而其他的Session信息则保存在服务器 ...
- Java 给Thread传递参数
一开始我想把run()函数写成有参函数来传值,后来发现行不通.经过查找,最终用如下方法传递了参数: 也就是用另外一个有参函数setTar()传递参数. 调用的时候用这4行code传递参数: 上面是用i ...
- 09:LGTB 学分块
总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 65536kB 描述 LGTB 最近在学分块,但是他太菜了,分的块数量太多他就混乱了,所以只能分成 3 块 今天他得 ...