2016-03-03 21 views
-1

任何人都可以告訴我爲什麼ios中的3des會在ios中每次onload時產生不同的編碼字符串?最初我將「密鑰」轉換爲md5格式的字符串,然後在3des中使用相同的密鑰來生成編碼值。ios中的3des每次在加載時提供不同的加密值?

這裏是我的代碼:

-(NSData *)tripleDesEncryptString:(NSString *)input key:(NSString*)key error:(NSError **)error{ 
    //TDES 
    NSParameterAssert(input); 
    NSParameterAssert(key); 
    NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding]; 
    NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding]; 
    size_t outLength; 
    //NSAssert(keyData.length == kCCKeySize3DES, @"the keyData is an invalid size"); 
    NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length + kCCBlockSize3DES)]; 
    CCCryptorStatus result = CCCrypt(
     kCCEncrypt, // operation 
     kCCAlgorithm3DES, // Algorithm 
     kCCOptionECBMode | kCCOptionPKCS7Padding, // options 
     keyData.bytes, // key 
     keyData.length, // keylength 
     nil, // iv 
     inputData.bytes, // dataIn 
     inputData.length, // dataInLength, 
     outputData.mutableBytes, // dataOut 
     outputData.length, // dataOutAvailable 
     &outLength // dataOutMoved 
    ); 

    if (result != kCCSuccess) { 
     if (error != NULL) { 
      *error = [NSError errorWithDomain:@"com.your_domain.your_project_name.your_class_name." code:result userInfo:nil]; 
     } 
     return nil; 
    } 
    [outputData setLength:outLength]; 
    return outputData; 
} 

-(void) testEncryptionAndDecryption { 
    NSString *str [email protected]"[email protected]#$%^&*()"; 
    id md5data =[str MD5]; 
    NSString *md5dataString =(NSString *)md5data; 
    NSData *encrypted = [self tripleDesEncryptString:@"[email protected]:123" key:md5dataString error:nil]; 
    NSString *strData = [encrypted base64EncodedStringWithOptions:0]; 
    NSLog(@"encrypted data length: %@",strData); 
    NSString *str2 = [[NSString alloc] initWithData:encrypted encoding:NSUTF8StringEncoding]; 
    NSLog(@"%@",str2); 
} 
+0

1.簡單的答案是因爲輸入參數不相同,檢查參數是準確的正確的長度。 2.不要使用3DES進行新的工作,它不安全,請使用AES。不要ECB模式,這是不安全的。 – zaph

+0

**切勿使用[ECB模式](http://crypto.stackexchange.com/q/14487/13022)**。它是確定性的,因此不具有語義安全性。你應該至少是使用隨機模式,如[CBC(http://crypto.stackexchange.com/q/22260/13022)或[CTR](http://crypto.stackexchange.com/a/2378/ 13022)。最好是對密文進行身份驗證,以便像[padding oracle attack](http://crypto.stackexchange.com/q/18185/13022)這樣的攻擊是不可能的。這可以通過驗證模式(如GCM或EAX)或[加密 - 然後MAC](http://crypto.stackexchange.com/q/202/13022)方案完成。 –

+0

其實**從不**有點強。如果你的加密數據長度恰好是一個塊(沒有填充),並且密鑰是唯一的並且隨機生成的,那麼添加IV和CBC模式就什麼都不會了。目前有些情況下,這是按照現行標準完成的。 – zaph

回答

2

測試代碼是有缺陷的。

NSString *str [email protected]"[email protected]#$%^&*()"; 
id md5data =[str MD5]; 
NSString *md5dataString =(NSString *)md5data; 

目前還不清楚MD5是什麼,可能是一個類別?

MD5的函數產生一個16字節的結果,但3DES需要一個24字節密鑰。

NSString *str2 = [[NSString alloc] initWithData:encrypted encoding:NSUTF8StringEncoding];將失敗,因爲任意的數據可以機器人被表示爲字符串。這就是爲什麼使用Base64的原因。

這真的是最好寫的是需要返回NSData參數和做在它之外的任何字符串操作的加密方法。這創造了單一責任方法。

這裏是一個重構版本 - 但仍然不安全:

-(NSData *)tripleDesEncryptData:(NSData *)data 
          key:(NSData*)key 
          error:(NSError **)error { 
    NSParameterAssert(data); 
    NSParameterAssert(key); 
    NSAssert(key.length == kCCKeySize3DES, @"the keyData is an invalid size"); 

    size_t outLength; 
    NSMutableData *outputData = [NSMutableData dataWithLength:(data.length + kCCBlockSize3DES)]; 

    CCCryptorStatus 
    result = CCCrypt(kCCEncrypt, // operation 
        kCCAlgorithm3DES, // Algorithm 
        kCCOptionECBMode | kCCOptionPKCS7Padding , // options 
        key.bytes, // key 
        key.length, // keylength 
        nil,// iv 
        data.bytes, // dataIn 
        data.length, // dataInLength, 
        outputData.mutableBytes, // dataOut 
        outputData.length, // dataOutAvailable 
        &outLength); // dataOutMoved 

    if (result != kCCSuccess) { 
     if (error != NULL) { 
      *error = [NSError errorWithDomain:@"com.your_domain.your_project_name.your_class_name." 
             code:result 
            userInfo:nil]; 
     } 
     return nil; 
    } 
    [outputData setLength:outLength]; 
    return outputData; 
} 

- (NSData *)hash192String:(NSString *)inputString { 
    NSData *inputData = [inputString dataUsingEncoding:NSUTF8StringEncoding]; 
    NSMutableData *hash = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH]; 

    CC_SHA256(inputData.bytes, (unsigned int)inputData.length, hash.mutableBytes); 

    return [hash subdataWithRange:NSMakeRange(0, 24)]; 
} 


