iOS 中使用sha1withRSA加密字符串

一.導(dǎo)入系統(tǒng)文件

#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import <Security/Security.h>

配置宏

#define kChosenDigestLength CC_SHA1_DIGEST_LENGTH // SHA-1消息摘要的數(shù)據(jù)位數(shù)160位
#define kPrivateKey @"你的私鑰"
#define kPublicKey @"你的公鑰"

SHA1+RSA 簽名

signSHA1WithRSA 為加簽

verifySHA1WithRSA 為驗簽 驗簽返回1為正確

+ (NSString *)signSHA1WithRSA:(NSString *)plainText{

uint8_t* signedBytes = NULL;

size_t signedBytesSize = 0;

OSStatus sanityCheck = noErr;

NSData* signedHash = nil;

SecKeyRef privateKeyRef = [self addPrivateKey:kPrivateKey];

signedBytesSize = SecKeyGetBlockSize(privateKeyRef);

NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];

signedBytes = malloc( signedBytesSize * sizeof(uint8_t) );

memset((void  *)signedBytes, 0x0, signedBytesSize);

sanityCheck = SecKeyRawSign(privateKeyRef,

kSecPaddingPKCS1SHA1,

(const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],

kChosenDigestLength,

(uint8_t *)signedBytes,

&signedBytesSize);

if (sanityCheck == noErr){

signedHash = [NSData dataWithBytes:(const void  *)signedBytes length:(NSUInteger)signedBytesSize];

}

else{

return nil;

}

if (signedBytes){

free(signedBytes);

}

NSString *signatureResult = [self base64EncodeData:signedHash];

return signatureResult;

}




+ (NSData *)getHashBytes:(NSData *)plainText {

CC_SHA1_CTX ctx;

uint8_t * hashBytes = NULL;

NSData * hash = nil;

// Malloc a buffer to hold hash.

hashBytes = malloc( kChosenDigestLength * sizeof(uint8_t) );

memset((void  *)hashBytes, 0x0, kChosenDigestLength);

// Initialize the context.

CC_SHA1_Init(&ctx);

// Perform the hash.

CC_SHA1_Update(&ctx, (void  *)[plainText bytes], [plainText length]);

// Finalize the output.

CC_SHA1_Final(hashBytes, &ctx);

// Build up the SHA1 blob.

hash = [NSData dataWithBytes:(const void  *)hashBytes length:(NSUInteger)kChosenDigestLength];

if (hashBytes) free(hashBytes);

return hash;

}




#pragma mark - SHA1+RSA 驗簽

+ (NSString *)signSHA1WithRSA:(NSString *)plainText{

uint8_t* signedBytes = NULL;

size_t signedBytesSize = 0;

OSStatus sanityCheck = noErr;

NSData* signedHash = nil;

SecKeyRef privateKeyRef = [self addPrivateKey:kPrivateKey];

signedBytesSize = SecKeyGetBlockSize(privateKeyRef);

NSData *plainTextBytes = [plainText dataUsingEncoding:NSUTF8StringEncoding];

signedBytes = malloc( signedBytesSize * sizeof(uint8_t) );

memset((void  *)signedBytes, 0x0, signedBytesSize);

sanityCheck = SecKeyRawSign(privateKeyRef,

kSecPaddingPKCS1SHA1,

(const uint8_t *)[[self getHashBytes:plainTextBytes] bytes],

kChosenDigestLength,

(uint8_t *)signedBytes,

&signedBytesSize);

if (sanityCheck == noErr){

signedHash = [NSData dataWithBytes:(const void  *)signedBytes length:(NSUInteger)signedBytesSize];

}

else{

return nil;

}

if (signedBytes){

free(signedBytes);

}

NSString *signatureResult = [self base64EncodeData:signedHash];

return signatureResult;

}




+ (NSData *)getHashBytes:(NSData *)plainText {

CC_SHA1_CTX ctx;

uint8_t * hashBytes = NULL;

NSData * hash = nil;

// Malloc a buffer to hold hash.

hashBytes = malloc( kChosenDigestLength * sizeof(uint8_t) );

memset((void  *)hashBytes, 0x0, kChosenDigestLength);

// Initialize the context.

CC_SHA1_Init(&ctx);

// Perform the hash.

CC_SHA1_Update(&ctx, (void  *)[plainText bytes], [plainText length]);

// Finalize the output.

CC_SHA1_Final(hashBytes, &ctx);

hash = [NSData dataWithBytes:(const void  *)hashBytes length:(NSUInteger)kChosenDigestLength];

if (hashBytes) free(hashBytes);

return hash;

}

#pragma mark - SHA1+RSA 驗簽

