AES加解密之C++实现

news/2024/11/8 3:03:01/

一、AES介绍

AES,高级加密标准(AES,Advanced Encryption Standard)为最常见的对称加密算法(微信小程序加密传输就是用这个加密算法的)。对称加密算法也就是加密和解密用相同的密钥,具体的加密流程如下图:在这里插入图片描述
下面简单介绍下各个部分的作用与意义:

明文P

没有经过加密的数据。

密钥K

用来加密明文的密码,在对称加密算法中,加密与解密的密钥是相同的。密钥为接收方与发送方协商产生,但不可以直接在网络上传输,否则会导致密钥泄漏,通常是通过非对称加密算法加密密钥,然后再通过网络传输给对方,或者直接面对面商量密钥。密钥是绝对不可以泄漏的,否则会被攻击者还原密文,窃取机密数据。

AES加密函数

设AES加密函数为E,则 C = E(K, P),其中P为明文,K为密钥,C为密文。也就是说,把明文P和密钥K作为加密函数的参数输入,则加密函数E会输出密文C。

密文C

经加密函数处理后的数据

AES解密函数

设AES解密函数为D,则 P = D(K, C),其中C为密文,K为密钥,P为明文。也就是说,把密文C和密钥K作为解密函数的参数输入,则解密函数会输出明文P。

在这里简单介绍下对称加密算法与非对称加密算法的区别。

对称加密算法

加密和解密用到的密钥是相同的,这种加密方式加密速度非常快,适合经常发送数据的场合。缺点是密钥的传输比较麻烦。

非对称加密算法

加密和解密用的密钥是不同的,这种加密方式是用数学上的难解问题构造的,通常加密解密的速度比较慢,适合偶尔发送数据的场合。优点是密钥传输方便。常见的非对称加密算法为RSA、ECC和EIGamal。

实际中,一般是通过RSA加密AES的密钥,传输到接收方,接收方解密得到AES密钥,然后发送方和接收方用AES密钥来通信。

二、AES结构

AES为分组密码,分组密码也就是把明文分成一组一组的,每组长度相等,每次加密一组数据,直到加密完整个明文。在AES标准规范中,分组长度只能是128位,也就是说,每个分组为16个字节(每个字节8位)。密钥的长度可以使用128位、192位或256位。密钥的长度不同,推荐加密轮数也不同,如下表所示:
|AES 密钥长度(32位比特字) |分组长度(32位比特字) |加密轮数
AES-128 4 4 10
AES-192 6 4 12
AES-256 8 4 14

这里实现的是AES-128,也就是密钥的长度为128位,加密轮数为10轮。
上面说到,AES的加密公式为C = E(K,P),在加密函数E中,会执行一个轮函数,并且执行10次这个轮函数,这个轮函数的前9次执行的操作是一样的,只有第10次有所不同。也就是说,一个明文分组会被加密10轮。AES的核心就是实现一轮中的所有操作。

AES的处理单位是字节,128位的输入明文分组P和输入密钥K都被分成16个字节,分别记为P = P0 P1 … P15 和 K = K0 K1 … K15。如,明文分组为P = abcdefghijklmnop,其中的字符a对应P0,p对应P15。一般地,明文分组用字节为单位的正方形矩阵描述,称为状态矩阵。在算法的每一轮中,状态矩阵的内容不断发生变化,最后的结果作为密文输出。该矩阵中字节的排列顺序为从上到下、从左至右依次排列

解密过程仍为10轮,每一轮的操作是加密操作的逆操作。由于AES的4个轮操作都是可逆的,因此,解密操作的一轮就是顺序执行逆行移位、逆字节代换、轮密钥加和逆列混合。同加密操作类似,最后一轮不执行逆列混合,在第1轮解密之前,要执行1次密钥加操作。

AES的S和逆S盒

AES的字节代换其实就是一个简单的查表操作。AES定义了一个S盒和一个逆S盒,S盒如下:

