3DES result in Java produces different result from

2019-02-16 03:09发布

问题:

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

回答1:

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.



回答2:

Error found. keydata encoding was different