【问题标题】:3DES result in Java produces different result from 3DES iOS versionJava 中的 3DES 结果产生与 3DES iOS 版本不同的结果
【发布时间】:2012-09-26 18:15:54
【问题描述】:

我真的真的……真的需要帮助…………

-已更新-

我需要帮助,因为与 iOS 3DES 函数相比,我的 java 函数给出了不同的结果。我发布了来自 ios 和 java 的代码;当指定明文为“tutor.1”且 MD5 密钥为“spO13+QLZCRAe93pIXMXLg==”(显然,MD5 对两者相同)时的结果。

JAVA 3DES(简短)

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

结果:R4mXAaHcFxM=

IOS 3DES - 再次更新

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

}

结果:YBAva5J2khY=

我需要 iOS 版本返回与 Java 版本相同的结果。

我在这里找到了 Base64 类:http://www.imthi.com/blog/programming/iphone-sdk-base64-encode-decode.php

我做错了什么?

感谢您的帮助和时间

【问题讨论】:

  • 你有ECB模式下的java算法。你能检查一下IOS是否也有吗?
  • 任何方式 3DES 都不是那么安全。您可以选择 AES
  • 所以一次你在密钥上使用MD5,第二次你不用,第一次你加密一个7个字符的字符串得到5个完整的块,第二次一个块?你看过节目吗?
  • @AmidD 对于前 8 个字节无关紧要,因为 IV 设置为全零。问题是如何加密 7 个字节的纯文本并获得 5 个完整的块作为回报。我不认为你可以,所以纯文本必须不同。
  • IOS 3DES 代码不是我的。我正在尝试根据我的目的调整该代码,但我不太了解所有步骤,所以我寻求帮助是正常的。你的专家眼可以看到我的新手眼看不到的东西。就这样。如果您能告诉我哪些代码行错误以及如何修复它,我非常感谢。我也尝试添加 kCCOptionECBMode,但显然我必须在此之前修复其他问题

标签: java ios algorithm encryption 3des


【解决方案1】:

好的,我开始更容易了,使用 DES 加密。此外,我将跳过 Base64 和密钥上的散列 - 一旦您确定加密工作正常,所有这些都可以轻松添加,并且可以一次添加一个。

这是 iOS 代码:

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

这是 Java 代码:

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

    }
}

两者都打印出加密数据的十六进制字节,并且他们同意。

现在应该(相对)容易迁移到 3DES。

只有当 3DES 在 iOS 和 Java 上达成一致后,我才会开始在密钥上添加散列。

【讨论】:

  • 不幸的是,加密长度总是太短。我希望我的方法返回一个长度为 56,而不是 12 的加密字符串。也许这个 Cypher 库不可能?
  • 我解决了大小结果问题(从 NSUTF8StringEncoding 切换到 NSUTF32StringEncoding)。我尝试了指定 3des 的解决方案,但不幸的是结果不同....
【解决方案2】:

发现错误。 keydata 编码不同

【讨论】:

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