行/列	0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F
0	0x63	0x7c	0x77	0x7b	0xf2	0x6b	0x6f	0xc5	0x30	0x01	0x67	0x2b	0xfe	0xd7	0xab	0x76
1	0xca	0x82	0xc9	0x7d	0xfa	0x59	0x47	0xf0	0xad	0xd4	0xa2	0xaf	0x9c	0xa4	0x72	0xc0
2	0xb7	0xfd	0x93	0x26	0x36	0x3f	0xf7	0xcc	0x34	0xa5	0xe5	0xf1	0x71	0xd8	0x31	0x15
3	0x04	0xc7	0x23	0xc3	0x18	0x96	0x05	0x9a	0x07	0x12	0x80	0xe2	0xeb	0x27	0xb2	0x75
4	0x09	0x83	0x2c	0x1a	0x1b	0x6e	0x5a	0xa0	0x52	0x3b	0xd6	0xb3	0x29	0xe3	0x2f	0x84
5	0x53	0xd1	0x00	0xed	0x20	0xfc	0xb1	0x5b	0x6a	0xcb	0xbe	0x39	0x4a	0x4c	0x58	0xcf
6	0xd0	0xef	0xaa	0xfb	0x43	0x4d	0x33	0x85	0x45	0xf9	0x02	0x7f	0x50	0x3c	0x9f	0xa8
7	0x51	0xa3	0x40	0x8f	0x92	0x9d	0x38	0xf5	0xbc	0xb6	0xda	0x21	0x10	0xff	0xf3	0xd2
8	0xcd	0x0c	0x13	0xec	0x5f	0x97	0x44	0x17	0xc4	0xa7	0x7e	0x3d	0x64	0x5d	0x19	0x73
9	0x60	0x81	0x4f	0xdc	0x22	0x2a	0x90	0x88	0x46	0xee	0xb8	0x14	0xde	0x5e	0x0b	0xdb
A	0xe0	0x32	0x3a	0x0a	0x49	0x06	0x24	0x5c	0xc2	0xd3	0xac	0x62	0x91	0x95	0xe4	0x79
B	0xe7	0xc8	0x37	0x6d	0x8d	0xd5	0x4e	0xa9	0x6c	0x56	0xf4	0xea	0x65	0x7a	0xae	0x08
C	0xba	0x78	0x25	0x2e	0x1c	0xa6	0xb4	0xc6	0xe8	0xdd	0x74	0x1f	0x4b	0xbd	0x8b	0x8a
D	0x70	0x3e	0xb5	0x66	0x48	0x03	0xf6	0x0e	0x61	0x35	0x57	0xb9	0x86	0xc1	0x1d	0x9e
E	0xe1	0xf8	0x98	0x11	0x69	0xd9	0x8e	0x94	0x9b	0x1e	0x87	0xe9	0xce	0x55	0x28	0xdf
F	0x8c	0xa1	0x89	0x0d	0xbf	0xe6	0x42	0x68	0x41	0x99	0x2d	0x0f	0xb0	0x54	0xbb	0x16

状态矩阵中的元素按照下面的方式映射为一个新的字节:把该字节的高4位作为行值,低4位作为列值,取出S盒或者逆S盒中对应的行的元素作为输出。

逆字节代换也就是查逆S盒来变换,逆S盒如下:

行/列	0	1	2	3	4	5	6	7	8	9	A	B	C	D	E	F
0	0x52	0x09	0x6a	0xd5	0x30	0x36	0xa5	0x38	0xbf	0x40	0xa3	0x9e	0x81	0xf3	0xd7	0xfb
1	0x7c	0xe3	0x39	0x82	0x9b	0x2f	0xff	0x87	0x34	0x8e	0x43	0x44	0xc4	0xde	0xe9	0xcb
2	0x54	0x7b	0x94	0x32	0xa6	0xc2	0x23	0x3d	0xee	0x4c	0x95	0x0b	0x42	0xfa	0xc3	0x4e
3	0x08	0x2e	0xa1	0x66	0x28	0xd9	0x24	0xb2	0x76	0x5b	0xa2	0x49	0x6d	0x8b	0xd1	0x25
4	0x72	0xf8	0xf6	0x64	0x86	0x68	0x98	0x16	0xd4	0xa4	0x5c	0xcc	0x5d	0x65	0xb6	0x92
5	0x6c	0x70	0x48	0x50	0xfd	0xed	0xb9	0xda	0x5e	0x15	0x46	0x57	0xa7	0x8d	0x9d	0x84
6	0x90	0xd8	0xab	0x00	0x8c	0xbc	0xd3	0x0a	0xf7	0xe4	0x58	0x05	0xb8	0xb3	0x45	0x06
7	0xd0	0x2c	0x1e	0x8f	0xca	0x3f	0x0f	0x02	0xc1	0xaf	0xbd	0x03	0x01	0x13	0x8a	0x6b
8	0x3a	0x91	0x11	0x41	0x4f	0x67	0xdc	0xea	0x97	0xf2	0xcf	0xce	0xf0	0xb4	0xe6	0x73
9	0x96	0xac	0x74	0x22	0xe7	0xad	0x35	0x85	0xe2	0xf9	0x37	0xe8	0x1c	0x75	0xdf	0x6e
A	0x47	0xf1	0x1a	0x71	0x1d	0x29	0xc5	0x89	0x6f	0xb7	0x62	0x0e	0xaa	0x18	0xbe	0x1b
B	0xfc	0x56	0x3e	0x4b	0xc6	0xd2	0x79	0x20	0x9a	0xdb	0xc0	0xfe	0x78	0xcd	0x5a	0xf4
C	0x1f	0xdd	0xa8	0x33	0x88	0x07	0xc7	0x31	0xb1	0x12	0x10	0x59	0x27	0x80	0xec	0x5f
D	0x60	0x51	0x7f	0xa9	0x19	0xb5	0x4a	0x0d	0x2d	0xe5	0x7a	0x9f	0x93	0xc9	0x9c	0xef
E	0xa0	0xe0	0x3b	0x4d	0xae	0x2a	0xf5	0xb0	0xc8	0xeb	0xbb	0x3c	0x83	0x53	0x99	0x61
F	0x17	0x2b	0x04	0x7e	0xba	0x77	0xd6	0x26	0xe1	0x69	0x14	0x63	0x55	0x21	0x0c	0x7d

