2012-04-09 195 views
23

我正在將UIImage轉換爲NSData。現在我需要使用公鑰加密該NSData,並且需要使用私鑰進行解密。請提供一步一步的程序。我需要使用哪種算法?有什麼好的加密和解密庫嗎?還提供一些用於加密和解密的代碼片段。iphone - 如何用公鑰加密NSData並用私鑰解密?

+0

您公鑰,你無法控制它了。每個人都可以將它傳遞給其他任何人,這意味着用你的私鑰加密數據是浪費時間。 – 2012-04-09 13:22:31

+0

@ParthBhatt真的我被卡住了。你可以把代碼樣本發送到我的個人郵箱ID – sachi 2012-04-11 04:46:48

+0

@sachi:是的,但是如果我可以在晚上發送給你,會好嗎?請提供您的電子郵件地址。 – 2012-04-11 05:01:03

回答

18

我已經試過RSA加密和解密的NSString的,你很可能修改它,讓它爲工作的NSData

添加Security.Framework到您的項目包。

ViewController.h代碼如下:

#import <UIKit/UIKit.h> 
#import <Security/Security.h> 

@interface ViewController : UIViewController 
{ 
SecKeyRef publicKey; 
SecKeyRef privateKey; 
    NSData *publicTag; 
    NSData *privateTag; 
} 
- (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer; 
- (void)decryptWithPrivateKey:(uint8_t *)cipherBuffer plainBuffer:(uint8_t *)plainBuffer; 
- (SecKeyRef)getPublicKeyRef; 
- (SecKeyRef)getPrivateKeyRef; 
- (void)testAsymmetricEncryptionAndDecryption; 
- (void)generateKeyPair:(NSUInteger)keySize; 
@end 

ViewController.m文件代碼如下:

#import "ViewController.h" 

const size_t BUFFER_SIZE = 64; 
const size_t CIPHER_BUFFER_SIZE = 1024; 
const uint32_t PADDING = kSecPaddingNone; 
static const UInt8 publicKeyIdentifier[] = "com.apple.sample.publickey"; 
static const UInt8 privateKeyIdentifier[] = "com.apple.sample.privatekey"; 

@implementation ViewController 

-(SecKeyRef)getPublicKeyRef { 

    OSStatus sanityCheck = noErr; 
    SecKeyRef publicKeyReference = NULL; 

    if (publicKeyReference == NULL) { 
     [self generateKeyPair:512]; 
       NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init]; 

     // Set the public key query dictionary. 
     [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass]; 
     [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag]; 
     [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; 
     [queryPublicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef]; 


     // Get the key. 
     sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, (CFTypeRef *)&publicKeyReference); 


     if (sanityCheck != noErr) 
     { 
      publicKeyReference = NULL; 
     } 


//  [queryPublicKey release]; 

    } else { publicKeyReference = publicKey; } 

    return publicKeyReference; } 

- (void)didReceiveMemoryWarning 
{ 
    [super didReceiveMemoryWarning]; 
    // Release any cached data, images, etc that aren't in use. 
} 




- (void)testAsymmetricEncryptionAndDecryption { 

    uint8_t *plainBuffer; 
    uint8_t *cipherBuffer; 
    uint8_t *decryptedBuffer; 



    const char inputString[] = "How to Encrypt data with public key and Decrypt data with private key"; 
    int len = strlen(inputString); 
    // TODO: this is a hack since i know inputString length will be less than BUFFER_SIZE 
    if (len > BUFFER_SIZE) len = BUFFER_SIZE-1; 

    plainBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t)); 
    cipherBuffer = (uint8_t *)calloc(CIPHER_BUFFER_SIZE, sizeof(uint8_t)); 
    decryptedBuffer = (uint8_t *)calloc(BUFFER_SIZE, sizeof(uint8_t)); 

    strncpy((char *)plainBuffer, inputString, len); 

    NSLog(@"init() plainBuffer: %s", plainBuffer); 
    //NSLog(@"init(): sizeof(plainBuffer): %d", sizeof(plainBuffer)); 
    [self encryptWithPublicKey:(UInt8 *)plainBuffer cipherBuffer:cipherBuffer]; 
    NSLog(@"encrypted data: %s", cipherBuffer); 
    //NSLog(@"init(): sizeof(cipherBuffer): %d", sizeof(cipherBuffer)); 
    [self decryptWithPrivateKey:cipherBuffer plainBuffer:decryptedBuffer]; 
    NSLog(@"decrypted data: %s", decryptedBuffer); 
    //NSLog(@"init(): sizeof(decryptedBuffer): %d", sizeof(decryptedBuffer)); 
    NSLog(@"====== /second test ======================================="); 

    free(plainBuffer); 
    free(cipherBuffer); 
    free(decryptedBuffer); 
} 

