一.导入系统文件
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCryptor.h>
#import <Security/Security.h>
配置宏
#define kChosenDigestLength CC_SHA1_DIGEST_LENGTH // SHA-1消息摘要的数据位数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]);
}