目录
1、实现原理
1、加签流程
第一步:对明文进行SHA1算法,生成数据摘要
第二步:使用RSA私钥对摘要内容进行加签操作,生成签名
2、验签流程
2、代码实现
1、 SHA1RSAUtil
#import "SHA1RSAUtil.h"
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import <Security/Security.h>
@implementation SHA1RSAUtil
#pragma mark - 添加私钥
+ (SecKeyRef)addPrivateKey:(NSString *)key{
// This is a base64 encoded key. so, decode it.
NSData *data = [[NSData alloc] initWithBase64EncodedString:key options:NSDataBase64DecodingIgnoreUnknownCharacters];
if(!data){ return nil; }
//a tag to read/write keychain storage
NSString *tag = @"RSA_PRIVATE_KEY";
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;
}
#pragma mark - 添加公钥
+ (SecKeyRef)addPublicKey:(NSString *)pubKey{
NSData *data = [[NSData alloc] initWithBase64EncodedString:pubKey options:NSDataBase64DecodingIgnoreUnknownCharacters];
//a tag to read/write keychain storage
NSString *tag = @"RSA_PUBLIC_KEY";
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;
}
#pragma mark - sha1生成摘要
// digest message with sha1
+ (NSData *)sha1:(NSString *)str
{
const void *data = [str cStringUsingEncoding:NSUTF8StringEncoding];
CC_LONG len = (CC_LONG)strlen(data);
uint8_t * md = malloc( CC_SHA1_DIGEST_LENGTH * sizeof(uint8_t) );;
CC_SHA1(data, len, md);
return [NSData dataWithBytes:md length:CC_SHA1_DIGEST_LENGTH];
}
#pragma mark - 使用sha1rsa生成验签
+ (NSString *)signSHA1WithRSA:(NSString *)content
privateKey:(NSString *)key{
SecKeyRef privateKeyRef = [self addPrivateKey:key];
if (!privateKeyRef) {
NSLog(@"添加私钥失败");
return nil;
}
NSData *sha1Data = [self sha1:content];
uint8_t *sig = NULL;
size_t sig_len = 0;
sig_len = SecKeyGetBlockSize(privateKeyRef);
sig = malloc(sig_len * sizeof(uint8_t));
memset((void *) sig, 0x0, sig_len);
OSStatus status = SecKeyRawSign(
privateKeyRef,
kSecPaddingPKCS1SHA1,
[sha1Data bytes],
CC_SHA1_DIGEST_LENGTH,
sig,
&sig_len
);
if (status != noErr) {
NSLog(@"加签失败:%d",(int)status); return nil;
}
NSData *outData = [NSData dataWithBytes:sig length:sig_len];
NSString * base64String = [outData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
if (sig) {
free(sig);
}
return base64String;
}
#pragma mark - 使用公钥验签
+ (BOOL)verifySHA1WithRSA:(NSString *)content
signature:(NSString *)signature
publicKey:(NSString *)key{
SecKeyRef publicKeyRef = [self addPublicKey:key];
if (!publicKeyRef) { NSLog(@"添加公钥失败"); return NO; }
NSData *originData = [self sha1:content];
NSData *signatureData = [[NSData alloc] initWithBase64EncodedString:signature options:NSDataBase64DecodingIgnoreUnknownCharacters];
if (!originData || !signatureData) { return NO; }
OSStatus status = SecKeyRawVerify(publicKeyRef, kSecPaddingPKCS1SHA1, [originData bytes], originData.length, [signatureData bytes], signatureData.length);
if (status ==noErr) {
return YES;
}
else{
NSLog(@"验签失败:%d",status);
return NO;
}
}
2、使用
//加签
NSData *encodeData = [tempStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [encodeData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
NSString *sign = [SHA1RSAUtil signSHA1WithRSA:base64String privateKey:privateKey];