Windows/Android/iOS平台实现RTMP推送和播放端AES或SM4加解密实例

  • 2019 年 10 月 6 日
  • 筆記

1. AES算法和SM4算法扫盲

AES算法

密码学中的高级加密标准(AdvancedEncryptionStandard,AES),又称Rijndael加密算法,是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用。经过五年的甄选流程,高级加密标准由美国国家标准与技术研究院(NIST)于2001年11月26日发布于FIPSPUB197,并在2002年5月26日成为有效的标准。2006年,高级加密标准已然成为对称密钥加密中最流行的算法之一。AES有一个固定的128位的块大小和128,192或256位大小的密钥大小。

该算法为比利时密码学家JoanDaemen和VincentRijmen所设计,结合两位作者的名字,以Rijndael命名之。AES在软件及硬件上都能快速地加解密,相对来说较易于操作,且只需要很少的存储空间。作为一个新的加密标准,目前正被部署应用到更广大的范围。

SM4算法

SM4算法全称为SM4分组密码算法,是国家密码管理局2012年3月发布的第23号公告中公布的密码行业标准。SM4算法是一个分组对称密钥算法,明文、密钥、密文都是16字节,加密和解密密钥相同。加密算法与密钥扩展算法都采用32轮非线性迭代结构。解密过程与加密过程的结构相似,只是轮密钥的使用顺序相反。

SM4算法的优点是软件和硬件实现容易,运算速度快。

2. 接口说明及调用展示

大牛直播SDK (Github) 发布的跨平台(Windows/Android/iOS平台)的基于AES/SM4音视频逐帧数据加密整体解决方案,第三方即便是破解了URL,也没法播放,通过抓包工具抓取到数据,也没法正常显示。

此方案的难点是需要了解音视频编码相关的细节,才能进行适当的扩展。优点是常用的rtmp server可以直接支持,通用性很强。只需要改推送端和播放端就好。

2.1 Windows平台RTMP推送端

C++接口:

		/*  		设置rtmp推送加密选项  		url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  		is_encrypt_video: 1:表示视频加密, 0:表示视频不加密, 默认不加密, 其他值返回错误  		is_encrypt_audio: 1:表示音频加密, 0:表示音频不加密, 默认不加密, 其他值返回错误  		成功返回 NT_ERC_OK  		*/  		NT_UINT32(NT_API *SetRtmpEncryptionOption)(NT_HANDLE handle, NT_PCSTR url, NT_INT32 is_encrypt_video, NT_INT32 is_encrypt_audio);      		/*  		设置rtmp加密算法  		url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  		encryption_algorithm: 加密算法, 当前支持aes和国标sm4. 1为aes, 2为sm4, 默认为aes.  		*/  		NT_UINT32(NT_API *SetRtmpEncryptionAlgorithm)(NT_HANDLE handle, NT_PCSTR url, NT_INT32 encryption_algorithm);      		/*  		设置rtmp推送加密密钥  		url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  		key:加密密钥  		key_size: 如果加密算法是aes, key_size必须是16, 24, 32 这三个值, 其他返回错误; 如果加密算法是sm4, key_size必须是16, 其他值返回错误.  		成功返回 NT_ERC_OK  		*/  		NT_UINT32(NT_API *SetRtmpEncryptionKey)(NT_HANDLE handle, NT_PCSTR url, const NT_BYTE* key, NT_UINT32 key_size);      		/*  		设置rtmp推送加密IV(初始化向量), 这个接口不调用的话, 将使用默认IV  		url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  		iv: 初始化向量  		iv_size: 当前必须是16, 其他值返回错误  		成功返回 NT_ERC_OK  		*/  		NT_UINT32(NT_API *SetRtmpEncryptionIV)(NT_HANDLE handle, NT_PCSTR url, const NT_BYTE* iv, NT_UINT32 iv_size);

