// // JXSecurityUtil.m // shiku_im // // Created by p on 2019/7/10. // Copyright © 2019 Reese. All rights reserved. // #import "JXSecurityUtil.h" #import #import #import "AESUtil.h" #import "DESUtil.h" #import "MD5Util.h" #if DEBUG #define LOGGING_FACILITY(X, Y) \ NSAssert(X, Y); #define LOGGING_FACILITY1(X, Y, Z) \ NSAssert1(X, Y, Z); #else #define LOGGING_FACILITY(X, Y) \ if (!(X)) { \ NSLog(Y); \ } #define LOGGING_FACILITY1(X, Y, Z) \ if (!(X)) { \ NSLog(Y, Z); \ } #endif @interface JXSecurityUtil () @property (strong, nonatomic) NSString * publicIdentifier; @property (strong, nonatomic) NSString * privateIdentifier; @end @implementation JXSecurityUtil{ size_t kSecAttrKeySizeInBitsLength; } +(instancetype)sharedManager { static dispatch_once_t onceToken; static JXSecurityUtil *instance; dispatch_once(&onceToken, ^{ instance = [[JXSecurityUtil alloc] init]; }); return instance; } - (instancetype)init { if ([super init]) { _publicIdentifier = [NSString stringWithFormat:@"com.RSA.publicIdentifier.mykey.%@",g_myself.userId]; _privateIdentifier = [NSString stringWithFormat:@"com.RSA.privateIdentifier.mykey.%@",g_myself.userId]; // 获取本地aes加密后的私钥 _privateAesStr = [g_default objectForKey:kMyPayPrivateKey]; } return self; } #pragma mark ---------RSA--------- // 创建最新秘钥对 - (void)generateKeyPairRSA { _privateKeyRef = [self getRSAPrivateKey]; _publicKeyRef = [self getRSAPublicKeyWithPrivateKey:_privateKeyRef]; // OSStatus sanityCheck = noErr; // _publicKeyRef = NULL; // _privateKeyRef = NULL; // // // First delete current keys. //// [self deleteAsymmetricKeys]; // // // Container dictionaries. // NSMutableDictionary * privateKeyAttr = [NSMutableDictionary dictionaryWithCapacity:0]; // NSMutableDictionary * publicKeyAttr = [NSMutableDictionary dictionaryWithCapacity:0]; // NSMutableDictionary * keyPairAttr = [NSMutableDictionary dictionaryWithCapacity:0]; // // // Set top level dictionary for the keypair. // [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; // [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:kSecAttrKeySizeInBitsLength] forKey:(__bridge id)kSecAttrKeySizeInBits]; // // // Set the private key dictionary. // [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent]; // [privateKeyAttr setObject:_privateIdentifier forKey:(__bridge id)kSecAttrApplicationTag]; // // See SecKey.h to set other flag values. // // // Set the public key dictionary. // [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent]; // [publicKeyAttr setObject:_publicIdentifier forKey:(__bridge id)kSecAttrApplicationTag]; // // See SecKey.h to set other flag values. // // // Set attributes to top level dictionary. // [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs]; // [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs]; // // // SecKeyGeneratePair returns the SecKeyRefs just for educational purposes. // sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &_publicKeyRef, &_privateKeyRef); // LOGGING_FACILITY( sanityCheck == noErr && _publicKeyRef != NULL && _privateKeyRef != NULL, @"Something went wrong with generating the key pair." ); // // NSString *pubStr = [self getPublicKeyAsBase64]; // NSString *pubJavaStr = [self getPublicKeyAsBase64ForJavaServer]; // NSString *priStr = [self getPrivateKeyAsBase64]; // NSLog(@"zhang_pubStr = %@", pubStr); // NSLog(@"zhang_pubJavaStr = %@", pubJavaStr); // NSLog(@"zhang_priStr = %@", priStr); } // RSA创建私钥 - (SecKeyRef)getRSAPrivateKey { NSData* tag = [@"com.example.keys.mykey" dataUsingEncoding:NSUTF8StringEncoding]; NSDictionary* attributes =@{ (id)kSecAttrKeyType : (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeySizeInBits : @1024, (id)kSecPrivateKeyAttrs : @{ (id)kSecAttrIsPermanent : @YES, (id)kSecAttrApplicationTag : tag, }, }; CFErrorRef error = NULL; SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes, &error); if (!privateKey) { NSError *err = CFBridgingRelease(error); // ARC takes ownership // Handle the error. . . NSLog(@"getPrivateKeyError - %@", err); } return privateKey; } // RSA根据私钥获取公钥 - (SecKeyRef)getRSAPublicKeyWithPrivateKey:(SecKeyRef)privateKey{ SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey); return publicKey; } - (void)setPrivateAesStr:(NSString *)privateAesStr { _privateAesStr = privateAesStr; // aes加密后的私钥保存本地 [g_default setObject:privateAesStr forKey:kMyPayPrivateKey]; } // 将秘钥key转data - (NSData *)getKeyBitsFromKey:(SecKeyRef)Key { CFErrorRef error = NULL; NSData* keyData = (NSData*)CFBridgingRelease( // ARC takes ownership SecKeyCopyExternalRepresentation(Key, &error) ); if (!keyData) { NSError *err = CFBridgingRelease(error); // ARC takes ownership // Handle the error. . . NSLog(@"getKeyBitsFromKeyError - %@", err); } return keyData; } // 根据秘钥的base64字符串转换为秘钥key - (SecKeyRef)getRSAKeyWithBase64Str:(NSString *)base64Str isPrivateKey:(BOOL)isPrivateKey { NSData *data = [[NSData alloc]initWithBase64EncodedString:base64Str options:NSDataBase64DecodingIgnoreUnknownCharacters]; // The key is assumed to be public, 2048-bit RSA NSDictionary* options; if (isPrivateKey) { options =@{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate, (id)kSecAttrKeySizeInBits: @1024, }; }else { options =@{ (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA, (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic, (id)kSecAttrKeySizeInBits: @1024, }; } CFErrorRef error = NULL; SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)data, (__bridge CFDictionaryRef)options, &error); if (!key) { NSError *err = CFBridgingRelease(error); // ARC takes ownership // Handle the error. . . } return key; } // 根据通用的key 转换为iOS秘钥base64字符串 - (NSString *)getKeyForJavaServer:(NSData*)keyBits { static const unsigned char _encodedRSAEncryptionOID[15] = { /* Sequence of length 0xd made up of OID followed by NULL */ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00 }; // That gives us the "BITSTRING component of a full DER // encoded RSA public key - We now need to build the rest unsigned char builder[15]; NSMutableData * encKey = [[NSMutableData alloc] init]; int bitstringEncLength; // When we get to the bitstring - how will we encode it? if ([keyBits length ] + 1 < 128 ) bitstringEncLength = 1 ; else bitstringEncLength = (int)(([keyBits length] + 1 ) / 256 ) + 2; // Overall we have a sequence of a certain length builder[0] = 0x30; // ASN.1 encoding representing a SEQUENCE // Build up overall size made up of - // size of OID + size of bitstring encoding + size of actual key size_t i = sizeof(_encodedRSAEncryptionOID) + 2 + bitstringEncLength + [keyBits length]; size_t j = encodeLength(&builder[1], i); [encKey appendBytes:builder length:j +1]; // First part of the sequence is the OID [encKey appendBytes:_encodedRSAEncryptionOID length:sizeof(_encodedRSAEncryptionOID)]; // Now add the bitstring builder[0] = 0x03; j = encodeLength(&builder[1], [keyBits length] + 1); builder[j+1] = 0x00; [encKey appendBytes:builder length:j + 2]; // Now the actual key [encKey appendData:keyBits]; // base64 encode encKey and return return [encKey base64EncodedStringWithOptions:0]; } size_t encodeLength(unsigned char * buf, size_t length) { // encode length in ASN.1 DER format if (length < 128) { buf[0] = length; return 1; } size_t i = (length / 256) + 1; buf[0] = i + 0x80; for (size_t j = 0 ; j < i; ++j) { buf[i - j] = length & 0xFF; length = length >> 8; } return i + 1; } // 删除之前存储的秘钥 - (void)deleteAsymmetricKeys { OSStatus sanityCheck = noErr; NSMutableDictionary * queryPublicKey = [NSMutableDictionary dictionaryWithCapacity:0]; NSMutableDictionary * queryPrivateKey = [NSMutableDictionary dictionaryWithCapacity:0]; NSMutableDictionary * queryServPublicKey = [NSMutableDictionary dictionaryWithCapacity:0]; // Set the public key query dictionary. [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass]; [queryPublicKey setObject:_publicIdentifier forKey:(__bridge id)kSecAttrApplicationTag]; [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; // Set the private key query dictionary. [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass]; [queryPrivateKey setObject:_privateIdentifier forKey:(__bridge id)kSecAttrApplicationTag]; [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; // Delete the private key. sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPrivateKey); LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecItemNotFound, @"Error removing private key, OSStatus == %ld.", (long)sanityCheck ); // Delete the public key. sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPublicKey); LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecItemNotFound, @"Error removing public key, OSStatus == %ld.", (long)sanityCheck ); if (_publicKeyRef) CFRelease(_publicKeyRef); if (_privateKeyRef) CFRelease(_privateKeyRef); } // 获取公钥的base64字符串 - (NSString *)getRSAPublicKeyAsBase64 { return [[self getKeyBitsFromKey:_publicKeyRef] base64EncodedStringWithOptions:0]; } // 获取私钥的base64字符串 - (NSString *)getRSAPrivateKeyAsBase64 { return [[self getKeyBitsFromKey:_privateKeyRef] base64EncodedStringWithOptions:0]; } // 获取通用公钥base64字符串 - (NSString *)getRSAPublicKeyAsBase64ForJavaServer { return [self getKeyForJavaServer:[self getKeyBitsFromKey:_publicKeyRef]]; } // JAVA可用base64秘钥字符串转iOS秘钥字符串 - (NSString *)getPublicKeyFromJavaServer:(NSString *)keyAsBase64 { /* First decode the Base64 string */ NSData *rawFormattedKey = [[NSData alloc] initWithBase64EncodedString:keyAsBase64 options:0]; /* Now strip the uncessary ASN encoding guff at the start */ unsigned char * bytes = (unsigned char *)[rawFormattedKey bytes]; size_t bytesLen = [rawFormattedKey length]; /* Strip the initial stuff */ size_t i = 0; if (bytes[i++] != 0x30) return FALSE; /* Skip size bytes */ if (bytes[i] > 0x80) i += bytes[i] - 0x80 + 1; else i++; if (i >= bytesLen) return FALSE; if (bytes[i] != 0x30) return FALSE; /* Skip OID */ i += 15; if (i >= bytesLen - 2) return FALSE; if (bytes[i++] != 0x03) return FALSE; /* Skip length and null */ if (bytes[i] > 0x80) i += bytes[i] - 0x80 + 1; else i++; if (i >= bytesLen) return FALSE; if (bytes[i++] != 0x00) return FALSE; if (i >= bytesLen) return FALSE; /* Here we go! */ NSData * extractedKey = [NSData dataWithBytes:&bytes[i] length:bytesLen - i]; // Base64 Encoding NSString *javaLessBase64String = [extractedKey base64EncodedStringWithOptions:0]; return javaLessBase64String; } // RSA加密 - (NSData *)encryptMessageRSA:(NSData *)msgData{ return [self encryptMessageRSA:msgData withPublicKey:_publicKeyRef]; } - (NSData *)encryptMessageRSA:(NSData *)msgData withPublicKey:(SecKeyRef)publicKey { NSData *data = msgData; size_t cipherBufferSize = SecKeyGetBlockSize(publicKey); uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t)); memset((void *)cipherBuffer, 0*0, cipherBufferSize); NSData *plainTextBytes = data; size_t blockSize = cipherBufferSize - 11; size_t blockCount = (size_t)ceil([plainTextBytes length] / (double)blockSize); NSMutableData *encryptedData = [NSMutableData dataWithCapacity:0]; for (int i=0; i