2012-02-19 2 views
1

iPhone 앱에서 문자열을 암호화해야합니다. 암호화 방식은 3DES/CBC/PKCS5 패딩 내가 목표 - C이 Java 코드로 변환 할 수 있습니다iPhone 앱의 3DES 암호화는 항상 Java의 3DES 암호화와 다른 결과를냅니다.

: 그 사양에 맞게이 목표-C 방법을 만들어

public class MessageEncrypt { 

public String encryptString(String message, String seckey) throws Exception{ 
    byte[] encData = encrypt(message, seckey); 

    return this.getHexString(encData, ""); 
} 

public String decryptString(String message, String seckey) throws Exception{ 
    return decrypt(this.getBArray(message), seckey); 
} 

private byte[] encrypt(String message, String seckey) throws Exception { 
    final MessageDigest md = MessageDigest.getInstance("md5"); 
    final byte[] digestOfPassword = md.digest(seckey.getBytes("utf-8")); 
    final byte[] keyBytes = acopyof(digestOfPassword, 24); 
    for (int j = 0, k = 16; j < 8;) { 
     keyBytes[k++] = keyBytes[j++]; 
    } 

    final SecretKey key = new SecretKeySpec(keyBytes, "DESede"); 
    final IvParameterSpec iv = new IvParameterSpec(new byte[8]); 
    final Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
    cipher.init(Cipher.ENCRYPT_MODE, key, iv); 

    final byte[] plainTextBytes = message.getBytes("utf-8"); 
    final byte[] cipherText = cipher.doFinal(plainTextBytes); 
    // final String encodedCipherText = new sun.misc.BASE64Encoder() 
    // .encode(cipherText); 

    return cipherText; 
} 

private String decrypt(byte[] message, String seckey) throws Exception { 
    final MessageDigest md = MessageDigest.getInstance("md5"); 
    final byte[] digestOfPassword = md.digest(seckey.getBytes("utf-8")); 
    final byte[] keyBytes = acopyof(digestOfPassword, 24); 
    for (int j = 0, k = 16; j < 8;) { 
     keyBytes[k++] = keyBytes[j++]; 
    } 

    final SecretKey key = new SecretKeySpec(keyBytes, "DESede"); 
    final IvParameterSpec iv = new IvParameterSpec(new byte[8]); 
    final Cipher decipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); 
    decipher.init(Cipher.DECRYPT_MODE, key, iv); 

    final byte[] plainText = decipher.doFinal(message); 

    return new String(plainText, "UTF-8"); 
} 

private String getHexString(byte[] barray, String delim) { 
    StringBuffer buffer = new StringBuffer(); 


    for (int i = 0; i < barray.length; i++) { 
     int ii = barray[i] & 0xFF; 
     String bInt = Integer.toHexString(ii); 
     if (ii < 16) { 
      bInt = "0" + bInt.toUpperCase(); 
     } 
     buffer.append(bInt); 
     if (i < barray.length - 1) { 
      buffer.append(delim); 
     } 
    } 

    return buffer.toString().toUpperCase(); 
} 

private byte[] getBArray(String bString) { 
    byte[] retBytes; 

    if (bString.length() % 2 != 0) { 
     return new byte[0]; 
    } 
    retBytes = new byte[bString.length()/2]; 

    for (int i = 0; i < bString.length()/2; i++) { 
     retBytes[i] = (byte) ((Character.digit(bString.charAt(2 * i), 16) << 4) + Character.digit(bString.charAt(2 * i + 1), 16)); 
    } 
    return retBytes; 
} 

public static byte[] acopyof(byte[] orig, int newlength){ 
    byte[] copya = new byte[newlength]; 
    for(int i=0;i< orig.length;i++){ 
     copya[i]=orig[i]; 
    } 
    for(int i=orig.length;i<newlength;i++){ 
     copya[i]=0x0; 
    } 
    return copya; 
} 

}

