2014-05-13 3 views
2

제 프로젝트에서 AES 128 CBC 암호화를 구현해야합니다. Category를 사용하고 NSData를 기반으로합니다. 이것은 내 암호화 코드 :iOS AES 암호화 - 암호화 실패

- (NSData*)AES128Decrypt 
{ 
    char ivPtr[kCCKeySizeAES128 + 1]; 
    bzero(ivPtr, sizeof(ivPtr)); 

    // fetch iv data 
    [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; 


    // 'key' should be 32 bytes for AES256, will be null-padded otherwise 
    char keyPtr[kCCKeySizeAES128 + 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]; // dataLength = 19 

    //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, 0, 
              keyPtr, kCCKeySizeAES128, 
              ivPtr, 
              [self bytes], dataLength, 
              buffer, bufferSize, 
              &numBytesDecrypted); // buffer = 0 & numBytesDecrypted = 0 

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

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

그리고 이것은 내 뷰 클래스에서 호출하고 어떻게 : 나는 "test12" 문자열을 전달하고

- (void) testActuallyEncrypting :(NSString*) hexString { 
    NSLog(@"String to Encrypt : %@", hexString); // prints test12 

    @try { 
    //Convert NSString to NSData 
    NSData *data = [self dataFromHexString:hexString]; // [hexString dataUsingEncoding:NSUTF8StringEncoding]; // 
    // // Prepare the NSDAta obj to store the encrypted pswd 
    NSData *encryptedData = [NSData dataWithBytes:[data bytes] length:[data length]]; // 6bytes 
    NSData *decryptedData = [encryptedData AES128Decrypt]; // 0bytes 
    NSString *decryptedString = [NSString stringWithUTF8String:[decryptedData bytes]]; // NULL Exception 
    NSLog(@"Decrypted String : %@", decryptedString); 

    decryptedString = [self addPaddingToString:decryptedString]; 
    decryptedData = [NSData dataWithBytes:[decryptedString UTF8String] length:[[decryptedString dataUsingEncoding:NSUTF8StringEncoding] length]]; 
    encryptedData = [decryptedData AES128Encrypt]; 
    if (encryptedData!=nil) 
    { 
     NSString *encryptedHexString = [self hexStringFromData:encryptedData]; 
     NSLog(@"Encrypted HexString : %@",encryptedHexString); 

    } 
    }@catch (NSException *ex) { 
     NSLog(@"Exception : %@", ex); 
    } 
} 

암호화 할 수 있습니다. AES128Decrypt을 호출하면 decryptedData이 0이되어 다음 줄 decryptedString이 Null 예외 - Exception : *** +[NSString stringWithUTF8String:]: NULL cString을 던집니다.

누구나 내가 왜 decryptedData가 null인지 알 수 있습니까? AES128Decrypt 메소드에서 어디서 잘못 될까요?

도와주세요. 나는 지난 2 일 동안 이것에 붙어있다. 이것에 인터넷에 많은 것을 찾았지만 그것을 통해 얻을 수있는 해결책을 얻을 수 없습니다. 도움을 주시면 감사하겠습니다. 감사.

업데이트 : - @ Zaph의 수업을 내 수업에 추가하고 전화했습니다.

NSLog(@"String to Encrypt : %@", hexString); 
NSString *iv = @"fedcba"; 
NSString *key = @"abcdef"; 

// Convert str to encrypt, iv & key from NSString to NSData 
NSData *dataIn = [hexString dataUsingEncoding:NSUTF8StringEncoding]; 
NSData *ivData = [iv dataUsingEncoding:NSUTF8StringEncoding]; 
NSData *symKey = [key dataUsingEncoding:NSUTF8StringEncoding]; 
NSError *error; 

NSData *result = [LoginViewController doCipher:dataIn iv:ivData key:symKey context:kCCEncrypt error:&error]; // result = 16bytes 

if (result != nil) { 
    // Convert result to satring 
    NSString *resultStr = [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]; 
    NSLog(@"Encrypted Str = %@", resultStr); // Encrypted Str = (null) ???? 

왜 변환 된 문자열이 null입니까? 제발 도와주세요. 감사합니다

+2

프로그래밍 오류를 잡는 것을 제외하고는'@ try'와'@ catch '를 사용하지 마십시오. Objective-C에서는 ** 컨트롤 구조가 아닙니다 **. – zaph

+0

NSString을 NSString으로 변환하는 것이 NSUTF8StringEncoding을 사용하여 인코딩하면 null이 반환되는 것으로 나타났습니다. NSASCIIStringEncoding 사용하여 시도했다, 값을 반환합니다. 그러나 문자열 값과 데이터 값은 다릅니다. 둘 다 똑같아 야하지? – Tvd

+0

모든 데이터가 UTR-8에도 유효하지는 않습니다. 데이터의 문자열 표현은 Base64 인코딩을 사용하는 것이 일반적입니다. NSString * resultStr = [[NSString alloc] initWithData : 결과 인코딩 : NSUTF8StringEncoding];'Base64 인코딩 사용 : NSString * resultBase64Str = [결과 base64EncodedStringWithOptions : 0];'NSASCIIStringEncoding'을 사용하면 표시 할 수 없게됩니다 캐릭터, 아마도 당신이 원하는 것이 아닙니다. – zaph

답변

3

암호화를 복잡하게 만들 필요가 없습니다. 여기에 기본적인 암호화/해독 방법이 있습니다. iv와 키는 정확한 길이 여야합니다. 값 컨텍스트는 kCCEncrypt 또는 kCCDecrypt입니다.

+ (NSData *)doCipher:(NSData *)dataIn 
        iv:(NSData *)iv 
       key:(NSData *)symmetricKey 
      context:(CCOperation)encryptOrDecrypt 
       error:(NSError **)error 
{ 
    CCCryptorStatus ccStatus = kCCSuccess; 
    size_t   cryptBytes = 0; 
    NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128]; 

    ccStatus = CCCrypt(encryptOrDecrypt, 
         kCCAlgorithmAES128, 
         kCCOptionPKCS7Padding, 
         symmetricKey.bytes, 
         kCCKeySizeAES128, 
         iv.bytes, 
         dataIn.bytes, 
         dataIn.length, 
         dataOut.mutableBytes, 
         dataOut.length, 
         &cryptBytes); 

    if (ccStatus == kCCSuccess) { 
     dataOut.length = cryptBytes; 
    } 
    else { 
     if (error) { 
      *error = [NSError errorWithDomain:@"kEncryptionError" 
             code:ccStatus 
            userInfo:nil]; 
     } 
     dataOut = nil; 
    } 

    return dataOut; 
} 
+0

위의 코드를 보내 주셔서 감사합니다. viewController 클래스에 추가했습니다. iv, key, str을 NSData 형식 (iv 및 16 바이트 키)으로 전달하고 NSData * result = [LoginViewController doCipher : dataIn iv : ivData 키 : symKey 컨텍스트 : kCCEncrypt 오류 : & 오류] 메서드를 호출하십시오. 하지만 NSString null로 변환 할 때 16bytes의 결과를 얻습니다. 위의 코드를 pls 검사 할 수 있습니까? 업데이트 아래에 추가했습니다. 오류도 0이 아니므로 오류가 발생하지 않습니다. 왜 문자열이 null입니까? 찾을 수 있도록 도와 주시겠습니까? – Tvd

+0

결과를 얻으려면 문자열로 변환합니다 (NSASCIIStringEncoding을 통해서만 작동합니다.) 그런 다음 문자열을 nsdata로 다시 변환하려고 시도했습니다. 그 중 3 개에 대해 다른 값을 얻었습니다. 3이 같지 않거나 적어도 둘 다 nsdata가되어서는 안됩니다. . 결과를 해독하고 문자열로 변환하는 것은 의심의 여지가 원래 문자열 전달 된 및 작동하고 있습니다.하지만 지식을 알고 싶습니다 및 동일한 알고 궁금합니다. 감사합니다. – Tvd

+0

코드에서 kCCOptionPKCS7Padding 사용한, 생각합니다. 그것은 PKCS 구현을위한 것입니다 .CBC를 사용해야합니다 .CBC에 대한 특수 설정/매개 변수 값은 무엇입니까? – Tvd