三、实现

说那么多没用,只需要了解对应原理就行,最终还是落在代码的实现上,为了可复用性、模块化和组件化,我依然封装为dll库,提供了如下三个接口:

  1. 秘钥初始化接口
    因为AES是对称加密,加解密用的同一个密码,这里我提供了一个秘钥初始化接口,初始化后加密和解密则使用该秘钥进行加解密。
// ------------------------------------------------------------------------
// Function:
//		Initial Encode or Decoder private key
// Remark:
//      This interface must be invoked before Encode_Data or Decoder_Data
// Parameter:
//      pPrivateKey[in]		:  private key
//		nKeyByteLen[in]		:  private key len
// Return:
//		return 0 if initial success else return -1
// ------------------------------------------------------------------------
AESENCRYPT_API int AES_InitlizeKey(char* pPrivateKey, AESKey nKeyByteLen);

该接口提供了两个参数,指定秘钥信息以及秘钥长度。

  1. 数据加密接口
// ------------------------------------------------------------------------
// Function:
//		Encode source data
// Remark:
//      AES_InitlizeKey must be invoked before invoke AES_Encode_Data
// Parameter:
//      pSrcData[in]		:  not encrypted source data
//		pDestBuf[in]		:  buffer that stored encrypted data
//		nSrcDataLenOrBufLen[in-out]	:
//							   input source data len or the result len,
//							   AES algorithmic does not change the len
//							   of input data len,so the input length equal
//							   result length
// Return:
//		return 0 if initial success else return -1
// ------------------------------------------------------------------------
AESENCRYPT_API long AES_Encode_Data(char* pSrcData, char* pDestBuf, unsigned long  nSrcDataLenOrBufLen);

该接口提供了三个参数,需要加密的文本数据,加密后存放的数据缓存以及缓存长度。

  1. 解密数据接口
// ------------------------------------------------------------------------
// Function:
//		Decode source data
// Remark:
//      AES_InitlizeKey must be invoked before invoke AES_Decode_Data
// Parameter:
//      pSrcEncryptData[in]		:  encrypted source data
//		pDestBuf[in]			:  buffer that stored decoded data
//		nSrcEncryptDataLenOrBufLen[in-out]	:
//							   input encrypted data len or the result len,
//							   AES algorithmic does not change the len
//							   of input data len,so the input length equal
//							   result length
// Return:
//		return 0 if initial success else return -1
// ------------------------------------------------------------------------
AESENCRYPT_API long AES_Decode_Data(char* pSrcEncryptData, char* pDestBuf, unsigned long  nSrcEncryptDataLenOrBufLen);

该接口提供数据解密,第一个参数为需要解密的数据,第二个为解密之后的数据缓存以及数据缓存长度。

加密核心实现

AES是分段多轮加密过程,其核心实现代码如下:

void Cipher(unsigned char* input, unsigned char* output)
{int i = 0;memset(&State[0][0],0,16);// 明文[128bit=16字节=4*4状态举证]状态数据初始化for(i=0;i<4*g_Nb;i++)                             {State[i%4][i/4]=input[i];					}// 轮密钥加[初始轮1加上Nr轮=Nr+1轮=Nr+1轮秘钥数组]AddRoundKey(0);									// 进行Nr-1轮加密,最后一轮不需要列混淆for (int round = 1; round <= g_Nr; round++)  {SubBytes();									//字节代换ShiftRows();								//行移位if(round != g_Nr)MixColumns();							//列混淆AddRoundKey(round);							//轮密钥加}  // 输出加密后的状态数据[加密前明文与加密后明文长度未变化]// 因为它是针对状态数据进行各项复杂操作的for (i = 0; i < (4 * g_Nb); i++){output[i] =  State[i % 4][ i / 4];}}

解密核心实现

解密其实就是一个逆向过程,实现核心代码如下:

void InvCipher(unsigned char* input,unsigned char* output)
{memset(&State[0][0],0,16);for (int i = 0; i < (4 * g_Nb); i++){State[i % 4][ i / 4] = input[i];}AddRoundKey(g_Nr);for (int round = g_Nr-1; round >= 1; round--)  // main round loop{InvShiftRows();InvSubBytes();AddRoundKey(round);InvMixColumns();}  // end main round loop for InvCipherInvShiftRows();InvSubBytes();AddRoundKey(0);// output = statefor (int i = 0; i < (4 * g_Nb); i++){output[i] =  State[i % 4][ i / 4];}
}

相关函数实现

// 轮密钥加
void AddRoundKey(int round)
{// 注: 秘钥块大小为Nk行一共Nr+1轮秘钥Nk为4-6-8大于等于明文矩阵行4//     故而多出秘钥块后面[所有行最后多出的不是每个秘钥块多出的]不参与//     秘钥加运行,Nk的增加也就是秘钥长度的增加只是起了增加轮Nr的作用//     所以每轮的作用行只有4行//							  b0 b4 b8 b12      k0 k1 k2 k3 //							  b0 b4 b8 b12  ^   k4 k5 k6 k7//							  b0 b4 b8 b12      k8 k9 k10k11//							  b0 b4 b8 b12      k12k13k14k15	int i,j;  //i行 j列           //因为密钥w是一列一列排列的,即 k0 k4 k8 k12for(j=0;j<4;j++)			  //							  k1 k5 k9 k13{							  //							  k2 k6 k10k14for(i=0;i<4;i++)		  //							  k3 k7 k11k15{						  // 所以i行j列的下标是4*((round*4)+j)+i即16*round+4*j+iState[i][j]=(unsigned char)((int)State[i][j]^(int)w[4*((round*4)+j)+i]);  }}
}// 字节代换函数
void SubBytes()                              
{int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){State[i][j]=AesSbox[State[i][j]];//因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j]}}
}// 逆字节代换函数
void InvSubBytes()
{int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){State[i][j]=AesiSbox[State[i][j]]; //因为 16*(State[i][j]>>4)+State[i][j]&0x0f=State[i][j]}}
}// 行移位
void ShiftRows()
{unsigned char temp[4*4];                                        //Page105int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){temp[4*i+j]=State[i][j];}}for(i=1;i<4;i++){for(j=0;j<4;j++){if(i==1)State[i][j]=temp[4*i+(j+1)%4];					//第一行左移1位else if(i==2)State[i][j]=temp[4*i+(j+2)%4];				//第二行左移2位else if(i==3)State[i][j]=temp[4*i+(j+3)%4];				//第三行左移3位}}}// 逆行移位
void InvShiftRows()
{unsigned char temp[4*4];int i,j;for(j=0;j<4;j++){for(i=0;i<4;i++){temp[4*i+j]=State[i][j];}}for(i=1;i<4;i++){for(j=0;j<4;j++){//if(i==1)State[i][j]=temp[4*i+(j-1)%4];    在此犯了一个错误 -1%4=-1 而不是3,所以采用了下面再加一个4的做法if(i==1)State[i][j]=temp[4*i+(j+3)%4];			//第一行右移1位 j-1+4=j+3else if(i==2)State[i][j]=temp[4*i+(j+2)%4];		//第二行右移2位 j-2+4=j+2else if(i==3)State[i][j]=temp[4*i+(j+1)%4];		//第三行右移3位 j-3+4=j+2}}}

四、测试

一下提供AES测试代码:

int _tmain(int argc, _TCHAR* argv[])
{// 32byte秘钥(256bit)char* pKey = "12345678123456781234567812345678";AES_InitlizeKey(pKey,AESKey_32);// 需要加密的数据char* pSrc = "dw123456";int nLen = strlen(pSrc);// 加密数据char szBuf[1024] = {0};int nOutLen = AES_Encode_Data(pSrc,szBuf,nLen);cout << "Encrypt source:" << pSrc << endl;cout << "Encrypt Result:" << szBuf << endl;// 将秘钥base分装--传输string strBase64 = Base64Helper::encode((const BYTE*)szBuf, nOutLen);int x = strBase64.length();// 解密秘闻char szUncrypt[1024] = {0};int nUnLen = strlen(szBuf);nOutLen = AES_Decode_Data(szBuf,szUncrypt,nUnLen);cout << "UnEncrypt Result:" << szUncrypt << endl;system("pause");
}

加密和解密测试如下:
在这里插入图片描述
可以看到明文dw123456经过AES加密之后变成了密文,然后又被解密为dw123456

五、文件加解密

加密测试

通过以上封装之后,我们就可以实现对文件的加密和解密了,这里我封装了一个demon,需要加密的原文如下(问题列表):
在这里插入图片描述
我们将使用如下demon进行加密,密码为24字节(192bit)-123456781234567812345678:
在这里插入图片描述
加密完成后生成文件“问题_Encrypt.txt”,密文如下:
在这里插入图片描述

解密测试

通过加密完成之后,文件是基本无法阅读的,所以我们需要用我们的密码解密,我们重新选择输入文件为加密后的密文文件,再次解密:
在这里插入图片描述
解密之后生成文件“问题_Encrypt_Dcrypt.txt”,文件内容如下:
在这里插入图片描述
通过文件内容,我们可以看到密文确实被解密了,核心加密代码如下:

BOOL CFileEncoderDlg::Encrypt(CString strInputFile, CString strKey,CString strDirectory)
{AESKey eKeyType = AESKey_16;if(24 == strKey.GetLength()){eKeyType = AESKey_24;} else if (32 == strKey.GetLength()){eKeyType = AESKey_32;}AES_InitlizeKey((LPTSTR)(LPCTSTR)strKey, eKeyType);TCHAR szTitle[MAX_PATH] = {_T("")};CFileUtil::GetFileTitleEx(strInputFile, szTitle, MAX_PATH);CString strFileName(szTitle);TCHAR szExt[MAX_PATH] = {_T("")};CFileUtil::GetFileExtName(strInputFile, szExt, MAX_PATH);strFileName += _T("_Encrypt.");strFileName += szExt;CString strOutputPath = strDirectory + _T("/");strOutputPath += strFileName;FILE* pFile = fopen((LPTSTR)(LPCTSTR)strInputFile, "rb");if(NULL == pFile){return FALSE;}FILE* pOutputFile = fopen((LPTSTR)(LPCTSTR)strOutputPath, "wb");if(NULL == pOutputFile){fclose(pFile);return FALSE;}while (0 == feof(pFile)){char szBuffer[1024] = {0};int nLen = fread(szBuffer, 1, 1024, pFile);if (nLen > 0){char szEncrypt[1024+16+16] = {0};	// 可能多出16字节加密长度int nEncryptLen = AES_Encode_Data(szBuffer, szEncrypt, nLen);if (nEncryptLen > 0){fwrite(szEncrypt, 1, nEncryptLen, pOutputFile);}}}fclose(pFile);fclose(pOutputFile);return TRUE;
}

核心解码代码如下:

BOOL CFileEncoderDlg::Decrypt(CString strInputFile, CString strKey, CString strDirectory)
{AESKey eKeyType = AESKey_16;if(24 == strKey.GetLength()){eKeyType = AESKey_24;} else if (32 == strKey.GetLength()){eKeyType = AESKey_32;}AES_InitlizeKey((LPTSTR)(LPCTSTR)strKey, eKeyType);TCHAR szTitle[MAX_PATH] = {_T("")};CFileUtil::GetFileTitleEx(strInputFile, szTitle, MAX_PATH);CString strFileName(szTitle);TCHAR szExt[MAX_PATH] = {_T("")};CFileUtil::GetFileExtName(strInputFile, szExt, MAX_PATH);strFileName += _T("_Dcrypt.");strFileName += szExt;CString strOutputPath = strDirectory + _T("/");strOutputPath += strFileName;FILE* pFile = fopen((LPTSTR)(LPCTSTR)strInputFile, "rb");if(NULL == pFile){return FALSE;}FILE* pOutputFile = fopen((LPTSTR)(LPCTSTR)strOutputPath, "wb");if(NULL == pOutputFile){fclose(pFile);return FALSE;}while (0 == feof(pFile)){char szBuffer[1024+16] = {0};int nLen = fread(szBuffer, 1, 1024+16, pFile);if (nLen > 0){char szDcrypt[2048] = {0};int nDcryptLen = AES_Decode_Data(szBuffer, szDcrypt, nLen);if (nDcryptLen > 0){fwrite(szDcrypt, 1, nDcryptLen, pOutputFile);}}}fclose(pFile);fclose(pOutputFile);return TRUE;
}

源码获取、合作、技术交流请获取如下联系方式:
QQ交流群:961179337
在这里插入图片描述

微信账号:lixiang6153
公众号:IT技术快餐
电子邮箱:lixx2048@163.com


http://www.ppmy.cn/news/839559.html

相关文章

大字符串替换

在业务中&#xff0c;字符串格式化处理比较常见&#xff0c;替换也是个很常见的操作。 最近遇到个问题&#xff0c;在处理字符串替换过程中&#xff0c;遇到了out of memory错误。 string text; Dictionary<string, string> dic; foreach (var key in dic.Kesy) {text …

公司监控显示无网络连接服务器,监控显示无网络视频什么原因

大家好&#xff0c;我是时间财富网智能客服时间君&#xff0c;上述问题将由我为大家进行解答。 监控显示无网络视频的原因有&#xff1a;接口接触不良&#xff1b;监视器出现故障&#xff1b;产品不合格&#xff1b;由于电压不稳摄像头被烧坏&#xff1b;设备连接错误&#xff…

安防视频流媒体服务器EasyNVR接入摄像头配置通道显示空白怎么处理?

大家知道我们的流媒体平台EasyNVR能够接入RTSP摄像头&#xff0c;进行网页无插件的视频监控&#xff0c;支持PC/安卓/iOS等主流终端&#xff0c;配置过程也易上手&#xff0c;操作简单。 我们的平台兼容多种浏览器&#xff0c;一般在浏览器内进行配置不会出现不兼容的情况&…

海康大华摄像头接入国标流媒体平台显示设备离线问题解决

发展目标 GB28181协议是由公安部牵头实现的安防行业统一的设备接入、流媒体传输的协议。 国标流媒体解决方案是专门用于接入国标设备的视频解决方案&#xff0c;不但从设备接入层面上&#xff0c;接入了内网或者公网的国标设备&#xff0c;而且在输出层面上&#xff0c;采用了…

IP网络摄像机网页无插件直播视频平台EasyNVR显示license expire的几种原因分析

EasyNVR视频平台是TSINGSEE青犀团队研发的一套视频边缘计算网关&#xff0c;支持对成功接入的摄像机实时视频进行7*24h录像&#xff0c;并且支持录像的检索与回放。最近有用户问EasyNVR系统使用过程中出现“license expire”的提示怎么处理&#xff0c;正好趁这个机会给大家介绍…

IP网络摄像头RTSP协议安防视频可视化平台EasyNVR录像回看没有数据是什么原因?

很多用户在使用TSINGSEE青犀视频云边端架构产品中时&#xff0c;都会碰到录像相关的设置问题&#xff0c;比如使用EasyNVR录像无法开启、录像时间与设置不对应等&#xff0c;但这些问题我们以前都为大家解决过&#xff0c;大多是由于用户对产品功能不熟悉&#xff0c;操作有误造…

宇视摄像机实况画面不清晰排查方法

摄像机安装后&#xff0c;发现画面不清晰怎么办&#xff1f;有可能是相机没有对好焦&#xff0c;此时可尝试进行图像对焦配置。 摄像机网页客户端图像对焦配置步骤 网页客户端配置 第一步&#xff1a;登录相机Web页面。浏览器界面网址栏输入摄像机IP地址&#xff0c;使用用户…

关于EasyNVR视频广场通道不在线也不显示快照的问题排查

EasyNVR流媒体服务支持RTSP稳定拉流接入&#xff0c;支持Onvif协议接入&#xff0c;支持RTMP/HLS/HTTP-FLV等视频流分发&#xff0c;将传统安防监控设备互联化&#xff0c;实现无插件直播。有用户反馈在EasyNVR配置IPC通道后发现通道不在线&#xff0c;也不显示快照&#xff0c…