+(NSString*)doCipher:(NSString*)sTextIn:(CCOperation)encryptOrDecrypt { 

// const void * vplainText; // size_t plainTextBufferSize;

NSMutableData *dTextIn; 

if (encryptOrDecrypt == kCCDecrypt) 
{ 



} 
else 
{ 

    dTextIn = [[sTextIn dataUsingEncoding: NSASCIIStringEncoding]mutableCopy]; 

} 

NSLog(@"************** Init encrypting **********************************"); 

NSLog(@"This is data to encrypt %@",dTextIn); 

CCCryptorStatus ccStatus; 
uint8_t *bufferPtr = NULL; 
size_t bufferPtrSize = 0; 
size_t movedBytes = 0; 
// uint8_t ivkCCBlockSize3DES; 

bufferPtrSize = ([dTextIn length] + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); 
bufferPtr = malloc(bufferPtrSize * sizeof(uint8_t)); 
memset((void *)bufferPtr, 0x00, bufferPtrSize); 



// Initialization vector; in this case 8 bytes. 

uint8_t iv[kCCBlockSize3DES]; 
memset((void *) iv, 0x8, (size_t) sizeof(iv)); 



UserAndPassword *userPass = [[UserAndPassword alloc]init]; 

NSString *userPassword = userPass.password; 

NSLog(@"This is my password %@",userPassword); 

NSString *key = [userPassword MD5String]; 

NSLog(@"This is MD5 key %@",key); 


NSMutableData *_keyData = [[key dataUsingEncoding:NSASCIIStringEncoding]mutableCopy]; 

unsigned char *bytePtr = (unsigned char *)[_keyData bytes]; 

NSLog(@"Bytes of key are %s ", bytePtr); 

NSLog(@"******** This is my key length %d *******",[_keyData length]); 

[_keyData setLength:24]; 

unsigned char *bytePtr1 = (unsigned char *)[_keyData bytes]; 

NSLog(@"******** Bytes of key are %s ************", bytePtr1); 

NSLog(@"********* This is key length %d ***********",[_keyData length]); 



ccStatus = CCCrypt(encryptOrDecrypt, // CCoperation op 
        kCCAlgorithm3DES, // CCAlgorithm alg 
        kCCOptionPKCS7Padding, // CCOptions 
        [_keyData bytes], // const void *key 
        kCCKeySize3DES, // 3DES key size length 24 bit 
        iv, //const void *iv, 
        [dTextIn bytes], // const void *dataIn 
        [dTextIn length], // size_t dataInLength 
        (void *)bufferPtr, // void *dataOut 
        bufferPtrSize, // size_t dataOutAvailable 
        &movedBytes); // size_t *dataOutMoved 

if (ccStatus == kCCParamError) return @"PARAM ERROR"; 
else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL"; 
else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE"; 
else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT"; 
else if (ccStatus == kCCDecodeError) return @"DECODE ERROR"; 
else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED"; 


NSString *result; 

if (encryptOrDecrypt == kCCDecrypt) 
{ 

    // result = [[NSString alloc] initWithData: [NSData dataWithBytes:(const void *)bufferPtr length:[(NSUInteger)movedBytes] encoding:NSASCIIStringEncoding]]; 
    result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding] autorelease]; 
} 
else 
{ 
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes]; 

    NSLog(@"This is my encrypted bytes %@", myData); 

    result = [NSString dataToHex:myData]; 

    NSLog(@"This is my encrypted string %@", result); 

    NSLog(@"********************** Encryption is finished ************"); 

} 
return result; 

}

내가 자바 코드로 얻은 3DES 암호화를 일치하도록 관리하지 않았고, 내가 문제가있는 이해가 안 돼요.

내가 모든 코드를보고하지 않은

+2

그의 답변에있는 지각 노트 외에도 다른 IV (0x00,0x00, ... Java와 0x08,0x08, ... Obj-C)를 사용하고 있는데 어떤 것도 볼 수 없습니다. 암호로 MD5를 사용하는 Obj-C 코드의 단계 : 암호의 ASCII 인코딩을 키로 사용하는 것처럼 보입니다. –

+1

문제는 키의 MD5에 있었고 다른 IV에서는 0x00 대신 0x08을 사용했습니다. 부두 고마워. – Pier

+0

@Pier는 위의 자바 코드를 달성하는 데 사용했던 최신의 목표 C 코드를 공유 할 수 있습니까? 이 자바 코드에 붙어있어? 나 좀 도와 줄 수있어? 미리 감사드립니다. – harikrishnan

답변

2

Java 버전은 IV가 0이고 Objective-C 버전은 8을 사용합니다.

MD5를 1 라운드 사용하고 소금을 사용하지 않고 암호에서 키를 추출하는 것은 안전하지 않습니다. PBKDF2와 같은 키 유도 알고리즘을 사용하십시오.

+0

하, 맞습니다. 10K 이상입니다. :). 3DES의 경우 IV는 16 바이트가 아니라 8 바이트 여야합니다. –

+0

@owlstead 죄송합니다. AES에도 익숙해 져야합니다. – erickson

+0

자바의 경우 예를 들어 new byte [myCipher.getBlockSize()],보다 유연하고 실수를 방지합니다. CCCrypt()와 비슷한 기능을 볼 수 없습니다. –

1

부두, 사전에 감사합니다,하지만 밖으로 점프 제일 먼저 당신의 입력 문자열에 대한 문자 인코딩 방식이 다르기 때문이다. 자바 알고리즘에서는 모든 문자열을 UTF-8으로 인코딩하지만 ObjC 알고리즘에서는 문자열을 ASCII으로 인코딩했습니다. 이것은 입력 문자열 중 가장 단순하지만 잠재적 인 문제입니다.

+0

안녕하십니까? @parception 동일한 자바 코드에 대한 객관적인 C 코드를 도와 주실 수 있습니까? – harikrishnan

1

문자 인코딩 문제가있는 것 같습니다. Objective-C 코드는 ASCII (8 비트) 문자를 기반으로하지만 Java 문자열을 바이트로 구문 분석하는 동안 (16 비트) UNICODE 문자 디코딩을 전환해야합니다. 반면에 작업중인 CPU 아키텍처 (Little 또는 Big Endianness)에 따라 배열에서 바이트 순서를 고려하는 것이 좋습니다.