iOS对称密钥加密/解密相当于Java

iOS对称密钥加密/解密相当于Java,java,objective-c,security,cryptography,Java,Objective C,Security,Cryptography,我正在尝试将ios中的数据加密/解密到java和java到ios,但我发现在java中加密的数据在ios中没有正确解密,在ios中加密的数据在java中没有正确解密 - (NSData *) encrypt:(NSData *) dataToEncrypt symmetricKey:(NSData *)symmetricKey context:(CCOperation)encryptOrDecrypt{ NSUInteger data_length= [dataToEncrypt len

我正在尝试将ios中的数据加密/解密到java和java到ios,但我发现在java中加密的数据在ios中没有正确解密,在ios中加密的数据在java中没有正确解密

- (NSData *) encrypt:(NSData *) dataToEncrypt symmetricKey:(NSData *)symmetricKey context:(CCOperation)encryptOrDecrypt{
    NSUInteger data_length= [dataToEncrypt length];
    uint8_t input_raw_data[data_length];

    //The [dataToEncrypt length] gives the number of chars present in the string.So say there are 10 chars.
    //Now,the getBytes needs to get the raw bytes from this i.e. binary NSData.But suppose the encoding was
    //full 16 bit encoding then the number of bytes needed wd have been double- 20.But as we are using the
    //NSUTF8StringEncoding,the number of byes needed is 1 per char as the chars(even if originally unicode are
    //compressed into an 8 bit UTF8 encoding.)

    [dataToEncrypt getBytes:&input_raw_data length:data_length];

//    [dataToEncrypt getBytes:&input_raw_data maxLength:data_length usedLength:NULL encoding:NSUTF8StringEncoding options:0 range:NSMakeRange(0,data_length) remainingRange:NULL];

    //According to the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t buffer_size           = data_length + kCCBlockSizeAES128;
    void* buffer                 = malloc(buffer_size);
    size_t num_bytes_encrypted   = 0;


    CCCryptorStatus crypt_status = CCCrypt(encryptOrDecrypt, kCCAlgorithmAES128, 0x0000,
                                           [symmetricKey bytes], kCCKeySizeAES128,
                                           NULL,
                                           input_raw_data, data_length,
                                           buffer, buffer_size,
                                           &num_bytes_encrypted);

//    NSLog(@"~~num bytes encrypted: %d",num_bytes_encrypted);
    if (crypt_status == kCCSuccess){
        NSLog(@"~~Data encoded successfully...");
        return [NSData dataWithBytesNoCopy:buffer length:num_bytes_encrypted];
    }

    free(buffer); //free the buffer;
    return nil;

}

Java代码-

 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
 String keyString = "keykeykeykeykeykeykeykey";
 byte[] keyBytes = keyString.getBytes("UTF-8"); 
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keyBytes, "AES"), new IvParameterSpec(new byte[16])); 
byte[] resultBytes = cipher.doFinal("Hallo Welt!".getBytes("UTF8")); 
FileOutputStream out = new FileOutputStream(new File("encryptedFileJava")); 
out.write(resultBytes); out.close();
这是加密文本——“SeáJb|8”R

键-BW3DKDF2BKD4BQ9XTDR1G==

请帮助我或建议任何解决方案


谢谢。

您至少有两个问题:

  • 目标C代码使用ECB模式,而Java代码使用CBC模式。在CCrypt调用中使用一个由零组成的字节数组,而不是NULL,以使用CBC模式和zero IV,就像Java代码一样

  • 由于keyBytes是24字节长,Java将使用AES-192。CCrypt将忽略额外的字节。将AES-192指定为CCrypt或使用128位密钥(“keyk”应该可以工作)


  • 您至少有两个问题:

  • 目标C代码使用ECB模式,而Java代码使用CBC模式。在CCrypt调用中使用一个由零组成的字节数组,而不是NULL,以使用CBC模式和zero IV,就像Java代码一样

  • 由于keyBytes是24字节长,Java将使用AES-192。CCrypt将忽略额外的字节。将AES-192指定为CCrypt或使用128位密钥(“keyk”应该可以工作)


  • 对于IOS和Java设备之间的安全通信,可以使用对称密钥加密

    在平台不同的情况下,建议生成的密钥为纯文本密钥,而不是API生成的密钥

    在这种情况下,可以使用AES 128位加密。IOS设备能够生成对称密钥并使用AES加密对文本进行加密

    下面的链接提供了使用纯文本对称密钥加密和解密的java代码


    对于IOS和Java设备之间的安全通信,可以使用对称密钥加密

    在平台不同的情况下,建议生成的密钥为纯文本密钥,而不是API生成的密钥

    在这种情况下,可以使用AES 128位加密。IOS设备能够生成对称密钥并使用AES加密对文本进行加密

    下面的链接提供了使用纯文本对称密钥加密和解密的java代码


    您正在ECB模式下使用AES。那是故意的吗?请向我们展示您试图用来解密它的Java代码。向我们展示输入数据+密钥+加密数据+解密数据的示例也有助于我们调试您的问题。@RasmusFaber hi这是java Cipher Cipher=Cipher.getInstance(“AES/CBC/NoPadding”)的示例代码;字符串keyString=“keykey”;byte[]keyBytes=keyString.getBytes(“UTF-8”);init(cipher.ENCRYPT_模式,新的SecretKeySpec(keyBytes,“AES”),新的IvParameterSpec(新字节[16]);byte[]resultBytes=cipher.doFinal(“你好!”.getBytes(“UTF8”);FileOutputStream out=新的FileOutputStream(新文件(“encryptedFileJava”);out.write(结果字节);out.close();这是加密文本——“SeáJb|8”R,key-BW3dKDf2bkDC4Bq9xTdr1g==您在ECB模式下使用AES的可能副本。那是故意的吗?请向我们展示您试图用来解密它的Java代码。向我们展示输入数据+密钥+加密数据+解密数据的示例也有助于我们调试您的问题。@RasmusFaber hi这是java Cipher Cipher=Cipher.getInstance(“AES/CBC/NoPadding”)的示例代码;字符串keyString=“keykey”;byte[]keyBytes=keyString.getBytes(“UTF-8”);init(cipher.ENCRYPT_模式,新的SecretKeySpec(keyBytes,“AES”),新的IvParameterSpec(新字节[16]);byte[]resultBytes=cipher.doFinal(“你好!”.getBytes(“UTF8”);FileOutputStream out=新的FileOutputStream(新文件(“encryptedFileJava”);out.write(结果字节);out.close();这是加密文本——“SeáJb|8”R,key-BW3dKDf2bkDC4Bq9xTdr1g==为iv指定NULL的CBC模式的可能副本将使用0x00数组。在Apple标题中:“如果选择了CBC模式(由于选项标志中没有任何模式位),并且不存在IV,则将使用NULL(全零)IV。”考虑纠正错误。对于IV指定的空的CBC模式将使用0x00的数组。从苹果报头:“如果选择CBC模式(在选项标志中没有任何模式位)并且没有IV,则将使用NULL(全零)IV。”考虑纠正答案。