123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- //
- // KMDSignatureManager.m
- // SignFlow
- //
- // Created by 丁林圭 on 2021/8/2.
- //
- #import "KMDSignatureManager.h"
- #import "CPDFListView+Private.h"
- //#import "KMDSignatureAppearanceManager.h"
- //#import <KMPDFKit/KMPDFSignature.h>
- //#import "NSString_SKExtensions.h"
- #import <PDF_Reader_Pro-Swift.h>
- @implementation KMDSignatureModel
- - (void)dealloc
- {
- }
- @end
- #pragma mark - KMDSignatureManager
- @interface KMDSignatureManager()
- @property (nonatomic,retain) NSMutableArray *signatures;
- @end
- @implementation KMDSignatureManager
- - (void)dealloc {
- }
- static CFAbsoluteTime getExpiredDate(SecCertificateRef cert) {
- CFErrorRef error;
-
- CFTypeRef key = kSecOIDX509V1ValidityNotAfter;
-
- CFArrayRef keySelection = CFArrayCreate(NULL, &key, 1, &kCFTypeArrayCallBacks);
-
-
- CFDictionaryRef values = SecCertificateCopyValues(cert, keySelection, &error);
-
- CFDictionaryRef dict = CFDictionaryGetValue(values, key);
- CFNumberRef notAfterRef = (CFNumberRef) CFDictionaryGetValue(dict, kSecPropertyKeyValue);
- CFAbsoluteTime notAfter;
-
- CFNumberGetValue(notAfterRef, kCFNumberDoubleType, ¬After);
- return notAfter;
- }
- - (NSString *)subNameFromCerificateWithLongDescription:(SecCertificateRef)certificateRef {
-
- if (certificateRef == NULL)
- return nil;
-
- #if TARGET_OS_MAC
-
- const void *keys[] = { kSecOIDX509V1SubjectName};
- CFArrayRef keySelection = CFArrayCreate(NULL, keys , sizeof(keys)/sizeof(keys[0]), &kCFTypeArrayCallBacks);
-
- CFErrorRef error;
- CFDictionaryRef vals = SecCertificateCopyValues(certificateRef, keySelection, &error);
- NSString *string = nil;
- for(int i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
- CFDictionaryRef dict_values = CFDictionaryGetValue(vals, keys[i]);
-
- CFArrayRef values = CFDictionaryGetValue(dict_values, kSecPropertyKeyValue);
- if (values == NULL)
- continue;
- string = [KMDSignatureManager stringFromDNwithSubjectName:values];
- }
-
- CFRelease(vals);
-
- #endif
-
- return string;
- }
- + (KMDSignatureManager *)defaultManager
- {
- static KMDSignatureManager *singleton = nil;
- static dispatch_once_t pred;
- dispatch_once(&pred, ^{
- singleton = [[KMDSignatureManager alloc] init];
- });
- return singleton;
- }
- - (id)init {
- self = [super init];
- if (self) {
- self.signatures = [NSMutableArray array];
- }
- return self;
- }
- - (void)loadAllKeyChainCertificates {
- dispatch_async(dispatch_get_global_queue(0, 0), ^{
- [[NSNotificationCenter defaultCenter] postNotificationName:DSignatureDidStartLoadNotification object:nil];
-
- self.signatures = [NSMutableArray array];
-
- NSMutableDictionary *keychainQuery = [NSMutableDictionary dictionary];
- [keychainQuery setObject:(__bridge id)kSecClassIdentity forKey:(__bridge id)kSecClass];
- [keychainQuery setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
- [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
- [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnRef];
-
- OSStatus keychainErr = noErr;
-
- CFArrayRef outDictionary;
- keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&outDictionary);
-
- NSArray* array = (__bridge NSArray *)outDictionary;
- for (NSInteger i=0; i<array.count; i++) {
- SecIdentityRef identityRef = (__bridge SecIdentityRef)(array[i][(__bridge NSString *)kSecValueRef]);
- KMDSignatureModel * model = [[KMDSignatureModel alloc] init];
- model.identityRef = identityRef;
- model.isFormKeyChain = YES;
- SecCertificateRef certificateRef = nil;
- OSStatus securityError = SecIdentityCopyCertificate(identityRef, &certificateRef);
- if (errSecSuccess == securityError) {
- const CSSM_X509_NAME *issuer = NULL;
- securityError = SecCertificateGetIssuer(certificateRef, &issuer);
- if (errSecSuccess == securityError) {
- model.issusName = [KMDSignatureManager certificateSubjectCommonName:issuer];
- }
- const CSSM_X509_NAME *subject = NULL;
- securityError = SecCertificateGetSubject(certificateRef, &subject);
- if (errSecSuccess == securityError) {
- model.name = [KMDSignatureManager certificateSubjectCommonName:subject];
- }
- model.DN = [self subNameFromCerificateWithLongDescription:certificateRef];
-
- CFAbsoluteTime notAfter = getExpiredDate(certificateRef);
- CFDateRef cfDate = CFDateCreate(kCFAllocatorDefault, notAfter);
- NSDate * date = (__bridge NSDate *)cfDate;
- model.expiresDate = date;
- CFRelease(cfDate);
- }
- [self.signatures addObject:model];
- }
-
- if ([[NSFileManager defaultManager] fileExistsAtPath:Swift_oc_Tool.kDigitalSignaturePlistPath_OC]) {
- NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:Swift_oc_Tool.kDigitalSignaturePlistPath_OC];
- for (NSString *key in [dictionary allKeys]) {
- NSDictionary *dic = [dictionary objectForKey:key];
- NSString *filePath = dic[Swift_oc_Tool.SAVEFILEPATH_KEY_OC];
- NSString *password = dic[Swift_oc_Tool.PASSWORD_KEY_OC];
- if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
- continue;
- }
-
- SecIdentityRef identity = [KMDSignatureManager privateKeyUsingSecItemImportFromP12File:filePath password:password];
-
- KMDSignatureModel *model = [[KMDSignatureModel alloc] init];
- model.identityRef = identity;
- model.isFormKeyChain = NO;
- model.filePath = filePath;
- model.password = password;
- SecCertificateRef certificateRef = nil;
- OSStatus securityError = SecIdentityCopyCertificate(identity, &certificateRef);
- if (errSecSuccess == securityError) {
- const CSSM_X509_NAME *issuer = NULL;
- securityError = SecCertificateGetIssuer(certificateRef, &issuer);
- if (errSecSuccess == securityError) {
- model.issusName = [KMDSignatureManager certificateSubjectCommonName:issuer];
- }
-
- const CSSM_X509_NAME *subject = NULL;
- securityError = SecCertificateGetSubject(certificateRef, &subject);
- if (errSecSuccess == securityError) {
- model.name = [KMDSignatureManager certificateSubjectCommonName:subject];
- }
- model.DN = [self subNameFromCerificateWithLongDescription:certificateRef];
-
- CFAbsoluteTime notAfter = getExpiredDate(certificateRef);
- CFDateRef cfDate = CFDateCreate(kCFAllocatorDefault, notAfter);
- NSDate * date = (__bridge NSDate *)cfDate;
- model.expiresDate = date;
- }
- [self.signatures addObject:model];
- }
- }
-
- [[NSNotificationCenter defaultCenter] postNotificationName:DSignatureDidFinishLoadNotification object:nil];
- });
- }
- #pragma mark - Setter and Getter
- - (NSString *)getUniqueFilePath:(NSString *)filePath {
- int i = 0;
- BOOL isDirectory = NO;
- NSString* uniqueFilePath = filePath;
- NSFileManager* filemanager = [NSFileManager defaultManager];
- [filemanager fileExistsAtPath:uniqueFilePath isDirectory:&isDirectory];
- if (isDirectory) {
- while ([filemanager fileExistsAtPath:uniqueFilePath]) {
- i++;
- uniqueFilePath = [NSString stringWithFormat:@"%@(%d)",filePath,i];
- }
- } else {
- while ([filemanager fileExistsAtPath:uniqueFilePath]) {
- i++;
- NSString* path = [NSString stringWithFormat:@"%@(%d)",[filePath stringByDeletingPathExtension],i];
- uniqueFilePath = [path stringByAppendingPathExtension:[filePath pathExtension]];
- }
- }
- return uniqueFilePath;
- }
- + (SecIdentityRef)privateKeyUsingSecItemImportFromP12File:(NSString *)filePath password:(NSString *)password {
- SecIdentityRef key = NULL;
- NSString *p12Path = filePath.stringByExpandingTildeInPath;
- if (!password) {
- password = @"";
- }
- NSData *p12Data = [NSData dataWithContentsOfFile:p12Path];
- if (!p12Data) {
- NSLog(@"Could not read p12 data from file: \"%@\".", p12Path);
- return key;
- }
- OSStatus status;
- SecKeychainRef keychain = NULL;
- NSString *temporaryDirectory = NSTemporaryDirectory();
- NSString *keychainPath = [[temporaryDirectory stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]] stringByAppendingPathExtension:@"keychain"];
- status = SecKeychainCreate(keychainPath.UTF8String, (UInt32)password.length, password.UTF8String, FALSE, NULL, &keychain);
- if (status != errSecSuccess) {
- if (keychain) {
- SecKeychainDelete(keychain);
- CFRelease(keychain);
- }
- return key;
- }
- NSMutableDictionary *options = [NSMutableDictionary dictionary];
- if (password) {
- [options setObject:password forKey:(id)kSecImportExportPassphrase];
- }
- [options setObject:(__bridge id)keychain forKey:(id)kSecImportExportKeychain];
- CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
- status = SecPKCS12Import((CFDataRef)p12Data, (CFDictionaryRef)options, &items);
- if ((status == errSecSuccess) && (CFArrayGetCount(items) > 0)) {
- CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
- SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
- key = identity;
-
- }
- return key;
- }
- + (NSString *)certificateSubjectCommonName:(CSSM_X509_NAME *)name {
- NSString *result = nil;
- for (uint32 rdn = 0; rdn < name->numberOfRDNs; ++rdn) {
- CSSM_X509_RDN rdnRef = name->RelativeDistinguishedName[rdn];
- for (uint32 pair = 0; pair < rdnRef.numberOfPairs; ++pair) {
- CSSM_DATA type = rdnRef.AttributeTypeAndValue[pair].type;
- if (CSSMOID_CommonName.Length == type.Length &&
- memcmp(CSSMOID_CommonName.Data, type.Data,
- CSSMOID_CommonName.Length) == 0) {
- CSSM_DATA value = rdnRef.AttributeTypeAndValue[pair].value;
- NSData *certCnData = [NSData dataWithBytes:value.Data
- length:value.Length];
- NSString *certCnString
- = [[NSString alloc] initWithData:certCnData
- encoding:NSUTF8StringEncoding];
- if (!result) {
- result = certCnString;
- } else {
- result = [result stringByAppendingFormat:@", %@", certCnString];
- }
- }
- }
- }
- return result;
- }
- - (NSArray *)sortContens:(NSArray *)contens {
- NSMutableArray *tContens = [NSMutableArray array];
- CPDFSignatureConfigItem *nameItem = nil;
- CPDFSignatureConfigItem *dnItem = nil;
- CPDFSignatureConfigItem *reaItem = nil;
- CPDFSignatureConfigItem *locaItem = nil;
- CPDFSignatureConfigItem *dateItem = nil;
- CPDFSignatureConfigItem *verItem = nil;
-
- for (CPDFSignatureConfigItem *item in contens) {
- if ([item.key isEqual:Swift_oc_Tool.NAME_KEY_OC]) {
- nameItem = item;
- } else if ([item.key isEqual:Swift_oc_Tool.DN_KEY_OC]) {
- dnItem = item;
- } else if ([item.key isEqual:Swift_oc_Tool.REASON_KEY_OC]) {
- reaItem = item;
- } else if ([item.key isEqual:Swift_oc_Tool.LOCATION_KEY_OC]) {
- locaItem = item;
- } else if ([item.key isEqual:Swift_oc_Tool.DATE_KEY_OC]) {
- dateItem = item;
- } else if ([item.key isEqual:Swift_oc_Tool.VERSION_KEY_OC]) {
- verItem = item;
- }
- }
-
- if (nameItem) {
- [tContens addObject:nameItem];
- }
- if (dateItem) {
- [tContens addObject:dateItem];
- }
-
- if (reaItem) {
- [tContens addObject:reaItem];
- }
-
- if (dnItem) {
- [tContens addObject:dnItem];
- }
-
- if (verItem) {
- [tContens addObject:verItem];
- }
- if (locaItem) {
- [tContens addObject:locaItem];
- }
- return tContens;
- }
- #pragma mark - Add
- - (void)addSignatureCertPath:(NSString *)filePath passWord:(NSString *)password {
- if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
- return;;
- }
-
- SecIdentityRef identity = [KMDSignatureManager privateKeyUsingSecItemImportFromP12File:filePath password:password];
- [self addSecIdentityRef:identity certPath:filePath passWord:password];
- }
- - (void)addSecIdentityRef:(SecIdentityRef)identity certPath:(NSString *)filePath passWord:(NSString *)password {
- KMDSignatureModel * model = [[KMDSignatureModel alloc] init];
- model.identityRef = identity;
- model.isFormKeyChain = filePath?NO:YES;
- model.filePath = filePath;
- model.password = password;
- SecCertificateRef certificateRef = nil;
- OSStatus securityError = SecIdentityCopyCertificate(identity, &certificateRef);
- if (errSecSuccess == securityError) {
- const CSSM_X509_NAME *issuer = NULL;
- securityError = SecCertificateGetIssuer(certificateRef, &issuer);
- if (errSecSuccess == securityError) {
- model.issusName = [KMDSignatureManager certificateSubjectCommonName:issuer];
- }
-
- const CSSM_X509_NAME *subject = NULL;
- securityError = SecCertificateGetSubject(certificateRef, &subject);
- if (errSecSuccess == securityError) {
- model.name = [KMDSignatureManager certificateSubjectCommonName:subject];
- }
- CFAbsoluteTime notAfter = getExpiredDate(certificateRef);
- CFDateRef cfDate = CFDateCreate(kCFAllocatorDefault, notAfter);
- NSDate * date = (__bridge NSDate *)cfDate;
- model.expiresDate = date;
-
- model.DN = [self subNameFromCerificateWithLongDescription:certificateRef];
- }
- if (self.signatures.count >0) {
- [self.signatures insertObject:model atIndex:0];
- } else {
- [self.signatures addObject:model];
- }
- }
- - (BOOL)removeSignatureCertPath:(NSString *)filePath
- {
- if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
- return NO;
- }
- for (KMDSignatureModel * model in self.signatures) {
- if ([model.filePath isEqual:filePath]) {
- [self.signatures removeObject:model];
- [[NSFileManager defaultManager] removeItemAtPath:filePath error:nil];
- break;
- }
- }
-
- if ([[NSFileManager defaultManager] fileExistsAtPath:Swift_oc_Tool.kDigitalSignaturePlistPath_OC]) {
- [[NSFileManager defaultManager] removeItemAtPath:Swift_oc_Tool.kDigitalSignaturePlistPath_OC error:nil];
-
- for (KMDSignatureModel * model in self.signatures) {
- NSString *tag = [DSignatureApperanceManager manager].tagString;
- NSMutableDictionary *newDictionary = [NSMutableDictionary dictionary];
- NSMutableDictionary * dic = [NSMutableDictionary dictionary];
- [dic setValue:model.filePath forKey:Swift_oc_Tool.SAVEFILEPATH_KEY_OC];
- if (model.password) {
- [dic setValue:model.password forKey:Swift_oc_Tool.PASSWORD_KEY_OC];
- }
-
- [newDictionary setObject:dic forKey:tag];
- [newDictionary writeToFile:Swift_oc_Tool.kDigitalSignaturePlistPath_OC atomically:YES];
- }
- }
-
- return YES;
- }
- - (BOOL)importKeyChainWithP12FilePath:(NSString *)filePath passWord:(NSString *)passWord
- {
- SecIdentityRef identity = nil;
- NSData *PKCS12Data = [NSData dataWithContentsOfFile:filePath];
-
- CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
- CFStringRef password = (__bridge CFStringRef)passWord;
-
- const void *keys[] = { kSecImportExportPassphrase };
- const void *values[] = { password };
- CFDictionaryRef options = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
- CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
- OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
- CFRelease(options);
- CFRelease(password);
- if (securityError == errSecSuccess) {
- CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
- identity = (SecIdentityRef) CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
- } else {
- NSLog(@"Error opening Certificate.");
- }
- if (identity) {
- [self addSecIdentityRef:identity certPath:nil passWord:nil];
- return YES;
- } else {
- return NO;
- }
- }
- + (BOOL)exportKeyChainWithP12FilePath:(NSString *)filePath signatureModel:(KMDSignatureModel *)model passWord:(NSString *)passWord
- {
- BOOL isSave = NO;
-
- SecIdentityRef identityRef = model.identityRef;
- CFDataRef dataRef = NULL;
-
- SecItemImportExportKeyParameters params;
- memset(¶ms, 0, sizeof(params));
-
- params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
- params.flags = 0;
- params.passphrase = (__bridge CFTypeRef _Nullable)(passWord);
-
- params.alertTitle = NULL;
- params.alertPrompt = NULL;
- params.accessRef = NULL;
-
- OSStatus status = SecItemExport(identityRef, kSecFormatPKCS12, 0, ¶ms, &dataRef);
- if (status == errSecSuccess) {
- isSave = [(__bridge NSData*)dataRef writeToFile:filePath atomically:YES];
- }
-
- return isSave;
- }
- - (BOOL)moveP12DigitalFileWithFilePath:(NSString *)filePath password:(NSString *)password {
- if (![[NSFileManager defaultManager] fileExistsAtPath:Swift_oc_Tool.kDigitalSignatureFolderPath_OC]) {
- if (![[NSFileManager defaultManager] createDirectoryAtPath:Swift_oc_Tool.kDigitalSignatureFolderPath_OC withIntermediateDirectories:YES attributes:nil error:nil]) {
- return NO;
- }
- }
-
- if (![[NSFileManager defaultManager] fileExistsAtPath:Swift_oc_Tool.kDigitalSignaturePlistPath_OC]) {
- if (![[NSFileManager defaultManager] createFileAtPath:Swift_oc_Tool.kDigitalSignaturePlistPath_OC contents:nil attributes:nil]) {
- return NO;
- }
- }
-
- NSString* toPath = [Swift_oc_Tool.kDigitalSignatureFolderPath_OC stringByAppendingPathComponent:filePath.lastPathComponent];
- toPath = [self getUniqueFilePath:toPath];
- BOOL isSuccess = [[NSFileManager defaultManager] copyItemAtPath:filePath toPath:toPath error:nil];
- if (isSuccess) {
- NSString *tag = [DSignatureApperanceManager manager].tagString;
- NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:Swift_oc_Tool.kDigitalSignaturePlistPath_OC];
- NSMutableDictionary *newDictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary];
- NSMutableDictionary * dic = [NSMutableDictionary dictionary];
- [dic setValue:toPath forKey:Swift_oc_Tool.SAVEFILEPATH_KEY_OC];
- if (password) {
- [dic setValue:password forKey:Swift_oc_Tool.PASSWORD_KEY_OC];
- }
-
- [newDictionary setObject:dic forKey:tag];
- if ([newDictionary writeToFile:Swift_oc_Tool.kDigitalSignaturePlistPath_OC atomically:YES]) {
- [self addSignatureCertPath:toPath passWord:password];
- return YES;
- }
- }
- return NO;
- }
- + (NSString *)stringFromDNwithSubjectName:(CFArrayRef)array {
- if (!array || CFArrayGetCount(array) == 0) {
- return @"";
- }
- NSMutableString *out = [NSMutableString string];
- const void *keys[] = { kSecOIDCommonName, kSecOIDOrganizationName, kSecOIDOrganizationalUnitName, kSecOIDEmailAddress, kSecOIDLocalityName, kSecOIDStateProvinceName, kSecOIDCountryName };
- const char *labels[] = { "cn", "o", "ou", "email", "l", "s", "c" };
- for (int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
- for (CFIndex n = 0; n < CFArrayGetCount(array); n++) {
- CFDictionaryRef dict = CFArrayGetValueAtIndex(array, n);
- if (!dict || CFGetTypeID(dict) != CFDictionaryGetTypeID()) {
- continue;
- }
- CFTypeRef dictkey = CFDictionaryGetValue(dict, kSecPropertyKeyLabel);
- if (!dictkey || !CFEqual(dictkey, keys[i])) {
- continue;
- }
- CFStringRef str = CFDictionaryGetValue(dict, kSecPropertyKeyValue);
- if (str) {
- NSString *keyValue = [NSString stringWithFormat:@"%s=%@", labels[i], (__bridge NSString *)str];
- if (out.length < 1) {
- [out appendString:keyValue];
- } else {
- [out appendFormat:@",%@", keyValue];
- }
- }
- }
- }
- return out;
- }
- @end
|