【问题标题】:3DES encryption in Java and Objective C produces different resultJava和Objective C中的3DES加密产生不同的结果
【发布时间】:2013-09-16 06:30:46
【问题描述】:

我必须在 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;
}

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

【问题讨论】:

    标签: java objective-c encryption 3des


    【解决方案1】:

    我做到了。解决方案:

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

    【讨论】:

    • 您好 可以提供MD5功能吗?因为我的 MD5 不能正常工作。
    • 嗨@kokx,我也遇到了这个问题,所以试试这个代码:+ (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]; }
    • @kokx,请参阅我的答案以获得完整的解决方案。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-09
      • 2012-03-10
      • 1970-01-01
      • 2021-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多