iPhone应用程序中的3DES加密总是产生与Java中的3DES加密不同的结果

iPhone应用程序中的3DES加密总是产生与Java中的3DES加密不同的结果,java,iphone,objective-c,encryption,3des,Java,Iphone,Objective C,Encryption,3des,我必须在我的iPhone应用程序中加密一个字符串。加密方案是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.get

我必须在我的iPhone应用程序中加密一个字符串。加密方案是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;
}
//const void*vplainText; //大小\u t明文缓冲大小

NSMutableData *dTextIn;

if (encryptOrDecrypt == kCCDecrypt)
{



}
else
{

    dTextIn = [[sTextIn dataUsingEncoding: NSASCIIStringEncoding]mutableCopy];

}

NSLog(@"************** Init encrypting **********************************");

NSLog(@"This is data to encrypt %@",dTextIn);

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



// Initialization vector; in this case 8 bytes.

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



UserAndPassword *userPass = [[UserAndPassword alloc]init];

NSString *userPassword = userPass.password;

NSLog(@"This is my password %@",userPassword);

NSString *key = [userPassword MD5String];

NSLog(@"This is MD5 key %@",key);


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

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

NSLog(@"Bytes of key are %s ", bytePtr);

NSLog(@"******** This is my key length %d *******",[_keyData length]);

[_keyData setLength:24];

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

 NSLog(@"******** Bytes of key are %s ************", bytePtr1);

 NSLog(@"*********  This is key length %d ***********",[_keyData length]);



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:NSASCIIStringEncoding]];
    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];

    NSLog(@"This is my encrypted bytes %@", myData);

    result = [NSString dataToHex:myData];

    NSLog(@"This is my encrypted string %@", result);

    NSLog(@"********************** Encryption is finished ************");

}
return result;
}

我没有设法匹配用Java代码获得的3DES加密,我不知道问题出在哪里

提前谢谢大家,,
Pier

我还没有看完您的所有代码,但首先跳出来的是输入字符串的字符编码方案不同。在Java算法中,您将所有字符串编码为
UTF-8
,但在ObjC算法中,您将字符串编码为
ASCII
,这对于除最简单的输入字符串以外的任何东西都是一个潜在问题。

我还没有看完您的所有代码,但是第一件跳出的事情是,输入字符串的字符编码方案是不同的。在Java算法中,您将所有字符串编码为
UTF-8
,但在ObjC算法中,您将字符串编码为
ASCII
,这对于除最简单的输入字符串以外的任何东西都是一个潜在问题。

看起来您有字符编码问题。Objective-C代码基于ASCII(8位)字符,但在将Java字符串解析为字节时,需要切换(16位)UNICODE字符解码。另一方面,在你的数组中考虑字节顺序取决于你正在处理的CPU架构(小的或大的字节数)可能是个好主意。

< P>看起来你有一个字符编码问题。Objective-C代码基于ASCII(8位)字符,但在将Java字符串解析为字节时,需要切换(16位)UNICODE字符解码。另一方面,根据您正在处理的CPU架构(很少或大的子集)考虑数组中的字节排序可能是个好主意。

< P> java版本使用的是IV的0,而Objto-C版本使用8S.<
使用一轮MD5和NOSALT从密码派生密钥是不安全的。使用像PBKDF2这样的密钥派生算法。

Java版本使用0的IV,而Objective-C版本使用8


使用一轮MD5和NOSALT从密码派生密钥是不安全的。使用像PBKDF2这样的密钥派生算法。

除了他的答案中的问题注释外,您还使用了不同的IV(Java中的0x00,0x00,…与Obj-C中的0x08,0x08,…)在Obj-C代码中,我看不到在密码上使用MD5的任何步骤:看起来您只是使用密码的ASCII编码作为密钥。问题在于密钥的MD5,在不同的IV中,我使用了0x08而不是0x00。非常感谢。@Pier你能分享你用来实现上述java代码的最新objective c代码吗?我被这个java代码卡住了?你能帮助我吗?提前感谢除了他回答中的问题感知注释外,您还使用了不同的IV(Java中的0x00,0x00,…与Obj-C中的0x08,0x08,…)在Obj-C代码中,我看不到在密码上使用MD5的任何步骤:看起来您只是使用密码的ASCII编码作为密钥。问题在于密钥的MD5,在不同的IV中,我使用了0x08而不是0x00。非常感谢。@Pier你能分享你用来实现上述java代码的最新objective c代码吗?我被这个java代码卡住了?你能帮助我吗?提前感谢哈,这是正确的10公里以上的一天:)。对于3DES,IV应该是8个字节,而不是16个字节。对于Java,我只使用新字节[myCipher.getBlockSize()],更灵活,避免错误。但是,在Java中,我通常让提供程序设置IV,然后在初始化
密码后查询参数。哈,这是正确的(每天10公里以上:)。对于3DES,IV应该是8个字节,而不是16个字节。对于Java,我只使用新字节[myCipher.getBlockSize()],更灵活,避免错误。在Java中,我通常让提供程序设置IV,然后在初始化
密码后查询参数。hi@perception你能帮我找出相同Java代码的目标c代码吗?hi@perception你能帮我找出相同Java代码的目标c代码吗?
NSMutableData *dTextIn;

if (encryptOrDecrypt == kCCDecrypt)
{



}
else
{

    dTextIn = [[sTextIn dataUsingEncoding: NSASCIIStringEncoding]mutableCopy];

}

NSLog(@"************** Init encrypting **********************************");

NSLog(@"This is data to encrypt %@",dTextIn);

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



// Initialization vector; in this case 8 bytes.

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



UserAndPassword *userPass = [[UserAndPassword alloc]init];

NSString *userPassword = userPass.password;

NSLog(@"This is my password %@",userPassword);

NSString *key = [userPassword MD5String];

NSLog(@"This is MD5 key %@",key);


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

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

NSLog(@"Bytes of key are %s ", bytePtr);

NSLog(@"******** This is my key length %d *******",[_keyData length]);

[_keyData setLength:24];

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

 NSLog(@"******** Bytes of key are %s ************", bytePtr1);

 NSLog(@"*********  This is key length %d ***********",[_keyData length]);



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:NSASCIIStringEncoding]];
    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];

    NSLog(@"This is my encrypted bytes %@", myData);

    result = [NSString dataToHex:myData];

    NSLog(@"This is my encrypted string %@", result);

    NSLog(@"********************** Encryption is finished ************");

}
return result;