美文网首页ios 开发
iOS Android DES加解密一致性问题

iOS Android DES加解密一致性问题

作者: 小乙的乙 | 来源:发表于2019-04-24 10:31 被阅读0次

    iOS Android DES加解密一致性问题

    iOS DES 加解密

    // 加密方法
    + (NSData *)DESEncrypt:(NSData *)data WithKey:(NSString *)key
    {
        //DES密钥参与运算的只有64位,超出的部分并不参与加密运算 可参考 https://www.cnblogs.com/songwenlong/p/5944139.html
        char keyPtr[kCCKeySizeAES256+1];
        bzero(keyPtr, sizeof(keyPtr));
        [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
      
        NSUInteger dataLength = [data length];
        
        size_t bufferSize = dataLength + kCCBlockSizeAES128;
        void *buffer = malloc(bufferSize);
    
        NSData *keybyte = [key dataUsingEncoding:NSUTF8StringEncoding];
        size_t numBytesEncrypted = 0;
      // ios中填写的参数比较多,android中有些参数在cipher中默认了
        CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmDES,
                                              kCCOptionPKCS7Padding,
                                              keyPtr, kCCBlockSizeDES,
                                              [keybyte bytes],
                                              [data bytes], dataLength,
                                              buffer, bufferSize,
                                              &numBytesEncrypted);
        if (cryptStatus == kCCSuccess) {
            return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
        }
        free(buffer);
        return nil;
    }
    
    // 解密方法
    + (NSData *)DESDecrypt:(NSData *)data WithKey:(NSString *)key
    {
        char keyPtr[kCCKeySizeAES256+1];
        bzero(keyPtr, sizeof(keyPtr));
        
        [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
        
        NSUInteger dataLength = [data length];
        
        size_t bufferSize = dataLength + kCCBlockSizeAES128;
        void *buffer = malloc(bufferSize);
        NSData *keybyte = [key dataUsingEncoding:NSUTF8StringEncoding];
        size_t numBytesDecrypted = 0;
        CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmDES,
                                              kCCOptionPKCS7Padding,
                                              keyPtr, kCCBlockSizeDES,
                                              [keybyte bytes],
                                              [data bytes], dataLength,
                                              buffer, bufferSize,
                                              &numBytesDecrypted);
        
        if (cryptStatus == kCCSuccess) {
            return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
        }
        
        free(buffer);
        return nil;
    }
    

    Android DES加解密

    // 加密
        public static String encode(String key, byte[] data) throws Exception {
            try {
                DESKeySpec dks = new DESKeySpec(key.getBytes());
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
                // key的长度不能够小于8位字节
                Key secretKey = keyFactory.generateSecret(dks);
                Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
                IvParameterSpec iv = new IvParameterSpec(key.getBytes());
                AlgorithmParameterSpec paramSpec = iv;
                cipher.init(Cipher.ENCRYPT_MODE, secretKey);
                byte[] bytes = cipher.doFinal(data);
                // return byte2hex(bytes);
                return new String(Base64.encode(bytes));
            } catch (Exception e) {
                throw new Exception(e);
            }
        }
    
    //解密
        public static byte[] decode(String key, byte[] data) throws Exception {
            try {
                SecureRandom sr = new SecureRandom();
                DESKeySpec dks = new DESKeySpec(key.getBytes());
                SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
                // key的长度不能够小于8位字节
                Key secretKey = keyFactory.generateSecret(dks);
                Cipher cipher = Cipher.getInstance(ALGORITHM_DES);
                IvParameterSpec iv = new IvParameterSpec(key.getBytes());
                AlgorithmParameterSpec paramSpec = iv;
                cipher.init(Cipher.DECRYPT_MODE, secretKey);
                return cipher.doFinal(data);
            } catch (Exception e) {
                throw new Exception(e);
            }
        }
    

    iOS中支持的填充只有两种模式

    /*!
        @enum       CCOptions
        @abstract   Options flags, passed to CCCryptorCreate().
    
        @constant   kCCOptionPKCS7Padding   Perform PKCS7 padding.
        @constant   kCCOptionECBMode        Electronic Code Book Mode.
                                            Default is CBC.
    */
    enum {
        /* options for block ciphers */
        kCCOptionPKCS7Padding   = 0x0001,
        kCCOptionECBMode        = 0x0002
        /* stream ciphers currently have no options */
    };
    typedef uint32_t CCOptions;
    

    注意:
    ⚠️ EBC 填充模式是不需要填写iv向量的,而kCCOptionPKCS7Padding 是需要填写iv 值的
    ⚠️iOS中没有PKCS5Padding 填充模式

    • java 中 "DES/CBC/PKCS5Padding" 对应的Object-C的是 kCCOptionPKCS7Padding
    • java中 "DES/ECB/PKCS5Padding" 对应的Object-C的是 kCCOptionPKCS7Padding | kCCOptionECBMod

    代码DEMO

    参考文章:

    1. https://www.cnblogs.com/LQCQ-Silent/p/5926584.html
    2. https://www.tuicool.com/articles/UJJrAj

    相关文章

      网友评论

        本文标题:iOS Android DES加解密一致性问题

        本文链接:https://www.haomeiwen.com/subject/ciybgqtx.html