0

I really really.... really need help...........

-UPDATED-

I need help because my java function gives me a different result compared with the iOS 3DES function. I posted the code from both ios and java; and results when specified plaintext is "tutor.1" and MD5 key is "spO13+QLZCRAe93pIXMXLg==" (MD5, clearly, is the same for both).

JAVA 3DES (short and simple)

public static String encrypt(String plaintext, String enctoken){

    if(enctoken == null)
        enctoken = "sfdjf48mdfdf3054";

    String encrypted = null; 

    byte[] plaintextByte = EncodingUtils.getBytes(plaintext,"UTF-8");

    byte[] hash = Connessione.md5(enctoken);

    Log.i("ENCRYPT", "MD5: "+Base64.encodeToString(hash, 0));

    try {
        Cipher cipher = Cipher.getInstance("DESEDE/ECB/PKCS5Padding");
        SecretKeySpec myKey = new SecretKeySpec(hash,"DESede");

        cipher.init(Cipher.ENCRYPT_MODE, myKey); 

        try {
            byte[] encryptedPlainText = cipher.doFinal(plaintextByte);

            encrypted = Base64.encodeToString(encryptedPlainText, 0);

            Log.i("ENCRYPT", "Pwd encrypted: "+encrypted);

            return encrypted;

        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchPaddingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }       

    return "";
}

result: R4mXAaHcFxM=

IOS 3DES - UPDATED AGAIN

// key value in parameters is MD5 value! It is the same for both version

+ (NSString *) encrypt:(NSString *) dataToEncrypt withKey:(NSString*) key{    


NSData *data = [dataToEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSData *mData = [key dataUsingEncoding:NSUTF8StringEncoding];

CCCryptorStatus ccStatus = kCCSuccess;


// Begin to calculate bytesNeeded....
size_t bytesNeeded = 0;

ccStatus = CCCrypt(kCCEncrypt,
                   kCCAlgorithm3DES,
                   kCCOptionECBMode | kCCOptionPKCS7Padding,
                   [mData bytes],
                   [mData length],
                   nil,
                   [data bytes],
                   [data length],
                   NULL,
                   0,
                   &bytesNeeded);

if(kCCBufferTooSmall != ccStatus){

    NSLog(@"Here it must return BUFFER TOO SMALL !!");
    return nil;
}

// .....End
// Now i do the real Crypting

char* cypherBytes = malloc(bytesNeeded);
size_t bufferLength = bytesNeeded;

if(NULL == cypherBytes)
    NSLog(@"cypherBytes NULL");

ccStatus = CCCrypt(kCCEncrypt,
                   kCCAlgorithm3DES,
                   kCCOptionECBMode | kCCOptionPKCS7Padding,
                   [mData bytes],
                   [mData length],
                   nil,
                   [data bytes],
                   [data length],
                   cypherBytes,
                   bufferLength,
                   &bytesNeeded);

if(kCCSuccess != ccStatus){
    NSLog(@"kCCSuccess NO!");
    return nil;
}

return [Base64 encode:[NSData dataWithBytes:cypherBytes length:bufferLength]]; 

}

result: YBAva5J2khY=

I need iOS version returns same result as the Java version.

I found the Base64 class here: http://www.imthi.com/blog/programming/iphone-sdk-base64-encode-decode.php

What i'm doing wrong ?

Thx for your help and time

kinghomer
  • 3,021
  • 2
  • 33
  • 56
  • 1
    You have java algorithm in [ECB](http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation) mode. Can you check whether IOS also has same. – Amit Deshpande Sep 26 '12 at 18:20
  • Any way 3DES is not that safe. You can opt for AES – Amit Deshpande Sep 26 '12 at 18:21
  • 2
    So one time you use a MD5 on the key, the second time you don't, first you encrypt a 7 character string and get 5 full blocks, and the second time one block? Have you even looked at the program? – Maarten Bodewes Sep 26 '12 at 19:14
  • @AmidD that would not matter for the first 8 bytes, since the IV is set to all zero's. The question is how you can encrypt 7 bytes plain text and get 5 full blocks in return. I don't think you can, so the plain text must be different. – Maarten Bodewes Sep 26 '12 at 19:27
  • 1
    IOS 3DES code is not mine. I'm trying to adapt that code for my purpose, and i don't understand well all steps, so it's normal that i'm asking for an help. Your expert eyes can see things that my novice eyes can't. That's all. If you can say me what lines of code is wrong and how to fix it, i appreciate very much. I tried to add kCCOptionECBMode too, but clearly i have to fix something else before that – kinghomer Sep 26 '12 at 19:51
  • @AmitD DES has been analysed for longer than any other encryption system and no significant weaknesses have ever been found (given the inadequate key size). 3DES is as secure as you can get. Prefer AES because it's fast; prefer 3DES if you don't care about speed and are paranoid about security. – Alan Stokes Sep 26 '12 at 20:08
  • I can't choose something different for encryption. Web services are not mine and authentication is implemented in this way, so i can just implement same thing – kinghomer Sep 27 '12 at 08:44
  • I've just updated code, deleting IV cause i red somewhere it's useless in ECB mode and adding kCCOptionsECBMode in CCrypt function – kinghomer Sep 27 '12 at 10:19
  • @owlstead In the iOS function MD5 is specified in parameters. I add a comment line at the begin of code specifying that, and please don't leave useless comment. If you wanna help me then help me. If don't, don't post. Thx – kinghomer Sep 27 '12 at 11:17
  • Did you check that the result wasn't changed when you switched to ECB mode? – Clive Evans Oct 03 '12 at 13:50
  • I think first problem is length. So, first of all i have to understand why java response gives a string with length 56 (which is 3des length) and ios Not! – kinghomer Oct 03 '12 at 20:41
  • I solved size problem, but result is always different. I'm bumping my head into the wall.... -.-. Check update ios code – kinghomer Oct 16 '12 at 17:27
  • I'm still looking for a solution... – kinghomer Oct 29 '12 at 23:36
  • I can't find solution for 3DES. Btw, I switched to AES and result string is the same. Simply specifying AES in place of 3DES. Nothing else – kinghomer Nov 05 '12 at 15:22

2 Answers2

0

Ok, I started off easier, using DES encryption. Also, I'm skipping the Base64 and the hashing on the key - all of these are easily added once you're sure that the encryption is working properly, and they can be added one at a time.

Here's the iOS code:

#import <UIKit/UIKit.h>
#import <CommonCrypto/CommonCrypto.h>
#import <CommonCrypto/CommonCryptor.h>

int main(int argc, char *argv[])
{
    @autoreleasepool {


            BOOL encryptOrDecrypt = kCCEncrypt;
            NSString *plainText = @"abcdefghijklmnop";
            NSString *key = @"01234567";

            const void *vplainText;
            size_t plainTextBufferSize;

            NSData *tempData = [plainText dataUsingEncoding:NSASCIIStringEncoding];
            plainTextBufferSize = [tempData length];
            vplainText =  [tempData bytes];

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

            bufferPtrSize = [plainText length];
            if (bufferPtrSize % 8) {
                bufferPtrSize += 8 - (bufferPtrSize % 8);
            }

//            bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
            bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t) + 1);   // To null-terminate a string if req'd
            memset((void *)bufferPtr, 0x0, bufferPtrSize+1);

            NSData *_keyData = [key dataUsingEncoding:NSASCIIStringEncoding];

            NSLog(@"key byte is %s", [_keyData bytes]);

            // Initialization vector; dummy in this case 0's.
            // uint8_t iv[kCCBlockSize3DES];
            // memset((void *) iv, 0x0, (size_t) sizeof(iv));

            ccStatus = CCCrypt(encryptOrDecrypt,
                                   kCCAlgorithmDES,
                                   kCCOptionECBMode, //kCCOptionPKCS7Padding | kCCOptionECBMode,
                                   (const void *)[_keyData bytes], //key
                                   kCCKeySizeDES,
                                   nil,  //iv,
                                   vplainText,  //plainText,
                                   plainTextBufferSize,
                                   (void *)bufferPtr,
                                   bufferPtrSize,
                                   &movedBytes);

            //if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
            /*else*/
            switch (ccStatus) {
                case kCCParamError:
                    NSLog(@"PARAM ERROR");
                    break;
                case kCCBufferTooSmall:
                    NSLog(@"BUFFER TOO SMALL");
                    break;
                case kCCMemoryFailure:
                    NSLog(@"MEMORY FAILURE");
                    break;
                case kCCAlignmentError:
                    NSLog(@"ALIGNMENT ERROR");
                    break;
                case kCCDecodeError:
                    NSLog(@"DECODE ERROR");
                    break;
                case kCCUnimplemented:
                    NSLog(@"UNIMPLEMENTED");
                    break;
                default:
                    NSLog(@"encrypt seems to have worked");
                    break;
            }

            for (size_t i=0; i<movedBytes; i++) {
                printf("%02x ", (int) bufferPtr[i]);
            }
            printf("\n");

        return UIApplicationMain(argc, argv, nil, NSStringFromClass([FAAppDelegate class]));
    }
}