/* Borrowed from: 
* https://developer.apple.com/library/mac/#documentation/security/conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html 
*/ 
- (void)encryptWithPublicKey:(uint8_t *)plainBuffer cipherBuffer:(uint8_t *)cipherBuffer 
{ 

    NSLog(@"== encryptWithPublicKey()"); 

    OSStatus status = noErr; 

    NSLog(@"** original plain text 0: %s", plainBuffer); 

    size_t plainBufferSize = strlen((char *)plainBuffer); 
    size_t cipherBufferSize = CIPHER_BUFFER_SIZE; 

    NSLog(@"SecKeyGetBlockSize() public = %lu", SecKeyGetBlockSize([self getPublicKeyRef])); 
    // Error handling 
    // Encrypt using the public. 
    status = SecKeyEncrypt([self getPublicKeyRef], 
          PADDING, 
          plainBuffer, 
          plainBufferSize, 
          &cipherBuffer[0], 
          &cipherBufferSize 
          ); 
    NSLog(@"encryption result code: %ld (size: %lu)", status, cipherBufferSize); 
    NSLog(@"encrypted text: %s", cipherBuffer); 
} 

- (void)decryptWithPrivateKey:(uint8_t *)cipherBuffer plainBuffer:(uint8_t *)plainBuffer 
{ 
    OSStatus status = noErr; 

    size_t cipherBufferSize = strlen((char *)cipherBuffer); 

    NSLog(@"decryptWithPrivateKey: length of buffer: %lu", BUFFER_SIZE); 
    NSLog(@"decryptWithPrivateKey: length of input: %lu", cipherBufferSize); 

    // DECRYPTION 
    size_t plainBufferSize = BUFFER_SIZE; 

    // Error handling 
    status = SecKeyDecrypt([self getPrivateKeyRef], 
          PADDING, 
          &cipherBuffer[0], 
          cipherBufferSize, 
          &plainBuffer[0], 
          &plainBufferSize 
          ); 
    NSLog(@"decryption result code: %ld (size: %lu)", status, plainBufferSize); 
    NSLog(@"FINAL decrypted text: %s", plainBuffer); 

} 



- (SecKeyRef)getPrivateKeyRef { 
    OSStatus resultCode = noErr; 
    SecKeyRef privateKeyReference = NULL; 
// NSData *privateTag = [NSData dataWithBytes:@"ABCD" length:strlen((const char *)@"ABCD")]; 
// if(privateKey == NULL) { 
     [self generateKeyPair:512]; 
     NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init]; 

     // Set the private key query dictionary. 
     [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass]; 
     [queryPrivateKey setObject:privateTag forKey:(__bridge id)kSecAttrApplicationTag]; 
     [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; 
     [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef]; 

     // Get the key. 
     resultCode = SecItemCopyMatching((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKeyReference); 
     NSLog(@"getPrivateKey: result code: %ld", resultCode); 

     if(resultCode != noErr) 
     { 
      privateKeyReference = NULL; 
     } 

//  [queryPrivateKey release]; 
// } else { 
//  privateKeyReference = privateKey; 
// } 

    return privateKeyReference; 
} 


#pragma mark - View lifecycle 



- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
} 

- (void)viewDidUnload 
{ 
    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)]; 
    publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)]; 
    [self testAsymmetricEncryptionAndDecryption]; 

} 

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 
} 

- (void)viewWillDisappear:(BOOL)animated 
{ 
    [super viewWillDisappear:animated]; 
} 

- (void)viewDidDisappear:(BOOL)animated 
{ 
    [super viewDidDisappear:animated]; 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    // Return YES for supported orientations 
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 
     return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 
    } else { 
     return YES; 
    } 
} 

- (void)generateKeyPair:(NSUInteger)keySize { 
    OSStatus sanityCheck = noErr; 
    publicKey = NULL; 
    privateKey = NULL; 

// LOGGING_FACILITY1(keySize == 512 || keySize == 1024 || keySize == 2048, @"%d is an invalid and unsupported key size.", keySize); 

    // First delete current keys. 
// [self deleteAsymmetricKeys]; 

    // Container dictionaries. 
    NSMutableDictionary * privateKeyAttr = [[NSMutableDictionary alloc] init]; 
    NSMutableDictionary * publicKeyAttr = [[NSMutableDictionary alloc] init]; 
    NSMutableDictionary * keyPairAttr = [[NSMutableDictionary alloc] init]; 

    // Set top level dictionary for the keypair. 
    [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType]; 
    [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits]; 

    // Set the private key dictionary. 
    [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent]; 
    [privateKeyAttr setObject:privateTag 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:publicTag 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, &publicKey, &privateKey); 
// LOGGING_FACILITY(sanityCheck == noErr && publicKey != NULL && privateKey != NULL, @"Something really bad went wrong with generating the key pair."); 
    if(sanityCheck == noErr && publicKey != NULL && privateKey != NULL) 
    { 
     NSLog(@"Successful"); 
    } 
// [privateKeyAttr release]; 
// [publicKeyAttr release]; 
// [keyPairAttr release]; 
} 


