精华内容
下载资源
问答
  • 音频文件加密解密

    2019-04-10 19:00:48
    音频文件加密解密。https://download.csdn.net/download/u012964281/8233079 整理成gradle,手动在设置中开启权限,将raw下音频文件放到手机存储根目录
  • DSP语音加密,通过音频数据的镜像翻转对音频进行加密,从mic接口输入,从line out接口输出,用按键控制,key_1录音,Key_2播放加密音频, Key_3播放解密音频
  • 实时音频信号加密
  • 音频加密解密1.txt

    2020-01-12 15:25:56
    信号 音频加密解密1.txt
  • 到目前为止,所有看到的设备都使用扩展名为.smp的XOR加密音频文件。 特征: 加密或解密单个文件。 加密或解密完整目录。 播放加密的音频文件,而无需先对其解密。 生成.mct文件以与一起使用,以为Salvat / hach...
  • Android 加密/解密音频文件(AES)

    热门讨论 2014-12-07 15:37:07
    使用AES算法加解密本地音频文件 博客地址:http://blog.csdn.net/u012964281/article/details/41787857
  • 运行代码前,将待加密的音频文件与代码文件放在同一目录下,并将文件“encryption.m”的第一行更改为与待加密音频文件的文件名相匹配 运行程序时请遵循此顺序 1. 运行 code_gen.m 2.运行encryption.m 3.运行...
  • 嗨,我想使用C#播放音频文件。 我该如何实现。 如何使用C#加密解密音频文件。
  • 使用RSA加密/解密音频文件的MATLAB程序 在运行代码之前,将要加密音频文件与代码文件放在同一目录中,并更改文件“ encryption.m”的第一行以使其与要加密音频文件的文件名相匹配。 运行程序时请遵循以下顺序 ...
  • 字符串传输PY Python项目:将字符串加密音频/从音频解密字符串
  • 加密解密

    千次阅读 2018-10-08 18:31:47
    1.加密解密 1.1 问答环节 1.2 加解密概况 2.对称加密和非对称加密 2.1 什么是对称加密 2.2 什么是非对称加密 2.3 常见对称加密有什么 2.4 常见非对称加密有什么 2.5 非对称加密用途 3.关于单向加密 3.1 MD...

    目录介绍

    • 1.加密和解密
      • 1.1 问答环节
      • 1.2 加解密概况
    • 2.对称加密和非对称加密
      • 2.1 什么是对称加密
      • 2.2 什么是非对称加密
      • 2.3 常见对称加密有什么
      • 2.4 常见非对称加密有什么
      • 2.5 非对称加密用途
    • 3.关于单向加密
      • 3.1 MD加密
      • 3.2 什么叫做加盐
    • 4.加密和解密代码展示
      • 4.1 DES加密和解密
      • 4.2 AES解密和解密
    • 5.RSA非对称加解密
      • 5.1 公钥加密,私钥解密
      • 5.2 私钥加密,公钥解密
      • 5.3 完整工具类代码
      • 5.4 注意RSA加密填充方式
      • 5.5 RSA加密内容长度限制问题
      • 5.6 加解密效率测试
      • 5.7 分段加密解密工具类代码

    好消息

    • 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!转载请注明出处,谢谢!
    • https://github.com/yangchong211/YCBlogs

    1.加密和解密

    1.1 问答环节

    • 1.1.1 常见的加密和解密有哪些?
    • 1.1.2 MD5加密是属于什么类型?是否可逆,以及有哪些应用场景?
    • 1.1.3 实际开发中有哪些加解密的应用场景?

    1.2 加解密概况

    • 1)在对称加密算法中,双方使用的密钥相同,要求解密方事先必须知道加密密钥。这类加密算法技术较为成熟,加密效率高。
    • 2)在非对称加密算法中,收发双方使用不同的密钥,发方使用公开密钥对消息进行加密,收发使用私有密钥机型解密,保密性更高,但效率更低。
    • 3)单向加密算法在加密过程中不需要使用密钥,输入明文后由算法直接加密成密文,密文无法解密,只有重新输入密文,并经过同样的加密算法处理,得到形同的密文并被系统重新识别后,才能真正的解密,这种算法非常复杂,通常只在数据量有限的情形下使用,如广泛应用在计算机系统中的口令加密等。

    2.对称加密和非对称加密

    2.1 什么是对称加密

    • 密钥可以自己指定,只有一把密钥,如果密钥暴露,文件就会被暴露
    • 特点是加密速度很快,但是缺点是安全性较低,因为只要密钥暴漏,数据就可以被解密了。
    • 一句话概括:加密和解密都是用相同密钥

    2.2 什么是非对称加密

    • 有两把钥匙(密钥对),公钥和私钥,公钥的话给别人,私钥自己保存
    • 把密钥通常是通过程序生成,不能自己指定
    • 特点是加密速度慢些,但是安全系数很高
    • 加密和解密的规则是:公钥加密只能私钥解密,私钥加密只能公钥解密
    • 应用场景举例:在集成支付宝支付sdk时,需要生成私钥和公钥,公钥需要设置到支付宝网站的管理后台,在程序中调用支付接口的时候,使用我们自己的私钥进行加密,这样支付宝由于有公钥可以解密,其他人即时劫持了数据,但是没有公钥,也无法解密。
    • image

    2.3 常见对称加密有什么

    • DES算法(Data Encryption Standard)
    • AES算法(Advanced Encryption Standard)

    2.4 常见非对称加密有什么

    • RSA

    2.5 非对称加密用途

    • 身份认证
      • 一条加密信息若能用A 的公钥能解开,则该信息一定是用A 的私钥加密的,该能确定该用户是A。
      • image
    • 陌生人通信
      • A 和B 两个人互不认识,A把自己的公钥发给B,B也把自己的公钥发给A,则双方可以通过对方的公钥加密信息通信。C 虽然也能得到A、B 的公钥,但是他解不开密文。
      • image
    • 支付宝支付加密
      • 具体可以参考支付宝sdk的官方demo

    3.关于单向加密

    • MD5
      • 关于MD5加密的工具类代码如下所示

    4.加密和解密代码展示

    4.1 DES加密和解密【对称加密】

    • 加密过程

      • 需要加密的内容,也就是明文;然后需要密钥。最后通过工具类加密得到加密后的密文
      private final String desEncryptString = "yangchong";
      private final String desEncryptKey = "19930311";
      s1 = DES.encryptDES(desEncryptString, desEncryptKey);
      Log.e("加密和解密", s1);
      加密和解密: 84r1gS+D3Op8yrSnF5ZDrQ==
      //s1为加密后的密文
      
    • 解密过程

      • 利用加密后的密文,与设置的key,也就是密钥,则可以解密得到加密的内容
      String s2 = DES.decryptDES(s1, desEncryptKey);
      Log.e("加密和解密", s2);
      //加密和解密: yangchong
      
    • Android中实现DES加密和解密的核心代码如下

    public class DES {
    
        //初始化向量,随意填写
        private static byte[] iv = {1,2,3,4,5,6,7,8};
    
        /**
         *
         * @param encryptString         明文
         * @param encryptKey            密钥
         * @return                      加密后的密文
         */
        public static String encryptDES(String encryptString,String encryptKey){
            try {
                //实例化IvParameterSpec对象,使用指定的初始化向量
                IvParameterSpec zeroIv=new IvParameterSpec(iv);
                //实例化SecretKeySpec,根据传入的密钥获得字节数组来构造SecretKeySpec
                SecretKeySpec key =new SecretKeySpec(encryptKey.getBytes(),"DES");
                //创建密码器
                Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");
                //用密钥初始化Cipher对象
                cipher.init(Cipher.ENCRYPT_MODE,key,zeroIv);
                //执行加密操作
                byte[]encryptedData=cipher.doFinal(encryptString.getBytes());
                return Base64.encodeToString(encryptedData,0);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            }
            return null;
        }
    
    
        /**
         * 解密的过程与加密的过程大致相同
         * @param decryptString         密文
         * @param decryptKey            密钥
         * @return  返回明文
         */
    
        public static String decryptDES(String decryptString,String decryptKey){
    
            try {
                //先使用Base64解密
                byte[]byteMi = Base64.decode(decryptString,0);
                //实例化IvParameterSpec对象使用指定的初始化向量
                IvParameterSpec zeroIv=new IvParameterSpec(iv);
                //实例化SecretKeySpec,根据传入的密钥获得字节数组来构造SecretKeySpec,
                SecretKeySpec key=new SecretKeySpec(decryptKey.getBytes(),"DES");
                //创建密码器
                Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");
                //用密钥初始化Cipher对象,上面是加密,这是解密模式
                cipher.init(Cipher.DECRYPT_MODE,key,zeroIv);
                //获取解密后的数据
                byte [] decryptedData=cipher.doFinal(byteMi);
                return new String(decryptedData);
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchPaddingException e) {
                e.printStackTrace();
            } catch (InvalidAlgorithmParameterException e) {
                e.printStackTrace();
            } catch (InvalidKeyException e) {
                e.printStackTrace();
            } catch (BadPaddingException e) {
                e.printStackTrace();
            } catch (IllegalBlockSizeException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    

    4.2 AES解密和解密【对称加密】

    public class AES {
    
    
        private static final String Algorithm = "AES";
        private final static String HEX = "0123456789ABCDEF";
    
        //加密函数,key为密钥
        public static String encrypt(String key, String src) throws Exception {
            byte[] rawKey = getRawKey(key.getBytes());
            byte[] result = encrypt(rawKey, src.getBytes());
            return toHex(result);
        }
    
        //解密函数。key值必须和加密时的key一致
        public static String decrypt(String key, String encrypted) throws Exception {
            byte[] rawKey = getRawKey(key.getBytes());
            byte[] enc = toByte(encrypted);
            byte[] result = decrypt(rawKey, enc);
            return new String(result);
        }
    
        private static void appendHex(StringBuffer sb, byte b) {
            sb.append(HEX.charAt((b >> 4) & 0x0f)).append(HEX.charAt(b & 0x0f));
        }
    
        private static byte[] getRawKey(byte[] seed) throws Exception {
            KeyGenerator kgen = KeyGenerator.getInstance(Algorithm);
            // SHA1PRNG 强随机种子算法, 要区别Android 4.2.2以上版本的调用方法
            SecureRandom sr = null;
            if (android.os.Build.VERSION.SDK_INT >= 17) {
                sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
            } else {
                sr = SecureRandom.getInstance("SHA1PRNG");
            }
            sr.setSeed(seed);
            kgen.init(256, sr); // 256位或128位或192位
            SecretKey skey = kgen.generateKey();
            byte[] raw = skey.getEncoded();
            return raw;
        }
    
        private static byte[] encrypt(byte[] key, byte[] src) throws Exception {
            SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm);
            Cipher cipher = Cipher.getInstance(Algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(src);
            return encrypted;
        }
    
        private static byte[] decrypt(byte[] key, byte[] encrypted) throws Exception {
            SecretKeySpec skeySpec = new SecretKeySpec(key, Algorithm);
            Cipher cipher = Cipher.getInstance(Algorithm);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] decrypted = cipher.doFinal(encrypted);
            return decrypted;
        }
    
        private static byte[] toByte(String hexString) {
            int len = hexString.length() / 2;
            byte[] result = new byte[len];
            for (int i = 0; i < len; i++) {
                result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();
            }
            return result;
        }
    
        private static String toHex(byte[] buf) {
            if (buf == null) {
                return "";
            }
            StringBuffer result = new StringBuffer(2 * buf.length);
            for (int i = 0; i < buf.length; i++) {
                appendHex(result, buf[i]);
            }
            return result.toString();
        }
    
    }
    

    5.RSA非对称加解密

    5.1 公钥加密,私钥解密

    • 第一步:获取随机的公钥和私钥

      • 代码如下所示:
      //秘钥默认长度
      public static final int DEFAULT_KEY_SIZE = 2048;
      KeyPair keyPair = RSA.generateRSAKeyPair(DEFAULT_KEY_SIZE);
      if (keyPair != null) {
          // 公钥
          publicKey = (RSAPublicKey) keyPair.getPublic();
          // 私钥
          privateKey = (RSAPrivateKey) keyPair.getPrivate();
      }
      
    • 第二步:公钥加密

      • 代码如下所示:
      //用公钥对字符串进行加密
      try {
          bytes = RSA.encryptByPublicKey(DEFAULT_SPLIT, publicKey.getEncoded());
          String s = new String(bytes);
          Log.e("加密和解密", s);
      } catch (Exception e) {
          e.printStackTrace();
      }
      
    • 第三步:私钥解密

      //使用私钥进行解密
      try {
          byte[] bytes = RSA.decryptByPrivateKey(this.bytes, privateKey.getEncoded());
          String s = new String(bytes);
          Log.e("加密和解密", s);
          //解密后得到的数据:yangchong
      } catch (Exception e) {
          e.printStackTrace();
      }
      

    5.2 私钥加密,公钥解密

    • 第一步:获取随机的公钥和私钥

      • 代码如下所示:
      //秘钥默认长度
      public static final int DEFAULT_KEY_SIZE = 2048;
      KeyPair keyPair = RSA.generateRSAKeyPair(DEFAULT_KEY_SIZE);
      if (keyPair != null) {
          // 公钥
          publicKey = (RSAPublicKey) keyPair.getPublic();
          // 私钥
          privateKey = (RSAPrivateKey) keyPair.getPrivate();
      }
      
    • 第二步:私钥加密

      • 代码如下所示:
      //使用私钥加密
      try {
          bytes1 = RSA.encryptByPrivateKey(DEFAULT_SPLIT, privateKey.getEncoded());
          String s = new String(bytes);
          Log.e("加密和解密", s);
      } catch (Exception e) {
          e.printStackTrace();
      }
      
    • 第三步:公钥解密

      //使用公钥解密
      try {
          byte[] bytes = RSA.decryptByPublicKey(this.bytes1, publicKey.getEncoded());
          String s = new String(bytes);
          Log.e("加密和解密", s);
          //解密后得到的数据:yangchong
      } catch (Exception e) {
          e.printStackTrace();
      }
      

    5.3 完整工具类代码

    • 代码如下所示:
      public class RSA {
      
          public static final String RSA = "RSA";// 非对称加密密钥算法
          public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式
      
      
      
          /**
           * 随机生成RSA密钥对
           *
           * @param keyLength         密钥长度,范围:512~2048
           *                          一般1024
           * @return
           */
          public static KeyPair generateRSAKeyPair(int keyLength) {
              try {
                  KeyPairGenerator kpg = KeyPairGenerator.getInstance(RSA);
                  kpg.initialize(keyLength);
                  return kpg.genKeyPair();
              } catch (NoSuchAlgorithmException e) {
                  e.printStackTrace();
                  return null;
              }
          }
      
          /*-------------------------------------------------------------------------------------------------*/
      
      
          /**
           * 用公钥对字符串进行加密
           * @param data                      原文
           * @param publicKey                 密钥
           * @return                          byte[] 解密数据
           */
          public static byte[] encryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
              // 得到公钥
              X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
              KeyFactory kf = KeyFactory.getInstance(RSA);
              PublicKey keyPublic = kf.generatePublic(keySpec);
              // 加密数据
              Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
              cp.init(Cipher.ENCRYPT_MODE, keyPublic);
              return cp.doFinal(data);
          }
      
          /**
           * 私钥加密
           *
           * @param data                      待加密数据
           * @param privateKey                密钥
           * @return                          byte[] 解密数据
           */
          public static byte[] encryptByPrivateKey(byte[] data, byte[] privateKey) throws Exception {
              // 得到私钥
              PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
              KeyFactory kf = KeyFactory.getInstance(RSA);
              PrivateKey keyPrivate = kf.generatePrivate(keySpec);
              // 数据加密
              Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
              cipher.init(Cipher.ENCRYPT_MODE, keyPrivate);
              return cipher.doFinal(data);
          }
      
          /**
           * 公钥解密
           *
           * @param data                      待解密数据
           * @param publicKey                 密钥
           * @return                          byte[] 解密数据
           */
          public static byte[] decryptByPublicKey(byte[] data, byte[] publicKey) throws Exception {
              // 得到公钥
              X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKey);
              KeyFactory kf = KeyFactory.getInstance(RSA);
              PublicKey keyPublic = kf.generatePublic(keySpec);
              // 数据解密
              Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
              cipher.init(Cipher.DECRYPT_MODE, keyPublic);
              return cipher.doFinal(data);
          }
      
          /**
           * 使用私钥进行解密
           * @param encrypted                 待解密数据
           * @param privateKey                密钥
           * @return                          byte[] 解密数据
           * @throws Exception                异常
           */
          public static byte[] decryptByPrivateKey(byte[] encrypted, byte[] privateKey) throws Exception {
              // 得到私钥
              PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKey);
              KeyFactory kf = KeyFactory.getInstance(RSA);
              PrivateKey keyPrivate = kf.generatePrivate(keySpec);
              // 解密数据
              Cipher cp = Cipher.getInstance(ECB_PKCS1_PADDING);
              cp.init(Cipher.DECRYPT_MODE, keyPrivate);
              byte[] arr = cp.doFinal(encrypted);
              return arr;
          }
      
      }
      

    5.4 注意RSA加密填充方式

    • 之前以为上面操作就能实现rsa加解密,以为可以呢,但是遇到Android这边加密过的数据,服务器端死活解密不了,原来android系统的RSA实现是"RSA/None/NoPadding",而标准JDK实现是"RSA/None/PKCS1Padding",这造成了在android机上加密后无法在服务器上解密的原因,所以在实现的时候这个一定要注意这个问题。

    5.5 RSA加密内容长度限制问题

    • RSA非对称加密内容长度有限制,1024位key的最多只能加密127位数据,否则就会报错(javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes)
    • RSA 算法规定:待加密的字节数不能超过密钥的长度值除以 8 再减去 11(即:KeySize / 8 - 11),而加密后得到密文的字节数,正好是密钥的长度值除以 8(即:KeySize / 8)。

    5.6 加解密效率测试

    • 第一步:获取随机的公钥和私钥

      • 代码如下所示:
      //秘钥默认长度
      public static final int DEFAULT_KEY_SIZE = 2048;
      KeyPair keyPair = RSA.generateRSAKeyPair(DEFAULT_KEY_SIZE);
      if (keyPair != null) {
          // 公钥
          publicKey = (RSAPublicKey) keyPair.getPublic();
          // 私钥
          privateKey = (RSAPrivateKey) keyPair.getPrivate();
      }
      
    • 第二步:用公钥对对象进行加密

      • 代码如下所示:
      //用公钥对对象进行加密
      YC yc = new YC();
      yc.setAge(25);
      yc.setName("杨充");
      StringBuilder stringBuilder = new StringBuilder();
      for(int a=0 ; a<500 ; a++){
          stringBuilder.append("都比小杨"+a);
      }
      yc.setInfo(stringBuilder.toString());
      String string = yc.toString();
      long start = System.currentTimeMillis();
      encryptBytes = new byte[0];
      try {
          encryptBytes = RSA.encryptByPublicKeyForSpilt(string.getBytes(),publicKey.getEncoded());
      } catch (Exception e) {
          e.printStackTrace();
      }
      long end=System.currentTimeMillis();
      Log.e("YC","公钥加密耗时 cost time---->"+(end-start));
      String encryStr = new String(encryptBytes);
      Log.e("YC","加密前数据长度 --1-->"+string.length());
      Log.e("YC","加密后数据长度 --1-->"+encryStr.length());
      
    • 第三步:使用私钥进行解密

      //使用私钥进行解密
      long start2 = System.currentTimeMillis();
      byte[] decryptBytes= new byte[0];
      try {
          decryptBytes = RSA.decryptByPrivateKeyForSpilt(encryptBytes,privateKey.getEncoded());
      } catch (Exception e) {
          e.printStackTrace();
      }
      String decryStr = new String(decryptBytes);
      long end2 =System.currentTimeMillis();
      Log.e("YC","私钥解密耗时 cost time---->"+(end2-start2));
      Log.e("YC","解密后数据 --1-->"+decryStr);
      
    • 第四步:加密和解密效率比较

      • 如下所示
      • 加密后数据大小的变化:数据量差不多是加密前的1.6倍
      • 经过几次测试可知,解密要比加密费时间多,所以一般建议在服务端做解密的逻辑操作
      • image

    5.7 分段加密解密工具类代码

    • 代码如下所示
      //秘钥默认长度
      private static final int DEFAULT_KEY_SIZE = 2048;
      // 当前秘钥支持加密的最大字节数
      private static final int DEFAULT_BUFFER_SIZE = (DEFAULT_KEY_SIZE / 8) - 11;
      // 当要加密的内容超过bufferSize,则采用partSplit进行分块加密
      private static final byte[] DEFAULT_SPLIT = "#PART#".getBytes();
      
      /**
       * 用公钥对字符串进行分段加密
       * @param data                      需要加密数据
       * @param publicKey                 公钥
       * @return                          byte[] 加密数据
       * @throws Exception                异常
       *                                  https://github.com/yangchong211
       */
      public static byte[] encryptByPublicKeyForSpilt(byte[] data, byte[] publicKey) throws Exception {
          int dataLen = data.length;
          if (dataLen <= DEFAULT_BUFFER_SIZE) {
              return encryptByPublicKey(data, publicKey);
          }
          List<Byte> allBytes = new ArrayList<>(2048);
          int bufIndex = 0;
          int subDataLoop = 0;
          byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
          for (int i = 0; i < dataLen; i++) {
              if (buf != null) {
                  buf[bufIndex] = data[i];
              }
              if (++bufIndex == DEFAULT_BUFFER_SIZE || i == dataLen - 1) {
                  subDataLoop++;
                  if (subDataLoop != 1) {
                      for (byte b : DEFAULT_SPLIT) {
                          allBytes.add(b);
                      }
                  }
                  byte[] encryptBytes = encryptByPublicKey(buf, publicKey);
                  for (byte b : encryptBytes) {
                      allBytes.add(b);
                  }
                  bufIndex = 0;
                  if (i == dataLen - 1) {
                      buf = null;
                  } else {
                      buf = new byte[Math.min(DEFAULT_BUFFER_SIZE, dataLen - i - 1)];
                  }
              }
          }
          byte[] bytes = new byte[allBytes.size()];
          int i = 0;
          for (Byte b : allBytes) {
              bytes[i++] = b;
          }
          return bytes;
      }
      
      /**
       * 用秘钥对字符串进行分段加密
       *
       * @param data                      要加密的原始数据
       * @param privateKey                秘钥
       * @return                          byte[] 加密数据
       * @throws Exception                异常
       *                                  https://github.com/yangchong211
       */
      public static byte[] encryptByPrivateKeyForSpilt(byte[] data, byte[] privateKey) throws Exception {
          int dataLen = data.length;
          if (dataLen <= DEFAULT_BUFFER_SIZE) {
              return encryptByPrivateKey(data, privateKey);
          }
          List<Byte> allBytes = new ArrayList<Byte>(2048);
          int bufIndex = 0;
          int subDataLoop = 0;
          byte[] buf = new byte[DEFAULT_BUFFER_SIZE];
          for (int i = 0; i < dataLen; i++) {
              if (buf != null) {
                  buf[bufIndex] = data[i];
              }
              if (++bufIndex == DEFAULT_BUFFER_SIZE || i == dataLen - 1) {
                  subDataLoop++;
                  if (subDataLoop != 1) {
                      for (byte b : DEFAULT_SPLIT) {
                          allBytes.add(b);
                      }
                  }
                  byte[] encryptBytes = encryptByPrivateKey(buf, privateKey);
                  for (byte b : encryptBytes) {
                      allBytes.add(b);
                  }
                  bufIndex = 0;
                  if (i == dataLen - 1) {
                      buf = null;
                  } else {
                      buf = new byte[Math.min(DEFAULT_BUFFER_SIZE, dataLen - i - 1)];
                  }
              }
          }
          byte[] bytes = new byte[allBytes.size()];
          int i = 0;
          for (Byte b : allBytes) {
              bytes[i++] = b;
          }
          return bytes;
      }
      
      /**
       * 用公钥分段解密
       *
       * @param encrypted                 待解密数据
       * @param publicKey                 公钥
       * @return                          byte[] 解密数据
       * @throws Exception                异常
       *                                  https://github.com/yangchong211
       */
      public static byte[] decryptByPublicKeyForSpilt(byte[] encrypted, byte[] publicKey) throws Exception {
          int splitLen = DEFAULT_SPLIT.length;
          if (splitLen <= 0) {
              return decryptByPublicKey(encrypted, publicKey);
          }
          int dataLen = encrypted.length;
          List<Byte> allBytes = new ArrayList<Byte>(1024);
          int latestStartIndex = 0;
          for (int i = 0; i < dataLen; i++) {
              byte bt = encrypted[i];
              boolean isMatchSplit = false;
              if (i == dataLen - 1) {
                  // 到data的最后了
                  byte[] part = new byte[dataLen - latestStartIndex];
                  System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                  byte[] decryptPart = decryptByPublicKey(part, publicKey);
                  for (byte b : decryptPart) {
                      allBytes.add(b);
                  }
                  latestStartIndex = i + splitLen;
                  i = latestStartIndex - 1;
              } else if (bt == DEFAULT_SPLIT[0]) {
                  // 这个是以split[0]开头
                  if (splitLen > 1) {
                      if (i + splitLen < dataLen) {
                          // 没有超出data的范围
                          for (int j = 1; j < splitLen; j++) {
                              if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
                                  break;
                              }
                              if (j == splitLen - 1) {
                                  // 验证到split的最后一位,都没有break,则表明已经确认是split段
                                  isMatchSplit = true;
                              }
                          }
                      }
                  } else {
                      // split只有一位,则已经匹配了
                      isMatchSplit = true;
                  }
              }
              if (isMatchSplit) {
                  byte[] part = new byte[i - latestStartIndex];
                  System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                  byte[] decryptPart = decryptByPublicKey(part, publicKey);
                  for (byte b : decryptPart) {
                      allBytes.add(b);
                  }
                  latestStartIndex = i + splitLen;
                  i = latestStartIndex - 1;
              }
          }
          byte[] bytes = new byte[allBytes.size()];
          int i = 0;
          for (Byte b : allBytes) {
              bytes[i++] = b;
          }
          return bytes;
      }
      
      /**
       * 使用私钥分段解密
       *
       * @param encrypted                 待解密数据
       * @param privateKey                私钥
       * @return                          byte[] 解密数据
       * @throws Exception                异常
       *                                  https://github.com/yangchong211
       */
      public static byte[] decryptByPrivateKeyForSpilt(byte[] encrypted, byte[] privateKey) throws Exception {
          int splitLen = DEFAULT_SPLIT.length;
          if (splitLen <= 0) {
              return decryptByPrivateKey(encrypted, privateKey);
          }
          int dataLen = encrypted.length;
          List<Byte> allBytes = new ArrayList<Byte>(1024);
          int latestStartIndex = 0;
          for (int i = 0; i < dataLen; i++) {
              byte bt = encrypted[i];
              boolean isMatchSplit = false;
              if (i == dataLen - 1) {
                  // 到data的最后了
                  byte[] part = new byte[dataLen - latestStartIndex];
                  System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                  byte[] decryptPart = decryptByPrivateKey(part, privateKey);
                  for (byte b : decryptPart) {
                      allBytes.add(b);
                  }
                  latestStartIndex = i + splitLen;
                  i = latestStartIndex - 1;
              } else if (bt == DEFAULT_SPLIT[0]) {
                  // 这个是以split[0]开头
                  if (splitLen > 1) {
                      if (i + splitLen < dataLen) {
                          // 没有超出data的范围
                          for (int j = 1; j < splitLen; j++) {
                              if (DEFAULT_SPLIT[j] != encrypted[i + j]) {
                                  break;
                              }
                              if (j == splitLen - 1) {
                                  // 验证到split的最后一位,都没有break,则表明已经确认是split段
                                  isMatchSplit = true;
                              }
                          }
                      }
                  } else {
                      // split只有一位,则已经匹配了
                      isMatchSplit = true;
                  }
              }
              if (isMatchSplit) {
                  byte[] part = new byte[i - latestStartIndex];
                  System.arraycopy(encrypted, latestStartIndex, part, 0, part.length);
                  byte[] decryptPart = decryptByPrivateKey(part, privateKey);
                  for (byte b : decryptPart) {
                      allBytes.add(b);
                  }
                  latestStartIndex = i + splitLen;
                  i = latestStartIndex - 1;
              }
          }
          byte[] bytes = new byte[allBytes.size()];
          int i = 0;
          for (Byte b : allBytes) {
              bytes[i++] = b;
          }
          return bytes;
      }
      

    关于其他内容介绍

    01.关于博客汇总链接

    02.关于我的博客

    展开全文
  • 实现C#加密各种文件 和解密加密后的文件 完整工程 直接可以编译运行
  • * 文件解密方法 */ private static void unCodeFile() { String Path = "G:\\filmVideo\\417\\american"; List<File> lists = FileUtil.getFileListFromPath(Path); if (lists == null || lists.size() )...

     

    代码比较简单,不做解释

    主界面调用方法,具体使用场景,需要根据自己的需求去封装

    package com.demo;
    
    import java.io.File;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    import thread.FileCodeListener;
    import thread.FileCodeRunnable;
    import thread.FileUnCodeRunnable;
    import thread.FileUtil;
    
    public class TestDemo {
    
    	static ExecutorService executor = Executors.newFixedThreadPool(10);
    
    	public static void main(String[] args) {
    		// codeFile();
    		unCodeFile();
    	}
    
    	/**
    	 * 文件解密方法
    	 */
    	private static void unCodeFile() {
    		String Path = "G:\\filmVideo\\417\\american";
    		List<File> lists = FileUtil.getFileListFromPath(Path);
    		if (lists == null || lists.size() < 1) {
    			System.out.println("====文件夹的个数 0 ==");
    			return;
    		}
    		System.out.println("====文件夹的个数==" + lists.size());
    		for (int i = 0; i < lists.size(); i++) {
    			String fileName = lists.get(i).getName();
    			String filePath = lists.get(i).getAbsolutePath();
    			String cachePath = "G:\\filmVideo\\417\\americanCache\\" + fileName;
    			FileUnCodeRunnable runnbale = new FileUnCodeRunnable(filePath, cachePath, new FileCodeListener() {
    
    				@Override
    				public void codeFileStatues(boolean isSuccess, String desc) {
    					System.out.println("====codeFileStatues====" + isSuccess + " / " + desc);
    				}
    
    				@Override
    				public void codeFileProgress(int progress) {
    					System.out.println("====progress====" + progress);
    
    				}
    			});
    			executor.execute(runnbale);
    		}
    	}
    
    	/**
    	 * 文件加密
    	 */
    	private static void codeFile() {
    		String filePath = "E:\\log\\aaa.mp4";
    		String cachePath = "E:\\log\\bbb.mp4";
    
    		FileCodeRunnable runnbale = new FileCodeRunnable(cachePath, filePath, new FileCodeListener() {
    
    			@Override
    			public void codeFileStatues(boolean isSuccess, String desc) {
    				System.out.println("====codeFileStatues====" + isSuccess + " / " + desc);
    			}
    
    			@Override
    			public void codeFileProgress(int progress) {
    				System.out.println("====progress====" + progress);
    
    			}
    		});
    		executor.execute(runnbale);
    	}
    }
    

     

    package thread;
    
    public class Config {
    
    	public static final String PASSWORD = "123456";
    
    }
    

     转码回调类

    package thread;
    
    public interface FileCodeListener {
    
    	// 转码进度
    	void codeFileProgress(int progress);
    
    	// 转码状态
    	void codeFileStatues(boolean isSuccess, String desc);
    
    }
    
    package thread;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.io.RandomAccessFile;
    
    /**
     * 文件加密方法
     * 
     * @author Administrator
     *
     */
    public class FileCodeRunnable implements Runnable {
    
    	String filePath;
    	String cachePath;
    	FileCodeListener listener;
    	long fileLenth = 1;
    
    	public FileCodeRunnable(String filePath, String cachePath, FileCodeListener listener) {
    		this.filePath = filePath;
    		this.cachePath = cachePath;
    		this.listener = listener;
    	}
    
    	@Override
    	public void run() {
    		File file = new File(filePath);
    		if (!file.exists()) {
    			listener.codeFileStatues(false, "文件不存在");
    			return;
    		}
    		fileLenth = file.length();
    		enCode();
    	}
    
    	public void enCode() {
    		InputStream in = null;
    		OutputStream out = null;
    		try {
    			File file = new File(filePath);
    			if (!file.exists()) {
    				return;
    			}
    			in = new FileInputStream(filePath);
    			out = new FileOutputStream(cachePath);
    			byte[] buffer = new byte[1024];
    			byte[] buffer2 = new byte[1024];
    			int readLength;
    			long sumLength = 0;
    			while ((readLength = in.read(buffer)) > 0) {
    				for (int i = 0; i < readLength; i++) {
    					byte b = buffer[i];
    					buffer2[i] = b == 255 ? 0 : ++b;// 文件的每一byte增1
    				}
    				sumLength = sumLength + readLength;
    				int progress = (int) (sumLength * 100 / fileLenth);
    				listener.codeFileProgress(progress);
    				out.write(buffer2, 0, readLength);
    				out.flush();
    			}
    			appendTail(cachePath, Config.PASSWORD);
    			listener.codeFileStatues(true, "转码完成");
    		} catch (Exception e) {
    			listener.codeFileStatues(true, "转码异常:" + e.toString());
    			e.printStackTrace();
    		} finally {
    			try {
    				if (in != null) {
    					in.close();
    				}
    				if (out != null) {
    					out.close();
    				}
    			} catch (Exception e2) {
    			}
    		}
    	}
    
    	/**
    	 * 在文件尾添加指定的字符串  
    	 * 
    	 * @param fileName
    	 * @param content
    	 */
    	private static void appendTail(String fileName, String content) {
    		try {
    			RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");
    			long fileLength = randomFile.length();
    			randomFile.seek(fileLength);
    			randomFile.writeBytes(content);
    			randomFile.close();
    		} catch (IOException e) {
    			e.printStackTrace();
    		}
    	}
    
    }
    

    解密工具类

    package thread;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    /**
     * 文件解密方法
     * 
     * @author Administrator
     *
     */
    public class FileUnCodeRunnable implements Runnable {
    
    	String filePath;
    	String cachePath;
    	FileCodeListener listener;
    	long fileLenth = 1;
    
    	public FileUnCodeRunnable(String filePath, String cachePath, FileCodeListener listener) {
    		this.filePath = filePath;
    		this.cachePath = cachePath;
    		this.listener = listener;
    	}
    
    	@Override
    	public void run() {
    		File file = new File(filePath);
    		if (!file.exists()) {
    			listener.codeFileStatues(false, "文件不存在");
    			return;
    		}
    		fileLenth = file.length();
    		unCode();
    	}
    
    	public void unCode() {
    		InputStream is = null;
    		OutputStream out = null;
    		try {
    			File file = new File(filePath);
    			if (!file.exists()) {
    				return;
    			}
    			File dest = new File(cachePath);
    			if (!dest.getParentFile().exists()) {
    				dest.getParentFile().mkdirs();
    			}
    			is = new FileInputStream(filePath);
    			out = new FileOutputStream(cachePath);
    
    			byte[] buffer = new byte[1024];
    			byte[] buffer2 = new byte[1024];
    			byte bMax = (byte) 255;
    			long size = file.length() - Config.PASSWORD.length();
    			int mod = (int) (size % 1024);
    			int div = (int) (size >> 10);
    			int count = mod == 0 ? div : (div + 1);
    			int k = 1;
    			int readLength = 0;
    			long sumWrite = 0; // 已经读写的
    			while ((k <= count && (readLength = is.read(buffer)) > 0)) {
    				if (mod != 0 && k == count) {
    					readLength = mod;
    				}
    				for (int i = 0; i < readLength; i++) {
    					byte b = buffer[i];
    					buffer2[i] = b == 0 ? bMax : --b;// 文件的每一个byte减1
    				}
    				sumWrite = sumWrite + readLength;
    
    				int progress = (int) (sumWrite * 100 / fileLenth);
    				listener.codeFileProgress(progress);
    				out.write(buffer2, 0, readLength);
    				k++;
    			}
    			listener.codeFileStatues(true, "解码成功");
    		} catch (Exception e) {
    			listener.codeFileStatues(false, "解码异常:" + e.toString());
    			e.printStackTrace();
    		} finally {
    			try {
    				if (out != null) {
    					out.close();
    				}
    				if (is != null) {
    					is.close();
    				}
    			} catch (Exception e2) {
    
    			}
    		}
    	}
    
    }
    

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    展开全文
  • 音频加密解密1 使用场景推流时将编码后的音频数据加密,再发送到云端。拉流时将加密音频数据解密,再进行解码、渲染。2 推流端用法// init sdk之前设置开关ZegoAudioEncryptDecrypt.enableAudioEncryptDecrypt...

    音频加密与解密

    1 使用场景

    推流时将编码后的音频数据加密,再发送到云端。拉流时将加密的音频数据解密,再进行解码、渲染。

    2 推流端用法

    // init sdk之前设置开关

    ZegoAudioEncryptDecrypt.enableAudioEncryptDecrypt(true);

    // 创建加密对象

    private ZegoAudioEncryptDecrypt mZegoAudioEncryptDecrypt = new ZegoAudioEncryptDecrypt();

    // 设置回调,推流成功后会收到回调

    mZegoAudioEncryptDecrypt.setAudioEncryptDecryptCallback(new IZegoAudioEncryptDecryptCallback() {

    @Override

    public int onAudioEncryptDecrypt(String streamID, ByteBuffer inData, int inDataLen, ByteBuffer outData, int maxOutBufLen) {

    // sdk将编码后的数据存储在inData中回调给业务层,inDataLen为inData中的数据长度

    // maxOutBufLen是输出缓冲区(outData)的最大长度(inDataLen < maxOutBufLen), 业务层需要将加密后的实际数据长度return给sdk

    // 以下代码为示例代码,直接copy了inData中的数据到outData中,业务层根据需求自行加密

    int realOutDataLen = inDataLen;

    if (realOutDataLen > maxOutBufLen) {

    realOutDataLen = maxOutBufLen;

    }

    for (int i = 0; i < realOutDataLen; i++) {

    outData.put(inData.get(i));

    }

    return realOutDataLen;

    }

    });

    // 当不需要使用数据加密功能时,置空回调,避免内存泄漏

    mZegoAudioEncryptDecrypt.setAudioEncryptDecryptCallback(null);

    3 拉流端用法

    // init sdk之前设置开关

    ZegoAudioEncryptDecrypt.enableAudioEncryptDecrypt(true);

    // 创建加密对象

    private ZegoAudioEncryptDecrypt mZegoAudioEncryptDecrypt = new ZegoAudioEncryptDecrypt();

    // 设置回调,拉流成功后会收到回调

    mZegoAudioEncryptDecrypt.setAudioEncryptDecryptCallback(new IZegoAudioEncryptDecryptCallback() {

    @Override

    public int onAudioEncryptDecrypt(String streamID, ByteBuffer inData, int inDataLen, ByteBuffer outData, int maxOutBufLen) {

    // sdk将加密的音频数据存储在inData中回调给业务层,inDataLen为inData中的数据长度

    // maxOutBufLen是输出缓冲区(outData)的最大长度(inDataLen < maxOutBufLen), 业务层需要将解密后的实际数据长度return给sdk

    // 以下代码为示例代码,直接copy了inData中的数据到outData中,业务层根据需求自行解密

    int realOutDataLen = inDataLen;

    if (realOutDataLen > maxOutBufLen) {

    realOutDataLen = maxOutBufLen;

    }

    for (int i = 0; i < realOutDataLen; i++) {

    outData.put(inData.get(i));

    }

    return realOutDataLen;

    }

    });

    // 当不需要使用数据解密功能时,置空回调,避免内存泄漏

    mZegoAudioEncryptDecrypt.setAudioEncryptDecryptCallback(null);

    4 注意

    当业务层需要同时使用音频加密、解密功能时,步骤二、步骤三中的代码可共用,onAudioEncryptDecrypt回调中的streamID用于区分推流、拉流。

    展开全文
  • 开局一张图 应该都见过ExoPlayer源码浅析ExoPlayer官方文档ExoPlayer GitHub需求与适用范围首先本文的适用范围是使用ExoPlayer框架时,直接解密播放已经经过AES加密过(或者类似需求)的音频或者视频,是利用官方...

    开局一张图 应该都见过

    dataSource.png

    ExoPlayer源码浅析

    ExoPlayer官方文档

    ExoPlayer GitHub

    需求与适用范围

    首先本文的适用范围是使用ExoPlayer框架时,直接解密播放已经经过AES加密过(或者类似需求)的音频或者视频,是利用官方demo内DefaultDataSourceFactory与DefaultDataSource改造而来。有需求就可以继续往下看了

    0.故事的开始

    故事的开始还得从新需求开始说起。公司新开了一个旅游项目,其中主要功能就是播放在线或者本地音频,这个非常非常平常的需求,让我开始EXO之旅。

    为什么不使用最平常简单的MediaPlayer,因为程序员喜新厌旧哇 嘻嘻。

    其中我们最主要的需求就是,下载下来的本地音频需要加密存放在本地,在播放的时候进行解密播放,以保证数据的安全性,在这里选用了常见的AES加解密。

    相信这些需求应该的比较常见的类型了,在选用Exoplayer之后,在线播放什么的肯定不用花费过多时间了,但在进行本地播放的时候碰到了问题。

    当初在查询ExoPlayer文档的时候是知道和看中了它的自定义资源播放功能的,官方文档和各种源码解析都说它有强大的自定义功能,但是等到我真正要实现我功能的时候,我感觉ExoPlayer是一个孤儿…

    为什么在GitHub上8000+星星的ExoPlayer在百度上的资料这么少(想抄都没地方抄)。。 百度Google了一圈下来,折腾完ExtractorsFactory,折腾Mp3Extractor,完全摸错了门。后来在stackOverflow 看到终于一篇关于自定义dataSource的提问,至此找到问题解决入口。

    思路与使用方式

    关于ExoPlayer的各种源码、使用解析在这就不赘叙了。正常的情况下,使用ExoPlayer默认的DefaultDataSource是完成不了直接播放AES加密音频的。

    最开始,要实现播放,只能先把AES音频解密成正常的MP3音频,这样,就完全打破了最初我们要把本地下载下来的音频加密存放与播放的预想,解密过后的音频总会在文件夹中显示出来,并以正常的MP3存在,这样音频就毫无安全性可言了,也就是说没有完成需求。

    为解决能直接播放AES加密音频的问题,我们采用的是自定义改写DataSourceFactory类,改写DataSource类,复用官方demo中Aes128DataSource类来完成的。

    只需要改写这一系列DataSource类文件,就可以完成我们直接播放AES音频文件的需求,下面逐个进行解析。

    通过前期查看和研究ExoPlayer源码我们观察到,这一系列的资源提供、分拆与解析过程在ExtractorMediaSource下的ExtractorMediaPeriod类有很清晰的体现。

    DefaultExtractorInput.png

    而我们需要实现的需求中,本质上只是把MP3文件加密了一次而已,它在播放的时候,最终只需要在拆解提供资源的时候把加密的文件流解密成正常的MP3流,给ExtractorMediaSource提供正常的MP3流即可,所以并不需要再过多的进行其他复杂操作就可以完成此需求。

    那么我实现的就是重写DefaultDataSourceFactory资源提供工厂类,改造DefaultDataSource,根据文件类型判断,加密的音频使用Aes128DataSource类拆解进行解密,未加密或者在线的URL继续使用getFileDataSource或者getContentDataSource原本默认的实现进行拆解。最后只需要用我们改写的factory替换默认的DataSourceFactory就可以完成我们的需求了。

    TestPlayerActivity.png

    1.AitripDataSourceFactory

    AitripDataSourceFactory是重写的DataSourceFactory工厂类,直接copyDefaultDataSource而来。主要是重写了createDataSource()方法,用于进入资源选择类AitripDataSource

        @Override
        public AitripDataSource createDataSource() {
            return new AitripDataSource(context, listener, baseDataSourceFactory.createDataSource());
        }

    2.AitripDataSource

    改写DataSource内open方法,用于扩展数据源选择方案,以让其正确选择到我们的解密Aes128DataSource类,注释基本可以解释一切。因为我在本地加密的文件是在文件名后又添加了.aitrip字段,所以只需根据文件名判断是否包含.aitrip,选择正确的DataSource解析即可。

        @Override
        public long open(DataSpec dataSpec) throws IOException {
            Assertions.checkState(dataSource == null);
            // Choose the correct source for the scheme.
            //选择正确的数据源方案
            String scheme = dataSpec.uri.getScheme();
            //如果URI是一个本地文件路径或本地文件的引用。
            Timber.e("解密:000000," + scheme + ",path:" + dataSpec.uri.getPath());
            if (Util.isLocalFileUri(dataSpec.uri)) {
                //如果路径尾包含aitrip的文件名,使用解密类
                if (dataSpec.uri.getPath().endsWith(".aitrip")) {
                    Aes128DataSource aes128DataSource =
                            new Aes128DataSource(getFileDataSource(), Aikey.getBytes(), Aikey.getBytes());
                    dataSource = aes128DataSource;
                } else {//否则,正常解析mp3
                    if (dataSpec.uri.getPath().startsWith("/android_asset/")) {
                        dataSource = getAssetDataSource();
                    } else {
                        dataSource = getFileDataSource();
                    }
                }
            } else if (SCHEME_ASSET.equals(scheme)) {
                dataSource = getAssetDataSource();
            } else if (SCHEME_CONTENT.equals(scheme)) {
                dataSource = getContentDataSource();
            } else if (SCHEME_RTMP.equals(scheme)) {
                dataSource = getRtmpDataSource();
            } else {
                dataSource = baseDataSource;
            }
            // Open the source and return.
            return dataSource.open(dataSpec);
        }

    3.Aes128DataSource

    直接copy自官方demo的AesDataSource,其本用于HLS文件播放列表解密的,但是很巧的是采用了解密方式,对我也同样适用,所以并不需要改动任何一行代码。。
    它主要是实现open后,利用Aes解密方式解密文件流提供给上层使用。

      @Override
      public long open(DataSpec dataSpec) throws IOException {
        Cipher cipher;
        try {
          cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
          throw new RuntimeException(e);
        }
    
        Key cipherKey = new SecretKeySpec(encryptionKey, "AES");
        AlgorithmParameterSpec cipherIV = new IvParameterSpec(encryptionIv);
    
        try {
          cipher.init(Cipher.DECRYPT_MODE, cipherKey, cipherIV);
        } catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
          throw new RuntimeException(e);
        }
    
        cipherInputStream = new CipherInputStream(
            new DataSourceInputStream(upstream, dataSpec), cipher);
    
        return C.LENGTH_UNSET;
      }
    

    就这样。。 没了。 完成之后再看回来,这么简单。。。 全是copy。。 说个毛啊。。。。 然而,对于刚接触ExoPlayer,想要实现类似功能,而网上没啥参考的小伙伴来说,应该是有点用的,特此记录。。。。

    结束

    有帮助就点星星哟

    下载源码慢慢看喔

    有什么疑问或者建议欢迎issues留言噢

    ExoPlayerTest小demo的Github地址

    展开全文
  • 音频解密算法

    2015-07-01 10:01:30
    音频解密算法
  • unity播放加密音频文件

    千次阅读 2017-01-07 23:04:19
    首先说一下起因,我这里有需求读书软件要求播放加密音频文件,所以一般的组件和www加载都不能使用,于是我需要一种新的方案来加载音频文件。于是我找到了一个开源的音频处理类库NAudio来处理MP3和wav的音频文件,...
  • 普通base64加密解密 加密 解密 字符大小写加密解密 大小写加解密算法 加密 解密 异或加解密(钥匙加解密) 异或加解密(钥匙加解密)算法 加密 解密 效果图 加密算法 本文提供三种方式来加密解密,...
  • 本文提出一种数字音频的混沌加密方案,通过把音频信号的冗余信息自适应地替换成混沌同步信息,从而有效地解决了混沌同步信号的传输问题,并在解密时获得容许误差范围内的混沌同步,进而恢复出密钥序列进行解密,最后将...
  • 数字音频文件数据量大、相关性强...在解密时只需同步播放任意k份秘密音频就可直接通过人耳听觉系统解密,少于k份的任意秘密音频同步播放不会暴露原始音频的任何信息.实验结果表明,加密后的音频具有良好的随机性和安全性
  • DES 加密解密方法

    2021-05-21 15:06:59
    1.首先引入crypto-js.min.js库 <...</script>...2.注册des加密解密方法 //DES加密 function encryptByDES(message, key){ var keyHex = CryptoJS.enc.Utf8.parse(key); var encrypted = CryptoJS.D
  • 【原创】C# RC4 加密解密工具,欢迎大家使用。
  • Android加密算法之AES加密解密实现

    千次阅读 2014-10-20 20:25:21
    前面写了常用了MD5加密算法,一个肯定不能满足本屌丝的胃口,最近发现AES加密算法貌似挺牛逼的样子,还是是美国联邦政府采用的一种区块高级加密标准,一看到“高级”就把我吓尿了,果然牛逼,废话少说,先学会用再说...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,235
精华内容 3,294
关键字:

如何解密加密音频