C#接口:

        /*           * 设置rtmp推送加密选项           * url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致           * is_encrypt_video: 1:表示视频加密, 0:表示视频不加密, 默认不加密, 其他值返回错误           * is_encrypt_audio: 1:表示音频加密, 0:表示音频不加密, 默认不加密, 其他值返回错误           *           * 成功返回 NT_ERC_OK  		 */          [DllImport(@"SmartPublisherSDK.dll")]  		public static extern UInt32 NT_PB_SetRtmpEncryptionOption(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, Int32 is_encrypt_video, Int32 is_encrypt_audio);      		/*           * 设置rtmp加密算法           * url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致           * encryption_algorithm: 加密算法, 当前支持aes和国标sm4. 1为aes, 2为sm4, 默认为aes.  		 */          [DllImport(@"SmartPublisherSDK.dll")]          public static extern UInt32 NT_PB_SetRtmpEncryptionAlgorithm(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, Int32 encryption_algorithm);      		/*           * 设置rtmp推送加密密钥           * url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致           * key:加密密钥           * key_size: 如果加密算法是aes, key_size必须是16, 24, 32 这三个值, 其他返回错误; 如果加密算法是sm4, key_size必须是16, 其他值返回错误.           * 成功返回 NT_ERC_OK  		 */          [DllImport(@"SmartPublisherSDK.dll")]          public static extern UInt32 NT_PB_SetRtmpEncryptionKey(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, byte[] key, UInt32 key_size);    		/*           * 设置rtmp推送加密IV(初始化向量), 这个接口不调用的话, 将使用默认IV           * url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致           * iv: 初始化向量           * iv_size: 当前必须是16, 其他值返回错误           * 成功返回 NT_ERC_OK  		 */          [DllImport(@"SmartPublisherSDK.dll")]          public static extern UInt32 NT_PB_SetRtmpEncryptionIV(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)]String url, byte[] iv, UInt32 iv_size);

C#调用展示:

				//设置RTMP加密(AES/SM4)                  /*                  Int32 is_encrypt_video = 1;                  Int32 is_encrypt_audio = 1;                  NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionOption(publisher_handle_, url, is_encrypt_video, is_encrypt_audio);                    Int32 encryption_algorithm = 1;                  NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionAlgorithm(publisher_handle_, url, encryption_algorithm);                    String key_str = "1234567890123456";                    UInt32 key_size = 16;                    if (key_str.Length <= 16)                  {                      key_size = 16;                  }                  else if (key_str.Length <= 24)                  {                      key_size = 24;                  }                  else                  {                      key_size = 32;                  }                    byte[] key = new byte[key_size];                    if (key_str.Length <= 32)                  {                      key = System.Text.Encoding.Default.GetBytes(key_str);                  }                  else                  {                      key = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 32));                  }                    NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionKey(publisher_handle_, url, key, key_size);                    String iv_str = "1234567890123456";                    UInt32 iv_size = 16;                    byte[] iv = new byte[iv_size];                    if (iv_str.Length <= 16)                  {                      iv = System.Text.Encoding.Default.GetBytes(iv_str);                  }                  else                  {                      iv = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 16));                  }                    NTSmartPublisherSDK.NT_PB_SetRtmpEncryptionIV(publisher_handle_, url, iv, iv_size);

2.2 Windows平台RTMP播放端

C++接口:

		/*  		*  		* 设置解密key,目前只用来解密rtmp加密流  		* key: 解密密钥  		* size: 密钥长度  		* 成功返回NT_ERC_OK  		*/  		NT_UINT32(NT_API *SetKey)(NT_HANDLE handle, const NT_BYTE* key, NT_UINT32 size);      		/*  		*  		* 设置解密向量,目前只用来解密rtmp加密流  		* iv:  解密向量  		* size: 向量长度  		* 成功返回NT_ERC_OK  		*/  		NT_UINT32(NT_API *SetDecryptionIV)(NT_HANDLE handle, const NT_BYTE* iv, NT_UINT32 size);

