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& ...
随机推荐
- Intel Naming Strategy--2
http://en.wikipedia.org/wiki/Intel_Corporation#Naming_strategy Naming strategy[edit] In 2006, Intel ...
- python xmlrpc
rpc 协议 RPC = Remote Procedure Call Protocol,即远程过程调用协议. xml rpc 协议 使用http协议作为传输协议,使用xml文本传输命令和数据的一种协议 ...
- 标准C头文件
ISO C标准定义的头文件: POSIX标准定义的必须的头文件: POSIX标准定义的XSI可选头文件: POSIX标准定义的可选头文件:
- 初学c的一点体会
自学C语言的一些体会1 从最初什么都不知道变成知道一点,一转眼就过去了三个多月,最开始只是刚进大学,感觉太闲了不太好就决定学点什么,于是就到图书馆逛了一圈找找看有什么有趣的书可以看看,刚好就在书架上看 ...
- (转)C中的volatile用法
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进 ...
- SQL 通配符及其使用
Sql Server中通配符的使用 通配符_ "_"号表示任意单个字符,该符号只能匹配一个字符."_"可以放在查询条件的任意位置,且只能代表一个字符.一个汉字只 ...
- dataTables-details 1.9
本文共四部分:官网 | 基本使用|遇到的问题|属性表 一:官方网站:[http://www.datatables.net/] 二:基本使用:[http://www.guoxk.com/node/jqu ...
- hihoCoder 1578 Visiting Peking University 【贪心】 (ACM-ICPC国际大学生程序设计竞赛北京赛区(2017)网络赛)
#1578 : Visiting Peking University 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Ming is going to travel for ...
- 百度dureos CMake Error
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage CMake Error: CMAKE_CXX_COMPILER not set, ...
- 概率dp集合
bzoj1076 你正在玩你最喜欢的电子游戏,并且刚刚进入一个奖励关.在这个奖励关里,系统将依次随机抛出k次宝物,每次你都可以选择吃或者不吃(必须在抛出下一个宝物之前做出选择,且现在决定不吃的宝物以后 ...