2014-01-21 76 views
0

在我的應用我存儲在鑰匙串加密的NSString的這個方法解密字符串保存在鑰匙串

NSUInteger fieldHash = [myStringToSave hash]; 
     // Encrypt 
     NSString *fieldString = [KeychainWrapper securedSHA256DigestHashForPIN:fieldHash]; 
     // Save in Keychain 
     if ([KeychainWrapper createKeychainValue:fieldString forIdentifier:PASSWORD]) { 
      [[NSUserDefaults standardUserDefaults] setBool:YES forKey:PASSWORD]; 
      [[NSUserDefaults standardUserDefaults] synchronize]; 

在KeychainWrapper.m有這種方法

+ (BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier 
{ 

    NSMutableDictionary *dictionary = [self setupSearchDirectoryForIdentifier:identifier]; 
    NSData *valueData = [value dataUsingEncoding:NSUTF8StringEncoding]; 
    [dictionary setObject:valueData forKey:(__bridge id)kSecValueData]; 

    // Protect the keychain entry so it's only valid when the device is unlocked. 
    [dictionary setObject:(__bridge id)kSecAttrAccessibleWhenUnlocked forKey:(__bridge id)kSecAttrAccessible]; 

    // Add. 
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL); 

    // If the addition was successful, return. Otherwise, attempt to update existing key or quit (return NO). 
    if (status == errSecSuccess) { 
     return YES; 
    } else if (status == errSecDuplicateItem){ 
     return [self updateKeychainValue:value forIdentifier:identifier]; 
    } else { 
     return NO; 
    } 
} 

+ (NSString *)securedSHA256DigestHashForPIN:(NSUInteger)pinHash 
{ 
    // 1 
    NSString *name = [[NSUserDefaults standardUserDefaults] stringForKey:USERNAME]; 
    name = [name stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
    // 2 
    NSString *computedHashString = [NSString stringWithFormat:@"%@%i%@", name, pinHash, SALT_HASH]; 
    // 3 
    NSString *finalHash = [self computeSHA256DigestForString:computedHashString]; 
    //NSLog(@"** Computed hash: %@ for SHA256 Digest: %@", computedHashString, finalHash); 
    return finalHash; 
} 

+ (NSString*)computeSHA256DigestForString:(NSString*)input 
{ 

    const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding]; 
    NSData *data = [NSData dataWithBytes:cstr length:input.length]; 
    uint8_t digest[CC_SHA256_DIGEST_LENGTH]; 

    CC_SHA256(data.bytes, data.length, digest); 

    // Setup our Objective-C output. 
    NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2]; 

    // Parse through the CC_SHA256 results (stored inside of digest[]). 
    for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++) { 
     [output appendFormat:@"%02x", digest[i]]; 
    } 

    return output; 
} 

爲了獲得存儲在鑰匙串中的值,我使用這個

+ (NSString *)keychainStringFromMatchingIdentifier:(NSString *)identifier 
{ 
    NSData *valueData = [self searchKeychainCopyMatchingIdentifier:identifier]; 
    if (valueData) { 
     NSString *value = [[NSString alloc] initWithData:valueData 
               encoding:NSUTF8StringEncoding]; 
     return value; 
    } else { 
     return nil; 
    } 
} 

使標識符PASSWORD這樣

NSString *myNewString = [KeychainWrapper keychainStringFromMatchingIdentifier:PASSWORD]; 

的問題是,它出來的字符串的加密其中我不能使用。有關如何解密它的任何建議? 在此先感謝

回答

1

以上代碼中的任何內容都不會加密任何內容。您似乎通過NSString hash然後SHA-256運行您的值。這兩個都是單向哈希值。按照設計,它們不能被顛倒。

一般來說,這段代碼非常混亂,目前還不清楚你想達到什麼目的。您通常不會加密您要放入鑰匙串的數據。

請注意,您的散列函數將截斷多字節字符串(例如中文)。

const char *cstr = [input cStringUsingEncoding:NSUTF8StringEncoding]; 
NSData *data = [NSData dataWithBytes:cstr length:input.length]; 

這應該是:

NSData *data = [input dataUsingEncoding:NSUTF8StringEncoding]; 
+0

我很抱歉,如果它的混亂,它只是一個模板,我發現。所以你告訴我沒有辦法用這種編碼進行反轉,並且我應該將項目存儲在鑰匙串中而不用任何編碼?最好的辦法是刪除所有的散列函數?無論如何感謝您的答案! – r4id4

+0

永遠不要複製加密代碼,也不要對它正在做什麼有一個明確的概念。所有代碼都是如此,但對於安全代碼來說卻是雙重的。非常不安全地執行加密代碼非常容易。對於這種情況,你可能只需要調用'+ createKeychainValue:forIdentifier:'而沒有其他任何東西,但不清楚你想要解決什麼問題。如果你有一些特定的問題,最好在這裏問一個問題,而不是尋找代碼示例。 –

+0

我想實現的目的是編碼一些數據並將其保存在鑰匙串中以實現雙重保護。然後,我需要獲取數據,但它是編碼的,我無法提供「解碼」。但正如你所說,我所做的是單向的,所以不能逆轉。再次感謝您的回覆。 – r4id4

1

此代碼是從雷Wenderlich網站的教程之一。請參閱:http://www.raywenderlich.com/6475/basic-security-in-ios-5-tutorial-part-1以獲取更多信息

的基本想法是,你保存它之前在鑰匙串,使用方法,您對密碼進行加密:

  • (的NSString *)securedSHA256DigestHashForPIN:(NSUInteger)pinHash;
  • (NSString *)computeSHA256DigestForString:(NSString *)input;

然後,當用戶輸入密碼時,您可以用相同的方法對其進行加密,並比較這兩個值以查看用戶是否輸入了正確的密碼。正如其他答案所說,您不能反轉加密以查找密碼,但如果您只是將存儲的密碼與輸入的密碼進行比較,則不需要。

我認爲在進入鑰匙串的過程中加密密碼可能過分,因爲無論如何密碼都應該被加密和保護,但無論如何不會看到任何傷害(除非您需要檢索原始密碼)。

如果您正在尋找加密和解密的字符串,然後檢查了這個問題:

AES Encryption for an NSString on the iPhone