C#接口:

        /*           * 设置解密key,目前只用来解密rtmp加密流  		 * key: 解密密钥  		 * size: 密钥长度  		 * 成功返回NT_ERC_OK  		 */          [DllImport(@"SmartPlayerSDK.dll")]          public static extern UInt32 NT_SP_SetKey(IntPtr handle, byte[] key, UInt32 size);    		/*  		 * 设置解密向量,目前只用来解密rtmp加密流  		 * iv:  解密向量  		 * size: 向量长度  		 * 成功返回NT_ERC_OK  		 */          [DllImport(@"SmartPlayerSDK.dll")]          public static extern UInt32 NT_SP_SetDecryptionIV(IntPtr handle, byte[] iv, UInt32 size);

调用展示:

            String key_str = "1234567890123456";                UInt32 key_size = 16;                if (key_str.Length <= 16)              {                  key_size = 16;              }              else if (key_str.Length <= 24)              {                  key_size = 24;              }              else              {                  key_size = 32;              }                byte[] key = new byte[key_size];                if (key_str.Length <= 32)              {                  key = System.Text.Encoding.Default.GetBytes(key_str);              }              else              {                  key = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 32));              }                NTSmartPlayerSDK.NT_SP_SetKey(player_handle_, key, key_size);                String iv_str = "1234567890123456789012345678901211";                UInt32 iv_size = 16;                byte[] iv = new byte[iv_size];                if (iv_str.Length <= 16)              {                  iv = System.Text.Encoding.Default.GetBytes(iv_str);              }              else              {                  iv = System.Text.Encoding.Default.GetBytes(key_str.Substring(0, 16));              }                iv = System.Text.Encoding.Default.GetBytes(iv_str);                NTSmartPlayerSDK.NT_SP_SetDecryptionIV(player_handle_, iv, iv_size);

2.3 Android平台RTMP推送端

	/**  	 * 设置rtmp推送加密选项  	 *  	 * @param url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  	 * @param is_encrypt_video: 1:表示视频加密, 0:表示视频不加密, 默认不加密, 其他值返回错误  	 * @param is_encrypt_audio: 1:表示音频加密, 0:表示音频不加密, 默认不加密, 其他值返回错误  	 *  	 * @return {0} if successful  	 */  	public native int SetRtmpEncryptionOption(long handle,  String url, int is_encrypt_video, int is_encrypt_audio);    	/**  	 * 设置rtmp加密算法  	 *  	 * @param url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  	 * @param encryption_algorithm: 加密算法, 当前支持aes和国标sm4. 1为aes, 2为sm4, 默认为aes.  	 *  	 * @return {0} if successful  	 */  	public native int SetRtmpEncryptionAlgorithm(long handle,  String url, int encryption_algorithm);    	/**  	 * 设置rtmp推送加密密钥  	 *  	 * @param url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  	 * @param key:加密密钥  	 * @param key_size: 当前key_size必须是16, 24, 32 这三个值,其他返回错误  	 *  	 * @return {0} if successful  	 */  	public native int SetRtmpEncryptionKey(long handle, String url, byte[] key, int key_size);    	/**  	 * 设置rtmp推送加密IV(初始化向量), 这个接口不调用的话, 将使用默认IV  	 *  	 * @param url: 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致  	 * @param iv:初始化向量  	 * @param iv_size: 当前必须是16, 其他值返回错误  	 *  	 * @return {0} if successful  	 */  	public native int SetRtmpEncryptionIV(long handle, String url, byte[] iv, int iv_size);

调用展示:

if(encrypt_key != null && !encrypt_key.isEmpty()) {                  Log.i(TAG, "encrypt_key:" + encrypt_key);                    int is_encrypt_video = 1;                  int is_encrypt_audio = 1;                    if (pushType == 1)                  {                      is_encrypt_video = 0;                  }                  else if (pushType == 2)                  {                      is_encrypt_audio = 0;                  }                    libPublisher.SetRtmpEncryptionOption(publisherHandle, publishURL, is_encrypt_video, is_encrypt_audio);                    //加密算法可自行设置                  int encryption_algorithm = 1;                  libPublisher.SetRtmpEncryptionAlgorithm(publisherHandle, publishURL, encryption_algorithm);                    int key_len = 16;                    if (encrypt_key.length() > 16 && encrypt_key.length() <= 24) {                      key_len = 24;                  } else if (encrypt_key.length() > 24) {                      key_len = 32;                  }                    byte[] key = new byte[key_len];                    for (int i = 0; i < key_len; i++) {                      key[i] = 0;                  }                    try {                      byte[] key_utf8 = encrypt_key.getBytes("UTF-8");                        int copy_len = key_utf8.length < key_len ? key_utf8.length : key_len;                        for (int i = 0; i < copy_len; ++i) {                          key[i] = key_utf8[i];                      }                    } catch (UnsupportedEncodingException e) {                      e.printStackTrace();                  }                    int ret = libPublisher.SetRtmpEncryptionKey(publisherHandle, publishURL, key, key.length);                    if(ret != 0)                  {                      Log.e(TAG, "Call SmartPublisherSetRtmpEncryptionKey failed, errorID: " + ret);                  }              }                if(encrypt_iv != null && !encrypt_iv.isEmpty()) {                  int iv_len = 16;                    byte[] iv = new byte[iv_len];                    for (int i = 0; i < iv_len; i++) {                      iv[i] = 0;                  }                    try {                      byte[] iv_utf8 = encrypt_iv.getBytes("UTF-8");                        int copy_len = iv_utf8.length < iv_len ? iv_utf8.length : iv_len;                        for (int i = 0; i < copy_len; ++i) {                          iv[i] = iv_utf8[i];                      }                    } catch (UnsupportedEncodingException e) {                      e.printStackTrace();                  }                    int ret = libPublisher.SetRtmpEncryptionIV(publisherHandle, publishURL, iv, iv.length);                    if(ret != 0)                  {                      Log.e(TAG, "Call SetRtmpEncryptionIV failed, errorID: " + ret);                  }              }

2.4 Android平台RTMP播放端

	/**  	 * 设置解密key,目前只用来解密rtmp加密流  	 *  	 * @param handle: return value from SmartPlayerOpen()  	 *  	 * @param key:解密密钥  	 *  	 * @param size:密钥长度  	 *  	 * @return {0} if successful  	 */  	public native int SmartPlayerSetKey(long handle, byte[] key, int size);    	/**  	 * 设置解密向量,目前只用来解密rtmp加密流  	 *  	 * @param handle: return value from SmartPlayerOpen()  	 *  	 * @param iv:解密向量  	 *  	 * @param size:向量长度  	 *  	 * @return {0} if successful  	 */  	public native int SmartPlayerSetDecryptionIV(long handle, byte[] iv, int size);

调用展示:

        if (encrypt_key != null && !encrypt_key.isEmpty()) {              Log.i(TAG, "encrypt_key:" + encrypt_key);                int key_len = 16;                if (encrypt_key.length() > 16 && encrypt_key.length() <= 24) {                  key_len = 24;              } else if (encrypt_key.length() > 24) {                  key_len = 32;              }                byte[] key = new byte[key_len];                for (int i = 0; i < key_len; i++) {                  key[i] = 0;              }                try {                  byte[] key_utf8 = encrypt_key.getBytes("UTF-8");                    int copy_key_len = key_utf8.length < key_len ? key_utf8.length : key_len;                    for (int i = 0; i < copy_key_len; ++i) {                      key[i] = key_utf8[i];                  }                } catch (UnsupportedEncodingException e) {                  e.printStackTrace();              }                libPlayer.SmartPlayerSetKey(playerHandle, key, key.length);                if (encrypt_iv != null && !encrypt_iv.isEmpty()) {                  Log.i(TAG, "encrypt_iv:" + encrypt_iv);                    int iv_len = 16;                  byte[] iv = new byte[iv_len];                    for (int i = 0; i < iv_len; i++) {                      iv[i] = 0;                  }                    try {                      byte[] iv_utf8 = encrypt_iv.getBytes("UTF-8");                        int copy_iv_len = iv_utf8.length < key_len ? iv_utf8.length : key_len;                        for (int i = 0; i < copy_iv_len; ++i) {                          iv[i] = iv_utf8[i];                      }                    } catch (UnsupportedEncodingException e) {                      e.printStackTrace();                  }                    libPlayer.SmartPlayerSetDecryptionIV(playerHandle, iv, iv.length);              }          }

2.5 iOS平台RTMP推送端

/**   * 设置rtmp推送加密选项   *   * @param url 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致   * @param is_encrypt_video 1:表示视频加密, 0:表示视频不加密, 默认不加密, 其他值返回错误   * @param is_encrypt_audio 1:表示音频加密, 0:表示音频不加密, 默认不加密, 其他值返回错误   *   * @return {0} if successful   */  -(NSInteger)SetRtmpEncryptionOption:(NSString*)url is_encrypt_video:(NSInteger)is_encrypt_video is_encrypt_audio:(NSInteger)is_encrypt_audio;    /**   * 设置rtmp加密算法   *   * @param url 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致   * @param encryption_algorithm 加密算法, 当前支持aes和国标sm4. 1为aes, 2为sm4, 默认为aes.   *   * @return {0} if successful   */  -(NSInteger)SetRtmpEncryptionAlgorithm:(NSString*)url encryption_algorithm:(NSInteger)encryption_algorithm;    /**   * 设置rtmp推送加密密钥   *   * @param url 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致   * @param key 加密密钥   * @param key_size 当前key_size必须是16, 24, 32 这三个值,其他返回错误   *   * @return {0} if successful   */  -(NSInteger)SetRtmpEncryptionKey:(NSString*)url key:(unsigned char*)key key_size:(NSInteger)key_size;    /**   * 设置rtmp推送加密IV(初始化向量), 这个接口不调用的话, 将使用默认IV   *   * @param url 考虑到可能推送到多个服务器,可以根据推送url配置不同的加密选项, 请确保url和SetURL一致   * @param iv 初始化向量   * @param iv_size 当前必须是16, 其他值返回错误   *   * @return {0} if successful   */  -(NSInteger)SetRtmpEncryptionIV:(NSString*)url iv:(unsigned char*)iv iv_size:(NSInteger)iv_size;

调用展示:

    NSInteger key_length = [encrypt_key_ length];        if(key_length > 0)      {          NSInteger is_encrypt_video = 1;          NSInteger is_encrypt_audio = 1;            if(video_opt_ == 0)          {              is_encrypt_video = 0;          }            if(audio_opt_ == 0)          {              is_encrypt_audio = 0;          }            [_smart_publisher_sdk SetRtmpEncryptionOption:rtmp_push_url is_encrypt_video:is_encrypt_video is_encrypt_audio:is_encrypt_audio];            //默认AES加密,如需SM4加密,参数设置2即可          NSInteger encryption_algorithm = 1;          [_smart_publisher_sdk SetRtmpEncryptionAlgorithm:rtmp_push_url encryption_algorithm:encryption_algorithm];            int key_len = 16;            if (key_length > 16 && key_length <= 24) {              key_len = 24;          } else if (key_length > 24) {              key_len = 32;          }            unsigned char key[32];          memset(key, 0, 32);            NSData* key_data = [encrypt_key_ dataUsingEncoding:NSUTF8StringEncoding];            NSInteger copy_key_len = key_length < key_len ? key_length : key_len;            Byte *copy_key_data = (Byte *)[key_data bytes];            for(int i=0;i<copy_key_len;i++)          {              key[i] = copy_key_data[i];          }            [_smart_publisher_sdk SetRtmpEncryptionKey:rtmp_push_url key:key key_size:key_len];            NSInteger iv_length = [encrypt_iv_ length];            if(iv_length > 0)          {              int iv_len = 16;                unsigned char iv[16];              memset(iv, 0, 16);                NSData* iv_data = [encrypt_iv_ dataUsingEncoding:NSUTF8StringEncoding];                NSInteger copy_iv_len = iv_length < iv_len ? iv_length : iv_len;                Byte *copy_iv_data = (Byte *)[iv_data bytes];                for(int i=0;i<copy_iv_len;i++)              {                  iv[i] = copy_iv_data[i];              }                [_smart_publisher_sdk SetRtmpEncryptionIV:rtmp_push_url iv:iv iv_size:iv_len];          }

2.6 iOS平台RTMP播放端

/**   * 设置解密key,目前只用来解密rtmp加密流   *   * @param key 解密密钥   *   * @param key_size 密钥长度   *   * @return {0} if successful   */  - (NSInteger)SmartPlayerSetKey:(unsigned char*)key key_size:(NSInteger)key_size;    /**   * 设置解密向量,目前只用来解密rtmp加密流   *   * @param iv 解密向量   *   * @param iv_size 向量长度   *   * @return {0} if successful   */  - (NSInteger)SmartPlayerSetDecryptionIV:(unsigned char*)iv iv_size:(NSInteger)iv_size;

调用展示:

    NSInteger key_length = [encrypt_key_ length];        if(key_length > 0)      {          int key_len = 16;            if (key_length > 16 && key_length <= 24) {              key_len = 24;          } else if (key_length > 24) {              key_len = 32;          }            unsigned char key[32];          memset(key, 0, 32);            NSData* key_data = [encrypt_key_ dataUsingEncoding:NSUTF8StringEncoding];            NSInteger copy_key_len = key_length < key_len ? key_length : key_len;            Byte *copy_key_data = (Byte *)[key_data bytes];            for(int i=0;i<copy_key_len;i++)          {              key[i] = copy_key_data[i];          }            [_smart_player_sdk SmartPlayerSetKey:key key_size:key_len];      }        NSInteger iv_length = [encrypt_iv_ length];        if(iv_length > 0)      {          int iv_len = 16;            unsigned char iv[16];          memset(iv, 0, 16);            NSData* iv_data = [encrypt_iv_ dataUsingEncoding:NSUTF8StringEncoding];            NSInteger copy_iv_len = iv_length < iv_len ? iv_length : iv_len;            Byte *copy_iv_data = (Byte *)[iv_data bytes];            for(int i=0;i<copy_iv_len;i++)          {              iv[i] = copy_iv_data[i];          }            [_smart_player_sdk SmartPlayerSetDecryptionIV:iv iv_size:iv_len];      }

3.注意事项

1. RTMP推送端什么时候调用加密接口?

回答:SetUrl之后,开始推送之前;

2. RTMP播放端,什么时候设置Key和IV解密向量?

回答:可以实现自动检测,如检测到推送的RTMP流系AES或SM4加密,会回调上来NT_SP_E_EVENT_ID_NEED_KEY事件,弹出输入Key和IV框,如输入的Key和IV不正确,播放端会收到NT_SP_E_EVENT_ID_KEY_ERROR事件

 NT_SP_E_EVENT_ID_NEED_KEY               = NT_SP_E_EVENT_ID_BASE | 0xC,  /*需要输入解密key才能播放*/   NT_SP_E_EVENT_ID_KEY_ERROR              = NT_SP_E_EVENT_ID_BASE | 0xD,  /*解密key不正确*/

3. 设置加解密Key和IV,有什么注意事项?

回答:key_size: 如果加密算法是aes, key_size必须是16, 24, 32 这三个值, 其他返回错误; 如果加密算法是sm4, key_size必须是16, 其他值返回错误;iv_size: 当前必须是16, 其他值返回错误。