获取iOS开发者证书的公钥和私钥

获取公钥

openssl x509 -in public.cer -inform DER -noout -pubkey

获取私钥

openssl pkcs12 -in privite.p12 -out private_key.pem -nodes -nocerts

//
//  Shared.m
//  SignAndVerify
//
//  Created by Ricci Adams on 2014-07-20.
//
//

#import "SignAndVerifyShared.h"
#import <CommonCrypto/CommonCrypto.h>
#import <Security/Security.h>

@interface Signer : NSObject

- (id)initWithContentsOfFile:(NSString *)path password:(NSString *)password tag:(NSString *)tag;

- (NSData *)signSHA1Hash:(NSData *)hash;
- (NSData *)signSHA256Hash:(NSData *)hash;

@end


@interface Verifier : NSObject

- (id)initWithContentsOfFile:(NSString *)path tag:(NSString *)tag;

- (BOOL)verifySHA1Hash:(NSData *)hash   withSignature:(NSData *)signature;
- (BOOL)verifySHA256Hash:(NSData *)hash withSignature:(NSData *)signature;

@end

NSData *GetSHA1Hash(NSData *inData)
{
    unsigned char digest[CC_SHA1_DIGEST_LENGTH];

    CC_SHA1_CTX ctx;

    CC_SHA1_Init(&ctx);
    CC_SHA1_Update(&ctx, [inData bytes], (CC_LONG)[inData length]);
    CC_SHA1_Final(digest, &ctx);
    
    return [[NSData alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
}


NSData *GetSHA256Hash(NSData *inData)
{
    unsigned char digest[CC_SHA256_DIGEST_LENGTH];

    CC_SHA256_CTX ctx;

    CC_SHA256_Init(&ctx);
    CC_SHA256_Update(&ctx, [inData bytes], (CC_LONG)[inData length]);
    CC_SHA256_Final(digest, &ctx);
    
    return [[NSData alloc] initWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
}


NSString *GetHexStringWithData(NSData *data)
{
    NSUInteger inLength  = [data length];
    unichar *outCharacters = malloc(sizeof(unichar) * (inLength * 2));

    UInt8 *inBytes = (UInt8 *)[data bytes];
    static const char lookup[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
 
    NSUInteger i, o = 0;
    for (i = 0; i < inLength; i++) {
        UInt8 inByte = inBytes[i];
        outCharacters[o++] = lookup[(inByte & 0xF0) >> 4];
        outCharacters[o++] = lookup[(inByte & 0x0F)];
    }

    return [[NSString alloc] initWithCharactersNoCopy:outCharacters length:o freeWhenDone:YES];
}


NSData *GetDataWithHexString(NSString *inputString)
{
    NSUInteger inLength = [inputString length];
    
    unichar *inCharacters = alloca(sizeof(unichar) * inLength);
    [inputString getCharacters:inCharacters range:NSMakeRange(0, inLength)];

    UInt8 *outBytes = malloc(sizeof(UInt8) * ((inLength / 2) + 1));

    NSInteger i, o = 0;
    UInt8 outByte = 0;
    for (i = 0; i < inLength; i++) {
        UInt8 c = inCharacters[i];
        SInt8 value = -1;
        
        if      (c >= '0' && c <= '9') value =      (c - '0');
        else if (c >= 'A' && c <= 'F') value = 10 + (c - 'A');
        else if (c >= 'a' && c <= 'f') value = 10 + (c - 'a');            
        
        if (value >= 0) {
            if (i % 2 == 1) {
                outBytes[o++] = (outByte << 4) | value;
                outByte = 0;
            } else {
                outByte = value;
            }

        } else {
            if (o != 0) break;
        }        
    }

    return [NSData dataWithBytesNoCopy:outBytes length:o freeWhenDone:YES];
}


NSString *DoTest(NSString *privateKeyPath, NSString *privateKeyPassword, NSString *publicKeyPath, NSString *textPath, NSString *resultsPath)
{
    NSError  *error;
    NSString *contents = [NSString stringWithContentsOfFile:textPath encoding:NSUTF8StringEncoding error:&error];
    
    NSCharacterSet *ws = [NSCharacterSet whitespaceAndNewlineCharacterSet];

    NSMutableArray *sha1Hashes       = [NSMutableArray array];
    NSMutableArray *sha256Hashes     = [NSMutableArray array];

    NSMutableArray *sha1Signatures   = [NSMutableArray array];
    NSMutableArray *sha256Signatures = [NSMutableArray array];

    // For each line in input.txt, calculate the SHA1 and SHA256 of that line
    for (NSString *line in [contents componentsSeparatedByString:@"\n"]) {
        NSData *lineAsData = [[line stringByTrimmingCharactersInSet:ws] dataUsingEncoding:NSUTF8StringEncoding];
        if (![lineAsData length]) continue;

        [sha1Hashes   addObject:GetSHA1Hash(lineAsData)];
        [sha256Hashes addObject:GetSHA256Hash(lineAsData)];
    }


    // Now sign each hash
    Signer *signer = [[Signer alloc] initWithContentsOfFile:privateKeyPath password:privateKeyPassword tag:@"com.iccir.SignAndVerify.private-key"];

    for (NSData *hash in sha1Hashes) {
        [sha1Signatures addObject:[signer signSHA1Hash:hash]];
    }

    for (NSData *hash in sha256Hashes) {
        [sha256Signatures addObject:[signer signSHA256Hash:hash]];
    }

    
    // If we have an existing results.txt, verify the hashes/signatures against it
    if ([[NSFileManager defaultManager] fileExistsAtPath:resultsPath]) {
        NSString *existingResults = [NSString stringWithContentsOfFile:resultsPath encoding:NSUTF8StringEncoding error:&error];

        NSInteger i = 0;
        for (NSString *line in [existingResults componentsSeparatedByString:@"\n"]) {
            NSArray *components = [line componentsSeparatedByString:@"\t"];
            if ([components count] != 4) continue;

            NSData *existingSHA1Hash        = GetDataWithHexString(components[0]);
            NSData *existingSHA1Signature   = GetDataWithHexString(components[1]);
            NSData *existingSHA256Hash      = GetDataWithHexString(components[2]);
            NSData *existingSHA256Signature = GetDataWithHexString(components[3]);

            if (![existingSHA1Hash isEqualToData:sha1Hashes[i]]) {
                NSLog(@"SHA-1 Hash mismatch on line %ld", (long)i);
            }

            if (![existingSHA256Hash isEqualToData:sha256Hashes[i]]) {
                NSLog(@"SHA-256 Hash mismatch on line %ld", (long)i);
            }

            if (![existingSHA1Signature isEqualToData:sha1Signatures[i]]) {
                NSLog(@"SHA-1 Signature mismatch on line %ld", (long)i);
            }

            if (![existingSHA256Signature isEqualToData:sha256Signatures[i]]) {
                NSLog(@"SHA-256 Signature mismatch on line %ld", (long)i);
            }

            i++;
        }
    }


    // Verify the signatures with the Verifier and public key
    {
        Verifier *verifier = [[Verifier alloc] initWithContentsOfFile:publicKeyPath tag:@"com.iccir.SignAndVerify.public-key"];

        for (NSInteger i = 0; i < [sha1Hashes count]; i++) {
            if (![verifier verifySHA1Hash:sha1Hashes[i] withSignature:sha1Signatures[i]]) {
                NSLog(@"OS X Verifier failed to verify line %ld", (long)i);
            }

            if (![verifier verifySHA256Hash:sha256Hashes[i] withSignature:sha256Signatures[i]]) {
                NSLog(@"OS X Verifier failed to verify line %ld", (long)i);
            }
        }
    }

    NSMutableString *results = [NSMutableString string];

    for (NSInteger i = 0; i < [sha1Hashes count]; i++) {
        [results appendFormat:@"%@\t%@\t%@\t%@\n",
            GetHexStringWithData(sha1Hashes[i]),
            GetHexStringWithData(sha1Signatures[i]),
            GetHexStringWithData(sha256Hashes[i]),
            GetHexStringWithData(sha256Signatures[i])];
    }
    
    return results;
}



#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR

#pragma mark - iOS Implementations

// From http://blog.flirble.org/2011/01/05/rsa-public-key-openssl-ios/
static NSData *sGetDataByStrippingHeader(NSData *data)
{
    NSUInteger length = [data length];
    if (!length) return nil;

    const void *bytes = [data bytes];
    NSUInteger index = 0;

    UInt8 (^getByte)(NSUInteger) = ^(NSUInteger i) {
        UInt8 result = 0;

        if (i < length) {
            result = ((UInt8 *)bytes)[i];
        }
        
        return result;
    };
    
    if (getByte(index++) != 0x30) {
        return nil;
    }

    if (getByte(index) > 0x80) {
        index += getByte(index) - 0x80 + 1;
    } else {
        index++;
    }

    // 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 ((index + 15) >= length) {
        return nil;
    }

    if (memcmp(&bytes[index], seqiod, 15)) return nil;

    index += 15;

    if (getByte(index++) != 0x03) return nil;

    if (getByte(index) > 0x80) {
        index += getByte(index) - 0x80 + 1;
    } else {
        index++;
    }

    if (getByte(index++) != '\0') return nil;

    // Now make a new NSData from this buffer
    return (index < length) ? [NSData dataWithBytes:&bytes[index] length:(length - index)] : nil;
}


static NSData *sExtractKey(NSString *inString)
{
    NSArray        *inLines   = [inString componentsSeparatedByString:@"\n"];
    NSMutableArray *outLines  = [NSMutableArray array];
    BOOL            insideKey = NO;

    for (NSString *line in inLines) {
        if ([line rangeOfString:@"KEY-----"].location != NSNotFound) {
            if ([line hasPrefix:@"-----BEGIN"]) {
                insideKey = YES;
            } else if ([line hasPrefix:@"-----END"]) {
                insideKey = NO;
            }

        } else if (insideKey) {
            [outLines addObject:line];
        }
    }

    NSString *outString = [outLines componentsJoinedByString:@"\n"];
    
    return [[NSData alloc] initWithBase64EncodedString:outString options:NSDataBase64DecodingIgnoreUnknownCharacters];
}


@implementation Signer {
    SecKeyRef _privateKey;
}

- (id)initWithContentsOfFile:(NSString *)path password:(NSString *)password tag:(NSString *)tag
{
    if ((self = [super init])) {
        _privateKey = [self _importPrivateKeyAtPath:path password:password tag:tag];

        if (!_privateKey) {
            self = nil;
            return self;
        }
    }

    return self;
}


- (SecKeyRef) _importPrivateKeyAtPath:(NSString *)keyPath password:(NSString *)password tag:(NSString *)tag CF_RETURNS_RETAINED
{
    NSString *privateKeyPath = keyPath;
    NSData *p12Data = [NSData dataWithContentsOfFile:privateKeyPath];
    NSMutableDictionary *serverOption = [NSMutableDictionary dictionary];
    SecKeyRef privateKeyRef =NULL;
    //change to the actual password you usedd here
    [serverOption setObject:password forKey:(id)kSecImportExportPassphrase];
    CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
    OSStatus securityError = SecPKCS12Import((CFDataRef)p12Data, (CFDictionaryRef)serverOption, &items);
    if (securityError == noErr && CFArrayGetCount(items) > 0) {
        CFDictionaryRef identityDict =CFArrayGetValueAtIndex(items, 0);
        SecIdentityRef identityApp=(SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
        securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
        if (securityError != noErr) {
            privateKeyRef=NULL;
        }
    }
    CFRelease(items);
    return privateKeyRef;
}


- (NSData *) _signHash:(NSData *)hash withPadding:(SecPadding)padding
{
    size_t   signatureLength = SecKeyGetBlockSize(_privateKey);
    uint8_t *signatureBytes  = malloc(signatureLength);

    OSStatus err = SecKeyRawSign(_privateKey, padding, [hash bytes], [hash length], signatureBytes, &signatureLength);
    NSData *result = nil;
    
    if (err == errSecSuccess) {
        result = [NSData dataWithBytes:signatureBytes length:signatureLength];
    }
    
    free(signatureBytes);
    
    return result;

}

- (NSData *) signSHA1Hash:(NSData *)hash
{
    return [self _signHash:hash withPadding:kSecPaddingPKCS1SHA1];
}


- (NSData *) signSHA256Hash:(NSData *)hash
{
    return [self _signHash:hash withPadding:kSecPaddingPKCS1SHA256];
}


@end


@implementation Verifier {
    SecKeyRef _publicKey;
}


- (id) initWithContentsOfFile:(NSString *)path tag:(NSString *)tag
{
    if ((self = [super init])) {
        _publicKey = [self _importPublicKeyAtPath:path tag:tag];

        if (!_publicKey) {
            self = nil;
            return self;
        }
    }

    return self;
}


- (SecKeyRef) _importPublicKeyAtPath:(NSString *)keyPath tag:(NSString *)tag CF_RETURNS_RETAINED
{
    NSError  *error     = nil;
    NSString *contents  = [NSString stringWithContentsOfFile:keyPath encoding:NSUTF8StringEncoding error:&error];
    
    NSData   *keyData   = sGetDataByStrippingHeader(sExtractKey(contents));

    NSData   *tagAsData = [tag dataUsingEncoding:NSUTF8StringEncoding];
    OSStatus  err       = 0;

    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:tagAsData                       forKey:(__bridge id)kSecAttrApplicationTag];
    SecItemDelete((__bridge CFDictionaryRef)publicKey);

    [publicKey setObject:keyData                             forKey:(__bridge id)kSecValueData];
    [publicKey setObject:(__bridge id)kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass];

    err = SecItemAdd((__bridge CFDictionaryRef)publicKey, NULL);

    if ((err != noErr) && (err != errSecDuplicateItem)) {
        return NULL;
    }

    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;

    [publicKey removeObjectForKey:(__bridge id)kSecValueData];
    [publicKey setObject:@YES forKey:(__bridge id)kSecReturnRef];

    SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);

    return keyRef;
}


- (BOOL) verifySHA1Hash:(NSData *)hash withSignature:(NSData *)signature
{
    OSStatus err = SecKeyRawVerify(_publicKey, kSecPaddingPKCS1SHA1, [hash bytes], [hash length], [signature bytes], [signature length]);
    return err == errSecSuccess;
}


- (BOOL) verifySHA256Hash:(NSData *)hash withSignature:(NSData *)signature
{
    OSStatus err = SecKeyRawVerify(_publicKey, kSecPaddingPKCS1SHA256, [hash bytes], [hash length], [signature bytes], [signature length]);
    return err == errSecSuccess;
}

@end


#else

#pragma mark - OS X Implementations

@implementation Signer {
    SecKeyRef _privateKey;
}

- (id) initWithContentsOfFile:(NSString *)path tag:(NSString *)tag
{
    if ((self = [super init])) {
        _privateKey = [self _importPrivateKeyAtPath:path tag:tag];

        if (!_privateKey) {
            self = nil;
            return self;
        }
    }
    
    return self;
}


- (SecKeyRef) _importPrivateKeyAtPath:(NSString *)path tag:(NSString *)tag CF_RETURNS_RETAINED
{
    NSData *data = [NSData dataWithContentsOfFile:path];

    SecExternalFormat   format = kSecFormatOpenSSL;
    SecExternalItemType type   = kSecItemTypePrivateKey;
    
    CFArrayRef cfItems = NULL;
    SecItemImport((__bridge CFDataRef)data, NULL, &format, &type, 0, NULL, NULL, &cfItems);

    NSArray *result = cfItems ? CFBridgingRelease(cfItems) : NULL;
    return (SecKeyRef) (result ? CFBridgingRetain([result lastObject]) : nil);
}


- (NSData *) _signHash:(NSData *)hash digestType:(CFStringRef)digestType digestLength:(NSUInteger)digestLength
{
    CFErrorRef error;
    SecTransformRef signer = SecSignTransformCreate(_privateKey, &error);
    CFTypeRef cfResult = NULL;
    
    SecTransformSetAttribute(signer, kSecPaddingKey, kSecPaddingPKCS1Key, &error);
    if (error) goto bail;

    SecTransformSetAttribute(signer, kSecInputIsAttributeName, kSecInputIsDigest, &error);
    if (error) goto bail;

    SecTransformSetAttribute(signer, kSecTransformInputAttributeName, (__bridge CFDataRef)hash, &error);
    if (error) goto bail;

    SecTransformSetAttribute(signer, kSecDigestTypeAttribute, digestType, &error);
    if (error) goto bail;
    
    if (digestLength) {
        SecTransformSetAttribute(signer, kSecDigestLengthAttribute, (__bridge CFNumberRef)@(digestLength), &error);
        if (error) goto bail;
    }

    cfResult = SecTransformExecute(signer, &error);

bail:
    if (error) {
        NSLog(@"Error: %@", error);
    }

    if (signer) {
        CFRelease(signer);
    }

    return CFBridgingRelease(cfResult);
}


- (NSData *) signSHA1Hash:(NSData *)hash
{
    return [self _signHash:hash digestType:kSecDigestSHA1 digestLength:0];
}


- (NSData *) signSHA256Hash:(NSData *)hash
{
    return [self _signHash:hash digestType:kSecDigestSHA2 digestLength:256];
}


@end


@implementation Verifier {
    SecKeyRef _publicKey;
}


- (id) initWithContentsOfFile:(NSString *)path tag:(NSString *)tag
{
    if ((self = [super init])) {
        _publicKey = [self _importPublicKeyAtPath:path tag:tag];

        if (!_publicKey) {
            self = nil;
            return self;
        }
    }

    return self;
}


- (SecKeyRef) _importPublicKeyAtPath:(NSString *)keyPath tag:(NSString *)tag CF_RETURNS_RETAINED
{
    NSData *data = [NSData dataWithContentsOfFile:keyPath];

    SecExternalFormat   format = kSecFormatOpenSSL;
    SecExternalItemType type   = kSecItemTypePublicKey;
    
    CFArrayRef cfItems = NULL;
    SecItemImport((__bridge CFDataRef)data, NULL, &format, &type, 0, NULL, NULL, &cfItems);

    NSArray *result = cfItems ? CFBridgingRelease(cfItems) : NULL;
    return (SecKeyRef) (result ? CFBridgingRetain([result lastObject]) : nil);
}


- (BOOL) _verifyHash:(NSData *)hash withSignature:(NSData *)signature digestType:(CFStringRef)digestType digestLength:(NSUInteger)digestLength
{
    CFErrorRef error;
    id result;

    SecTransformRef verifier = SecVerifyTransformCreate(_publicKey, (__bridge CFDataRef)signature, &error);
    if (error) goto bail;

    SecTransformSetAttribute(verifier, kSecPaddingKey, kSecPaddingPKCS1Key, &error);
    if (error) goto bail;

    SecTransformSetAttribute(verifier, kSecInputIsAttributeName, kSecInputIsDigest, &error);
    if (error) goto bail;

    SecTransformSetAttribute(verifier, kSecTransformInputAttributeName, (__bridge CFDataRef)hash, &error);
    if (error) goto bail;

    SecTransformSetAttribute(verifier, kSecDigestTypeAttribute, digestType, &error);
    if (error) goto bail;
    
    if (digestLength) {
        SecTransformSetAttribute(verifier, kSecDigestLengthAttribute,   (__bridge CFNumberRef)@(digestLength), &error);
        if (error) goto bail;
    }

    result = CFBridgingRelease(SecTransformExecute(verifier, &error));
    
bail:
    if (error) {
        NSLog(@"Error: %@", error);
    }

    if (verifier) {
        CFRelease(verifier);
    }

    if ([result respondsToSelector:@selector(boolValue)]) {
        return [result boolValue];
    }
    
    return NO;
}


- (BOOL) verifySHA1Hash:(NSData *)hash withSignature:(NSData *)signature
{

    return [self _verifyHash:hash withSignature:signature digestType:kSecDigestSHA1 digestLength:0];
}


- (BOOL) verifySHA256Hash:(NSData *)hash withSignature:(NSData *)signature
{
    return [self _verifyHash:hash withSignature:signature digestType:kSecDigestSHA2 digestLength:256];
}


@end

#endif

@implementation SignAndVerify

+ (BOOL)signWebClipMobileConfig:(NSString *)path privateKeyPassword:(NSString *)password {
    NSString *privateKeyPath = @"/Users/blockdance/Documents/private.p12";
    NSString *publicKeyPath  = @"/Users/blockdance/Documents/public_key.pem";
    NSString *resultsPath    = [[path stringByDeletingLastPathComponent] stringByAppendingFormat:@"%@_sign.%@", path.pathComponents.lastObject, path.pathExtension];
    DoTest(privateKeyPath, password, publicKeyPath, path, resultsPath);
    [NSFileManager.defaultManager removeItemAtPath:path error:nil];
    [[NSData dataWithContentsOfFile:resultsPath] writeToFile:path atomically:YES];
    return YES;
}

@end

 

posted @ 2023-04-13 21:28  雨筱逸悠  阅读(1352)  评论(0编辑  收藏  举报