关于DES加密,密钥和待加密串相同,在android版本和IOS版本得到不同的密文,怎么破?

andywster 发布于 2014/02/13 21:47
阅读 3K+
收藏 3

背景:业务要跟后台系统交互,对信息加密,APP有IOS和android两版本,所以算法必须一致。在用同样的密钥和加密内容进行加密后,得出的密文不同。 我找了些资料,也有很多人遇到。 导致密文不同结果的原因是填充算法不一致。IOS 用的是DES PKCS7Padding 而这种填充方式Android不支持。在豆瓣上看到有人建议采用下面几种方式:

1.都用NoPadding,太痛苦,放弃
2.java下载扩展包,让java支持PKCS7Padding,可以考虑,但要服务器加java的扩展包
3.别使用AES算法了,使用DES或3DES等,因为它们的加密数据包单位长度是8字节,在8字节的情况下PKCS7Padding 等价与 PKCS5Padding。

我选择了3.  可还是结果不一样,请懂的帮忙看看,android版本代码如下:

private static byte[] iv = {1,2,3,4,5,6,7,8};

public static String enCrypto(String txt, String key)  
            throws  Exception{  
        StringBuffer sb = new StringBuffer();  
        DESKeySpec desKeySpec = new DESKeySpec(key.getBytes());  
        SecretKeyFactory skeyFactory = null;  
        Cipher cipher = null;  
        try {  
            skeyFactory = SecretKeyFactory.getInstance("DES");  
            cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        }  
        IvParameterSpec zeroIv = new IvParameterSpec(iv); 
        SecretKey deskey = skeyFactory.generateSecret(desKeySpec);  
        cipher.init(Cipher.ENCRYPT_MODE, deskey,zeroIv);  
        byte[] cipherText = cipher.doFinal(txt.getBytes());  
        
        return Base64.encode(cipherText);
其中Base64的编码算法我单独测试过,和IOS对字符串的编码一致的。

IOS的代码:

 + (NSString *)encrypt:(NSString *)sText key:(NSString *)key
{
    NSData* encryptData = [sText dataUsingEncoding:NSUTF8StringEncoding];
    const void *dataIn = (const void *)[encryptData bytes];
    size_t dataInLength = [encryptData length];
    
    /*
     DES加密 :用CCCrypt函数加密一下,然后用base64编码
     */
    
    size_t dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
    uint8_t *dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
    size_t dataOutMoved = 0;
    
    memset((void *)dataOut, 0x0, dataOutAvailable);//将已开辟内存空间buffer的首 1 个字节的值设为值 0
    
    NSString *initIv = @"12345678";
    const void *vkey = (const void *) [key UTF8String];
    const void *iv = (const void *) [initIv UTF8String];
    
    //CCCrypt函数 加密
    CCCrypt(kCCEncrypt,//  加密
            kCCAlgorithmDES,//  加密根据哪个标准(des,3des,aes。。。。)
            kCCOptionPKCS7Padding,//  选项分组密码算法(des:对每块分组加一次密  3DES:对每块分组加三个不同的密)
            vkey,  //密钥
            kCCKeySizeDES,//   DES 密钥的大小(kCCKeySizeDES=8)
            iv, //  可选的初始矢量
            dataIn, // 数据的存储单元
            dataInLength,// 数据的大小
            (void *)dataOut,// 用于返回数据
            dataOutAvailable,
            &dataOutMoved);
    
    //编码 base64
    NSData *data = [NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved];
    NSString *result = [GTMBase64 stringByEncodingData:data];
    
    return result;


加载中
0
北京d路飞
北京d路飞
找这个算法的C代码实现,Android通过JNI用跟iOS一样的 C代码算法。
0
捉鬼大帝
捉鬼大帝
同意lS,用c写加密算法,java调用C
0
韦韦韦
    NSString *initIv = @"12345678"; 你这个偏移变量装换完之后貌似是字符 但是java里的是数字吧 你这么写试试 

Byte iv[] = {1,2,3,4,5,6,7,8}; 这样保持了和java一致 我觉得应该可以

返回顶部
顶部