+ (BOOL)verifySHA1WithRSA:(NSString *)plainString signature:(NSString *)signatureString{

NSData *plainData = [plainString dataUsingEncoding:NSUTF8StringEncoding];

NSData *signatureData = [self base64DecodeString:signatureString];

SecKeyRef publicKey = [self addPublicKey:kPublicKey];

size_t signedHashBytesSize = SecKeyGetBlockSize(publicKey);

const void* signedHashBytes = [signatureData bytes];

size_t hashBytesSize = CC_SHA1_DIGEST_LENGTH;

uint8_t* hashBytes = malloc(hashBytesSize);

if (!CC_SHA1([plainData bytes], (CC_LONG)[plainData length], hashBytes)) {

return NO;

}

OSStatus status = SecKeyRawVerify(publicKey,

kSecPaddingPKCS1SHA1,

hashBytes,

hashBytesSize,

signedHashBytes,

signedHashBytesSize);

return status == errSecSuccess;

}




#pragma mark - Base64

+ (NSString *)base64EncodeData:(NSData *)data{

data = [data base64EncodedDataWithOptions:0];

NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

return ret;

}




+ (NSData *)base64DecodeString:(NSString *)string{

NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:NSDataBase64DecodingIgnoreUnknownCharacters];

return data;

}




+ (SecKeyRef)addPrivateKey:(NSString *)key{

NSRange spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];

NSRange epos = [key rangeOfString:@"-----END RSA 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:@""];

NSData *data = base64_decode(key);

data = [self stripPrivateKeyHeader:data];

if(!data){

return nil;

}

NSString *tag = @"RSAUtil_PrivKey";

NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

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);

[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];

SecKeyRef keyRef = nil;

status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);

if(status != noErr){

return nil;

}

return keyRef;

}

static NSData *base64_decode(NSString *str){

NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];

return data;

}



+ (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    = 22; //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 = 0;

unsigned char *ptr = &c_key[idx];

idx += byteCount;

while (byteCount) {

accum = (accum << 8) + *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 = [self 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;

}



+ (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    = 0;

if (c_key[idx++] != 0x30) return(nil);

if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;

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, 15)) return(nil);

idx += 15;

if (c_key[idx++] != 0x03) return(nil);

if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;

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]);

}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拄轻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖洁桌,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件渴频,死亡現(xiàn)場離奇詭異蕾各,居然都是意外死亡冶忱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門登馒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匙握,“玉大人,你說我怎么就攤上這事陈轿∪Ψ模” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵麦射,是天一觀的道長蛾娶。 經(jīng)常有香客問我,道長潜秋,這世上最難降的妖魔是什么蛔琅? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮半等,結(jié)果婚禮上揍愁,老公的妹妹穿的比我還像新娘。我一直安慰自己杀饵,他們只是感情好莽囤,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著切距,像睡著了一般朽缎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上谜悟,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天话肖,我揣著相機與錄音,去河邊找鬼葡幸。 笑死最筒,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蔚叨。 我是一名探鬼主播床蜘,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蔑水!你這毒婦竟也來了邢锯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤搀别,失蹤者是張志新(化名)和其女友劉穎丹擎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體歇父,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡蒂培,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年再愈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片护戳。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡践磅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出灸异,到底是詐尸還是另有隱情,我是刑警寧澤羔飞,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布肺樟,位于F島的核電站,受9級特大地震影響逻淌,放射性物質(zhì)發(fā)生泄漏么伯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一卡儒、第九天 我趴在偏房一處隱蔽的房頂上張望田柔。 院中可真熱鬧,春花似錦骨望、人聲如沸硬爆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缀磕。三九已至,卻和暖如春劣光,著一層夾襖步出監(jiān)牢的瞬間袜蚕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工绢涡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留牲剃,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓雄可,卻偏偏與公主長得像凿傅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子滞项,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1 基礎(chǔ) 1.1 對稱算法 描述:對稱加密是指加密過程和解密過程使用相同的密碼狭归。主要分:分組加密、序列加密文判。 原理...
    御淺永夜閱讀 2,375評論 1 4
  • feisky云計算过椎、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 3,827評論 0 5
  • 1、App支付簡介 買家在手機戏仓、掌上電腦等無線設(shè)備的應(yīng)用程序內(nèi)疚宇,可通過支付寶進行付款購買特定服務(wù)或商品亡鼠,資金即時到...
    PZcoder閱讀 43,991評論 5 22
  • 今天考試,老師給了假范圍敷待,我想去絞頭间涵。
    王宇宙她姐玉娘閱讀 119評論 0 0
  • 熱修復(fù) 隨著移動互聯(lián)網(wǎng)的快速發(fā)展,用戶對app的品質(zhì)要求也越來越高榜揖,對于app來說如果有bug影響到用戶體驗勾哩,那對...
    BigBigArvin閱讀 447評論 0 0