2012-02-19 10 views
1

iPhoneアプリで文字列を暗号化する必要があります。暗号化方式は、3DES/CBC/PKCS5パディングであり、Iは、Objective-CでこのJavaコードに変換する必要がありますiPhoneアプリケーションの3DES暗号化は、Javaの3DES暗号化とは常に異なる結果をもたらします。

:私はそれらの仕様に合わせて、このObjective-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; 

}

私はJavaコードで得られた3DES暗号化と一致するように管理していなかったと私は問題であるかを理解していません。

は 桟橋

+2

彼の答えの知覚ノートに加えて、別のIV(0x00,0x00、Javaでは0x08,0x08、Obj-Cでは...)を使用していますが、私は見ることができませんパスワードでMD5を使用するObj-Cコードのステップ:パスワードのASCIIエンコーディングをキーとして使用するように見えます。 –

+1

問題はキーのMD5にあり、別のIVでは0x00の代わりに0x08を使用しました。おかげで多くの桟橋。 – Pier

+0

@Pierは、上記のJavaコードを達成するために使用した最新の目的のCコードを共有できますか?私はこのJavaコードに悩まされていますか?手伝って頂けますか ?ありがとうございます。 – harikrishnan

答えて

2

JavaバージョンではIVが0、Objective-Cバージョンでは8が使用されています。

MD5の1ラウンドを使用し、パスワードなしで鍵を派生させても安全ではありません。 PBKDF2のようなキー導出アルゴリズムを使用してください。

+0

Ha、それは正しい10Kの上向き日です:)。 3DESの場合、IVは16バイトではなく8バイトでなければなりません。 –

+0

@owlsteadおっと、そうです。あまりにもAESに慣れている。 – erickson

+0

Javaの場合、私はちょうど例を使用します。新しいバイト[myCipher.getBlockSize()]は、より柔軟で、間違いを避けます。しかし、CCCrypt()と同様の機能はありません。 –

1

、事前にありがとう私はすべてのあなたのコードを見ていないが、飛び出す最初の事はあなたの入力文字列の文字符号化方式が異なることです。あなたのJavaアルゴリズムでは、すべての文字列をUTF-8としてエンコードしていますが、ObjCアルゴリズムでは、文字列をASCIIとしてエンコードしました。これは入力文字列の中で最も単純なものの潜在的な問題です。

+0

こんにちは@perception同じJavaコードのこの目的のCコードを手伝ってもらえますか? – harikrishnan

1

文字エンコードに問題があるようです。 Objective-CコードはASCII(8ビット)文字に基づいていますが、Java文字列をバイトに解析する際に、(16ビット)UNICODE文字のデコードを切り替える必要があります。一方、作業中のCPUアーキテクチャー(リトルエンディアンまたはビッグエンディアン)に応じて、配列内のバイトオーダリングを検討することをお勧めします。