And here's the Java code:

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;


public class DesRun {
    /**
     * @param args
     */
    public static void main(String[] args) {
        String theKey = "01234567";
        String message = "abcdefghijklmnop";
        Cipher ecipher, dcipher;
         try {
            // generate secret key using DES algorithm
             SecretKeySpec key = new SecretKeySpec(theKey.getBytes("UTF-8"), "DES");

                 ecipher = Cipher.getInstance("DES");
                 dcipher = Cipher.getInstance("DES");

                 // initialize the ciphers with the given key
                 ecipher.init(Cipher.ENCRYPT_MODE, key);
                 dcipher.init(Cipher.DECRYPT_MODE, key);

                 byte[] encrypted = ecipher.doFinal(message.getBytes("UTF-8"));
                 System.out.println(DatatypeConverter.printHexBinary(encrypted));
                 String decrypted = new String(dcipher.doFinal(encrypted), "UTF-8");

                 System.out.println("Decrypted: " + decrypted);

             }
             catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

    }
}

Both print out the hex bytes of the encrypted data, and they agree.

Now it should be (relatively) easy to move to 3DES.

Only once you've got 3DES agreeing on both iOS and Java would I start to add hashing on the keys.

craigmj
  • 4,827
  • 2
  • 18
  • 22
  • Unfortunally, encrypt length is always too short. I expect my method returns an encrypted string with length = 56, not 12. Maybe is not possible by this Cypher library ? – kinghomer Oct 15 '12 at 15:03
  • I solved size result problem (switch from NSUTF8StringEncoding to NSUTF32StringEncoding). I tried your solution specifying 3des, but results are different unfortunally.... – kinghomer Oct 16 '12 at 17:25
0

Error found. keydata encoding was different

kinghomer
  • 3,021
  • 2
  • 33
  • 56