-(void) testEncryptionAndDecryption { 
    NSString *md5String = @"[email protected]#$%^&*()"; 
    NSString *stringData = @"[email protected]:123"; 

    NSData *keyData = [self hash192String:md5String]; 
    NSData *data  = [stringData dataUsingEncoding:NSUTF8StringEncoding]; 
    NSData *encrypted = [self tripleDesEncryptData:data key:keyData error:nil]; 

    NSString *encryptedBase64 = [encrypted base64EncodedStringWithOptions:0]; 

    NSLog(@"encrypted base64\nlength: %lu\nstring: %@", (unsigned long)encryptedBase64.length, encryptedBase64); 
} 

輸出:

加密的base64
長度:32
字符串:+ VSdzF4BmAMnGITAWFqaY2mgp8Nr8I13

+0

是的,它是category.from md5我可以得到32byte key.is它3DES需要完全24byte的密鑰? – adarshaU

+0

是的,3DES需要一個24字節的密鑰,您生成密鑰的方式可能是使用'md5data'後面的任何數據。另外,演員:'NSString * md5dataString =(NSString *)md5data;'是可疑的。 – zaph

+0

我直接嘗試使用字符串NSString * md5data = [str MD5];但沒有變化 – adarshaU

0
func testCrypt(data:NSData, keyData:NSData, ivData:NSData) -> String { 

    var base64cryptString = String() 
    let cryptData = NSMutableData(length: Int(data.length) + kCCBlockSizeAES128)! 
    let keyLength    = size_t(kCCKeySizeAES128) 
    let operation: CCOperation = UInt32(kCCEncrypt) 
    let algoritm: CCAlgorithm = UInt32(kCCAlgorithmAES128) 
    let options: CCOptions = UInt32(kCCOptionPKCS7Padding) 

    var numBytesEncrypted :size_t = 0 
    let cryptStatus = CCCrypt(operation, 
           algoritm, 
           options, 
           keyData.bytes, keyLength, 
           ivData.bytes, 
           data.bytes, data.length, 
           cryptData.mutableBytes, cryptData.length, 
           &numBytesEncrypted) 

    if UInt32(cryptStatus) == UInt32(kCCSuccess) { 
     cryptData.length = Int(numBytesEncrypted) 
     base64cryptString = cryptData.base64EncodedString(options: .endLineWithLineFeed) 
    } 
    return base64cryptString 
} 

你可以通過它需要加密的數據和NSData的格式鍵和值調用func testCrypt(data:NSData, keyData:NSData, ivData:NSData)

例如:

let data: NSData! = message.data(using: .utf8) as NSData!; 
let keyData: NSData! = keyValue.data(using: .utf8) as NSData!; 
let ivData: NSData! = ivValue.data(using: .utf8) as NSData!; 
var base64cryptString = self.testCrypt(data: data, keyData: keyData, ivData: ivData) 
+0

您能否提供關於此解決方案的更多信息? – Arcath

+0

你可以通過傳遞需要加密的數據,密鑰和NSData格式的值來調用 func testCrypt(數據:NSData,keyData:NSData,ivData:NSData)。例如: 讓數據:NSData! = message.data(使用:.utf8)作爲NSData! 讓keyData:NSData! = keyValue.data(使用:.utf8)作爲NSData! 讓ivData:NSData! = ivValue.data(使用:.utf8)作爲NSData! var base64cryptString = self.testCrypt(data:data,keyData:keyData,ivData:ivData) –