@end 

讓我知道如果你需要更多的幫助。

希望這會有所幫助。

+2

@sachi:這個答案對你有幫助嗎? – 2012-04-10 07:22:43

+1

我把這個文本作爲加密的文本 - 4 [...] - vJNàØmY-ú:º‰aé-™¬> qS•¿]〜ÎoÍ™vIá%sjÂ...◊5s'6ÒW..但我需要base64文本。你有什麼解決方案嗎? ..謝謝 – 2012-12-06 09:41:54

+1

@ParthBhatt - 如何得到這個 - >靜態常量UInt8 publicKeyIdentifier [] =「com.apple.sample.publickey」; static const UInt8 privateKeyIdentifier [] =「com.apple.sample.privatekey」; ,我擁有文件.der&.pem中的所有密鑰。 – 2013-05-23 10:54:02

14

的NSData + AESCrypt.h

#import <Foundation/Foundation.h> 

@interface NSData (AESCrypt) 

- (NSData *)AES256EncryptWithKey:(NSString *)key; 
- (NSData *)AES256DecryptWithKey:(NSString *)key; 

+ (NSData *)dataWithBase64EncodedString:(NSString *)string; 
- (id)initWithBase64EncodedString:(NSString *)string; 

- (NSString *)base64Encoding; 
- (NSString *)base64EncodingWithLineLength:(NSUInteger)lineLength; 

- (BOOL)hasPrefixBytes:(const void *)prefix length:(NSUInteger)length; 
- (BOOL)hasSuffixBytes:(const void *)suffix length:(NSUInteger)length; 

的NSData + AESCrypt.m

#import "NSData+AESCrypt.h" 
#import <CommonCrypto/CommonCryptor.h> 

static char encodingTable[64] = 
{ 
    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 
    'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 
    'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 
    'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' 
}; 

@implementation NSData (AESCrypt) 

- (NSData *)AES256EncryptWithKey:(NSString *)key{ 
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise 
    char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused) 
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

    // fetch key data 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = [self length]; 

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block. 
    //That's why we need to add the size of one block here 
    size_t bufferSize = dataLength + kCCBlockSizeAES128; 
    void *buffer = malloc(bufferSize); 

    size_t numBytesEncrypted = 0; 
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
             keyPtr, kCCKeySizeAES256, 
             NULL /* initialization vector (optional) */, 
             [self bytes], dataLength, /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesEncrypted); 
    if(cryptStatus == kCCSuccess) 
    { 
    //the returned NSData takes ownership of the buffer and will free it on deallocation 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; 
    } 

    free(buffer); //free the buffer 
    return nil; 
} 

- (NSData *)AES256DecryptWithKey:(NSString *)key{ 

    // 'key' should be 32 bytes for AES256, will be null-padded otherwise 
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused) 
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

    // fetch key data 
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; 

    NSUInteger dataLength = [self length]; 

    //See the doc: For block ciphers, the output size will always be less than or 
    //equal to the input size plus the size of one block. 
    //That's why we need to add the size of one block here 
    size_t bufferSize = dataLength + kCCBlockSizeAES128; 
    void *buffer = malloc(bufferSize); 

size_t numBytesDecrypted = 0; 
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding, 
             keyPtr, kCCKeySizeAES256, 
             NULL /* initialization vector (optional) */, 
             [self bytes], dataLength, /* input */ 
             buffer, bufferSize, /* output */ 
             &numBytesDecrypted); 

    if(cryptStatus == kCCSuccess) 
    { 
    //the returned NSData takes ownership of the buffer and will free it on deallocation 
    return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted]; 
    } 

    free(buffer); //free the buffer 
    return nil; 
} 

#pragma mark - 

+ (NSData *)dataWithBase64EncodedString:(NSString *)string 
{ 
    return [[[NSData allocWithZone:nil] initWithBase64EncodedString:string] autorelease]; 
} 

