RSA Algorithm and Its Use in iOS, RSA Algorithm Used in iOS
Because the project needs to transmit the user password, in order to ensure security, we need to use RSA encryption, So we learned how to use RSA encryption in iOS. On the history and principle of RSA, the following two articles are very clear: http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.html http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html simply speaking, RSA is built on a mathematical problem, is the decomposition of large numbers: it is very easy to multiply two large prime numbers, but it is extremely difficult to break down the product by line. Where is the difficulty? It's a mathematician... After understanding this, We can roughly understand the principle of RSA: asymmetric encryption (1) Party B generates two keys (Public Key and private key ). The Public Key is public and can be obtained by anyone. The private key is kept confidential. (2) Party A obtains Party B's public key and then uses it to encrypt the information. (3) Party B obtains the encrypted information and decrypts it with the private key. It is like a set of Special locks and keys. The locks are made public. Everyone can use them to lock their things. Only those with keys can open them. So the question is, since the lock is public, cannot the lock structure be used to reverse the key shape? The answer is: no! Because the lock is special, it is especially difficult to push backwards. (This is not an absolute solution. Maybe the mathematical problem of big data decomposition will be solved in the future, and this algorithm will not be safe. For details, see the link at the beginning.) The application scenario I met is, the client has the server's public key. The client needs to encrypt the user's password with the public key and upload it to the server. The server can use the private key for decryption. So what the client needs to do is to use the public key given by the server for RSA encryption. There is no direct RSA encryption API on iOS. The Code on gitHub is similar, mainly three methods (copied from the https://github.com/ideawu/Objective-C-RSA) note that there is a kSecPaddingPKCS1 in the Code is written by the author, and our project needs to pass kSecPaddingNone !!!
+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{// Skip ASN.1 public key headerif (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_RSAstatic 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 bufferreturn([NSData dataWithBytes:&c_key[idx] length:len - idx]);}
+ (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 = [RSA stripPublicKeyHeader:data];if(!data){return nil;}NSString *tag = @"what_the_fuck_is_this";NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];// Delete any old lingering key with the same tagNSMutableDictionary *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 keySecKeyRef keyRef = nil;status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);if(status != noErr){return nil;}return keyRef;}
1 + (NSString *) encryptData :( NSData *) data publicKey :( NSString *) pubKey {2 if (! Data |! PubKey) {3 return nil; 4} 5 SecKeyRef keyRef = [RSA addPublicKey: pubKey]; 6 if (! KeyRef) {7 return nil; 8} 9 10 const uint8_t * srcbuf = (const uint8_t *) [data bytes]; 11 size_t srclen = (size_t) data. length; 12 13 size_t outlen = SecKeyGetBlockSize (keyRef) * sizeof (uint8_t); 14 if (srclen> outlen-11) {15 CFRelease (keyRef); 16 return nil; 17} 18 void * outbuf = malloc (outlen); 19 20 OSStatus status = noErr; 21 status = SecKeyEncrypt (keyRef, 22 kSecPaddingNone, // the original author wrote kSecPaddingPKCS1. Chunge's study is written here as kSecPaddingNone to conform to our use of 23 srcbuf, 24 srclen, 25 outbuf, 26 & outlen27); 28 NSString * ret = nil; 29 if (status! = 0) {30 // NSLog (@ "SecKeyEncrypt fail. error Code: % ld ", status); 31} else {32 NSData * data = [NSData dataWithBytes: outbuf length: outlen]; 33 ret = base64_encode_data (data ); 34} 35 free (outbuf); 36 CFRelease (keyRef); 37 return ret; 38}
There is also an article can refer to: http://blog.iamzsx.me/show.html? Id = 155002 the signature mechanism is not enough to encrypt a specific parameter. It also needs to ensure that the request is not tampered with, so the signature mechanism is necessary. MD5 Signature is relatively simple and commonly used: Obtain the string A to be signed (such as A url), and combine it with the key agreed on by the server to form A new string B, perform the MD5 Algorithm on B to obtain the signature C, and then send C together as the signature of A to the server. After the server receives the request, it uses the same algorithm as the key agreed by the client to obtain C'. If C = C', it indicates that the request has not been tampered, otherwise, if the verification fails, the RSA signature can also be executed, which is a little more troublesome than the MD5 Signature, because the client needs to generate a public key private key pair, the basic process is to get the string A (such as A url) to be signed like the MD5 Signature, and use the private key to encrypt the string B, then, the server sends B and the original data A along with its own public key to the server. The server receives the request and decrypts it with the public key to obtain B '. If B = B ', it indicates that the original data has not been tampered with; otherwise, the verification fails. It is also said that after B is obtained here, C needs to be encrypted again with the public key of the server, and C and the original data are sent to the server together with its own public key. After the server receives the data, you need to use your own private key to decrypt and get C' again, and then use the client's public key to decrypt to get B ', and then the same as above... I haven't used RSA signature and verification yet, so I still need to study how to implement it. I want to add it !!! HTTPShttps is a typical application of RSA encryption. However, the private key of the server's public key is not produced by itself, but issued by the CA. The principle of a lot of online, one of which: http://jingyan.baidu.com/article/2fb0ba4048e15500f3ec5f7e.html