Java和Objective C中的3DES加密产生不同的结果

时间:2013-09-12 03:02:45

标签: java objective-c encryption 3des

我必须加密Objective C中的字符串。加密方案是3DES / CBC / PKCS5填充,我必须在Objective C中转换这个Java代码:

        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;
            }
  }

目标C代码:

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

    NSMutableData *dTextIn;

    if (encryptOrDecrypt == kCCDecrypt)
    {
        //TODO
    }
    else
    {
        dTextIn = [[sTextIn dataUsingEncoding: NSUTF8StringEncoding]mutableCopy];
    }

    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, 0x0, bufferPtrSize);

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

    NSString *key = [@"MY_KEY_HERE" MD5];

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

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

    [_keyData setLength:24];

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

    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:NSUTF8StringEncoding] autorelease];
    }
    else
    {
        NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        result = [NSString dataToHex:myData];
    }
    return result;
}

不明白为什么我会得到不同的结果。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我做到了。解决方案:

Java代码:

public class MessageEncrypt {

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

            return Base64.encodeToString(encData, Base64.DEFAULT);
        }

        public String decryptString(String message, String seckey) throws Exception{
            byte[] encData= Base64.decode(message, Base64.DEFAULT);

            return decrypt(encData, 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);

            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");
        }

        public 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;
        }
    }

目标C代码:

+(NSString*)doCipher:(NSString*)message key:(NSString*)key operation:(CCOperation)encryptOrDecrypt {

    const void *messageData;
    size_t messageBufferSize;

    if (encryptOrDecrypt == kCCDecrypt){
        NSData *messageEncryptData= [NSData dataFromBase64String:message];
        messageBufferSize= [messageEncryptData length];
        messageData= [messageEncryptData bytes];
    }
    else{
        messageBufferSize= message.length;
        messageData = [[[message dataUsingEncoding: NSUTF8StringEncoding]mutableCopy] bytes];
    }

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

    bufferPtrSize = (messageBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);

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

    NSMutableData *keyData = [[key dataUsingEncoding:NSUTF8StringEncoding]mutableCopy];
    NSData *keyEncodedMD5 = [NSData MD5Digest:keyData];

    NSMutableData *keyDataAux = [NSMutableData dataWithData:keyEncodedMD5];
    NSRange rangeToModify = NSMakeRange([keyEncodedMD5 length], kCCKeySize3DES - [keyEncodedMD5 length]);
    [keyDataAux setLength: kCCKeySize3DES];
    [keyDataAux replaceBytesInRange:rangeToModify withBytes:[keyEncodedMD5 bytes]];

    ccStatus = CCCrypt(encryptOrDecrypt, // CCoperation op
                       kCCAlgorithm3DES, // CCAlgorithm alg
                       kCCOptionPKCS7Padding, // CCOptions
                       [keyDataAux bytes], // const void *key
                       kCCKeySize3DES, // 3DES key size length 24 bytes
                       iv,  //const void *iv,
                       messageData, // const void *dataIn
                       messageBufferSize, // 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:NSUTF8StringEncoding] ;
    }
    else{
        NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        result= [myData base64EncodedString];
    }

    return result;
}

答案 1 :(得分:0)

Objective-C代码:

 + (NSString*) doCipher:(NSString*)plainText operation:(CCOperation)encryptOrDecrypt
 {

     const void *vplainText;
     size_t plainTextBufferSize;

     if (encryptOrDecrypt == kCCDecrypt)
     {
         NSData *EncryptData = [[NSData alloc] initWithBase64EncodedString:plainText];
         plainTextBufferSize = [EncryptData length];
         vplainText = [EncryptData bytes];
     }
     else
     {
         plainTextBufferSize = [plainText length];
         vplainText = (const void *) [plainText UTF8String];
     }

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


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

     bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
     bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
     memset((void *)bufferPtr, 0x0, bufferPtrSize);


     NSData *testData = [self md5DataFromString:SECRET_KEY];
     const char *constSource = [testData bytes];

     unsigned char source[24];
     memcpy(source, constSource, sizeof (source));

     for (int j = 0, k = 16; j < 8;) {
         source[k++] = source[j++];
     }

     ccStatus = CCCrypt(encryptOrDecrypt,
                   kCCAlgorithm3DES,
                   kCCOptionPKCS7Padding,
                   source,
                   kCCKeySize3DES,
                   iv,
                   vplainText,
                   plainTextBufferSize,
                   (void *)bufferPtr,
                   bufferPtrSize,
                   &movedBytes);
     if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
     else 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:NSUTF8StringEncoding];
     }
     else
     {
         NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
         result = [myData base64Encoding];
     }
     return result;
 }

 + (NSData *)md5DataFromString:(NSString *)input
 {
     const char *cStr = [input UTF8String];
     unsigned char digest[16];
     CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call

     return [NSData dataWithBytes:digest length:CC_MD5_DIGEST_LENGTH];
 }