- (id)initWithBase64EncodedString:(NSString *)string 
{ 
    NSMutableData *mutableData = nil; 

    if(string) 
    { 
     unsigned long ixtext = 0; 
     unsigned long lentext = 0; 
     unsigned char ch = 0; 
     unsigned char inbuf[4], outbuf[3]; 
     short i = 0, ixinbuf = 0; 
     BOOL flignore = NO; 
     BOOL flendtext = NO; 
     NSData *base64Data = nil; 
     const unsigned char *base64Bytes = nil; 

     // Convert the string to ASCII data. 
     base64Data = [string dataUsingEncoding:NSASCIIStringEncoding]; 
     base64Bytes = [base64Data bytes]; 
     mutableData = [NSMutableData dataWithCapacity:base64Data.length]; 
     lentext = base64Data.length; 

     while(YES) 
    { 
     if(ixtext >= lentext) break; 
     ch = base64Bytes[ixtext++]; 
     flignore = NO; 

     if((ch >= 'A') && (ch <= 'Z')) ch = ch - 'A'; 
     else if((ch >= 'a') && (ch <= 'z')) ch = ch - 'a' + 26; 
     else if((ch >= '0') && (ch <= '9')) ch = ch - '0' + 52; 
     else if(ch == '+') ch = 62; 
     else if(ch == '=') flendtext = YES; 
     else if(ch == '/') ch = 63; 
     else flignore = YES; 

     if(! flignore) 
     { 
      short ctcharsinbuf = 3; 
      BOOL flbreak = NO; 

      if(flendtext) 
      { 
       if(! ixinbuf) break; 
       if((ixinbuf == 1) || (ixinbuf == 2)) ctcharsinbuf = 1; 
       else ctcharsinbuf = 2; 
       ixinbuf = 3; 
       flbreak = YES; 
      } 

      inbuf [ixinbuf++] = ch; 

      if(ixinbuf == 4) 
      { 
       ixinbuf = 0; 
       outbuf [0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4); 
       outbuf [1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2); 
       outbuf [2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F); 

       for(i = 0; i < ctcharsinbuf; i++) 
       [mutableData appendBytes:&outbuf[i] length:1]; 
      } 

      if(flbreak) break; 
     } 
    } 
} 

    self = [self initWithData:mutableData]; 
    return self; 
} 

#pragma mark - 

    - (NSString *)base64Encoding 
    { 
     return [self base64EncodingWithLineLength:0]; 
    } 

    - (NSString *)base64EncodingWithLineLength:(NSUInteger)lineLength 
    { 
     const unsigned char *bytes = [self bytes]; 
     NSMutableString *result = [NSMutableString stringWithCapacity:self.length]; 
     unsigned long ixtext = 0; 
     unsigned long lentext = self.length; 
     long ctremaining = 0; 
     unsigned char inbuf[3], outbuf[4]; 
     unsigned short i = 0; 
     unsigned short charsonline = 0, ctcopy = 0; 
     unsigned long ix = 0; 

     while(YES) 
     { 
      ctremaining = lentext - ixtext; 
      if(ctremaining <= 0) break; 

      for(i = 0; i < 3; i++) 
      { 
       ix = ixtext + i; 
       if(ix < lentext) inbuf[i] = bytes[ix]; 
       else inbuf [i] = 0; 
      } 

      outbuf [0] = (inbuf [0] & 0xFC) >> 2; 
      outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4); 
      outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6); 
      outbuf [3] = inbuf [2] & 0x3F; 
      ctcopy = 4; 

      switch(ctremaining) 
      { 
       case 1: 
       ctcopy = 2; 
       break; 
       case 2: 
       ctcopy = 3; 
       break; 
      } 

      for(i = 0; i < ctcopy; i++) 
       [result appendFormat:@"%c", encodingTable[outbuf[i]]]; 

      for(i = ctcopy; i < 4; i++) 
       [result appendString:@"="]; 

      ixtext += 3; 
      charsonline += 4; 

      if(lineLength > 0) 
      { 
      if(charsonline >= lineLength) 
      { 
       charsonline = 0; 
       [result appendString:@"\n"]; 
      } 
      } 
    } 

    return [NSString stringWithString:result]; 
    } 
#pragma mark - 
- (BOOL)hasPrefixBytes:(const void *)prefix length:(NSUInteger)length 
{ 
    if(! prefix || ! length || self.length < length) return NO; 
     return (memcmp([self bytes], prefix, length) == 0); 
    } 

    - (BOOL)hasSuffixBytes:(const void *)suffix length:(NSUInteger)length 
    { 
     if(! suffix || ! length || self.length < length) return NO; 
     return (memcmp(((const char *)[self bytes] + (self.length - length)), suffix, length) == 0 ); 
    } 

您可以使用下面的代碼:一旦你放棄

NSData *encryptedData = [UIImagePNGRepresentation(/*your image*/) AES256EncryptWithKey:/*your enc key*/]; 

NSData *plainData = [encryptedData AES256DecryptWithKey:/*your enc key*/]; 

UIImage *img =[UIImage imageWithData:plainData]; 
+1

/*您的密鑰* /可以通過逆向工程應用程序檢索,如果直接作爲字符串存儲在應用程序中。 – 2015-07-02 16:39:34

+0

也不使用兩個鍵 – 2016-12-14 12:50:38