Windows/Android/iOS平臺實現RTMP推送和播放端AES或SM4加解密實例

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. 接口說明及調用展示

業內首家RTMP整體加解密SDK方案提供商。大牛直播SDK發布的跨平臺(Windows/Android/iOS平臺)的基于AES/SM4音視頻逐幀數據加密整體解決方案,第三方即便是破解了URL,也沒法播放,通過抓包工具抓取到數據,也沒法正常顯示。

此方案的難點是需要了解音視頻編碼相關的細節,才能進行適當的擴展。優點是常用的RTMP Server(如nginx或SRS)或CDN可以直接支持,通用性很強。只需要改推送端和播放端就好。

功能支持:支持AES 128、192、256加解密、支持SM4加解密、支持只加密音頻、視頻、音視頻

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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

            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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

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);
                }
            }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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);

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

        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);
            }
        }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

    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];
        }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

調用展示:

    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];
    }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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不正確*/

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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

回答:key_size: 如果加密算法是aes, key_size必須是16, 24, 32 這三個值, 其他返回錯誤; 如果加密算法是sm4, key_size必須是16, 其他值返回錯誤;iv_size: 當前必須是16, 其他值返回錯誤。

相關資料:Github:?https://github.com/daniulive/SmarterStreaming

年轻人片-年轻人看片-年轻人免费在线看片