C++实现AES算法

http://blog.csdn.net/liuyan4794/article/details/8729107


AES.h

[cpp]  view plain copy
  1. #pragma once  
  2. #include"stdafx.h"  
  3.   
  4. #define AES_KEY_ROW_NUMBER 4  
  5. #define AES_KEY_COLUMN_NUMBER 4  
  6. #define AES_ROUND_COUNT 10  
  7.   
  8. class AES  
  9. {  
  10. public:  
  11.     AES(void);  
  12.     AES(BYTE* key);  
  13.     virtual ~AES(void);  
  14.   
  15.     void Encrypt(BYTE *, BYTE *,size_t);  
  16.     void Decrypt(BYTE *, BYTE *,size_t);  
  17.   
  18. private:  
  19.   
  20.     BYTE swapbox[11][4][4];  
  21.   
  22.     BYTE* Cipher(BYTE* input);  
  23.     BYTE* InvCipher(BYTE* input);  
  24.   
  25.     BYTE* Cipher(void * input, size_t length);  
  26.     BYTE* InvCipher(void * input, size_t length);     
  27.   
  28.     void KeyExpansion(BYTE* key, BYTE w[][4][AES_KEY_COLUMN_NUMBER]);  
  29.     BYTE FFmul(BYTE a, BYTE b);  
  30.   
  31.     void SubBytes(BYTE state[][AES_KEY_COLUMN_NUMBER]);  
  32.     void ShiftRows(BYTE state[][AES_KEY_COLUMN_NUMBER]);  
  33.     void MixColumns(BYTE state[][AES_KEY_COLUMN_NUMBER]);  
  34.     void AddRoundKey(BYTE state[][AES_KEY_COLUMN_NUMBER], BYTE k[][AES_KEY_COLUMN_NUMBER]);  
  35.   
  36.     void InvSubBytes(BYTE state[][AES_KEY_COLUMN_NUMBER]);  
  37.     void InvShiftRows(BYTE state[][AES_KEY_COLUMN_NUMBER]);  
  38.     void InvMixColumns(BYTE state[][AES_KEY_COLUMN_NUMBER]);  
  39.   
  40.   
  41. };  

AES.cpp

[cpp]  view plain copy
  1. #include"stdafx.h"  
  2. #include"AES.h"  
  3. #include<stdlib.h>  
  4. #include<memory.h>  
  5.   
  6. //permutebox  
  7. static unsigned char permutebox[] =  
  8. /*  0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f */  
  9.     0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76, /*0*/  
  10.     0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0, /*1*/  
  11.     0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15, /*2*/  
  12.     0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75, /*3*/  
  13.     0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84, /*4*/  
  14.     0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf, /*5*/  
  15.     0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8, /*6*/  
  16.     0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2, /*7*/  
  17.     0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73, /*8*/  
  18.     0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb, /*9*/  
  19.     0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79, /*a*/  
  20.     0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08, /*b*/  
  21.     0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a, /*c*/  
  22.     0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e, /*d*/  
  23.     0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf, /*e*/  
  24.     0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16  /*f*/  
  25. };  
  26. //inversepermutationbox  
  27. static  unsigned char inversepermutationbox[]=   
  28. /*  0    1    2    3    4    5    6    7    8    9    a    b    c    d    e    f  */  
  29.     0x52,0x09,0x6a,0xd5,0x30,0x36,0xa5,0x38,0xbf,0x40,0xa3,0x9e,0x81,0xf3,0xd7,0xfb, /*0*/  
  30.     0x7c,0xe3,0x39,0x82,0x9b,0x2f,0xff,0x87,0x34,0x8e,0x43,0x44,0xc4,0xde,0xe9,0xcb, /*1*/  
  31.     0x54,0x7b,0x94,0x32,0xa6,0xc2,0x23,0x3d,0xee,0x4c,0x95,0x0b,0x42,0xfa,0xc3,0x4e, /*2*/  
  32.     0x08,0x2e,0xa1,0x66,0x28,0xd9,0x24,0xb2,0x76,0x5b,0xa2,0x49,0x6d,0x8b,0xd1,0x25, /*3*/  
  33.     0x72,0xf8,0xf6,0x64,0x86,0x68,0x98,0x16,0xd4,0xa4,0x5c,0xcc,0x5d,0x65,0xb6,0x92, /*4*/  
  34.     0x6c,0x70,0x48,0x50,0xfd,0xed,0xb9,0xda,0x5e,0x15,0x46,0x57,0xa7,0x8d,0x9d,0x84, /*5*/  
  35.     0x90,0xd8,0xab,0x00,0x8c,0xbc,0xd3,0x0a,0xf7,0xe4,0x58,0x05,0xb8,0xb3,0x45,0x06, /*6*/  
  36.     0xd0,0x2c,0x1e,0x8f,0xca,0x3f,0x0f,0x02,0xc1,0xaf,0xbd,0x03,0x01,0x13,0x8a,0x6b, /*7*/  
  37.     0x3a,0x91,0x11,0x41,0x4f,0x67,0xdc,0xea,0x97,0xf2,0xcf,0xce,0xf0,0xb4,0xe6,0x73, /*8*/  
  38.     0x96,0xac,0x74,0x22,0xe7,0xad,0x35,0x85,0xe2,0xf9,0x37,0xe8,0x1c,0x75,0xdf,0x6e, /*9*/  
  39.     0x47,0xf1,0x1a,0x71,0x1d,0x29,0xc5,0x89,0x6f,0xb7,0x62,0x0e,0xaa,0x18,0xbe,0x1b, /*a*/  
  40.     0xfc,0x56,0x3e,0x4b,0xc6,0xd2,0x79,0x20,0x9a,0xdb,0xc0,0xfe,0x78,0xcd,0x5a,0xf4, /*b*/  
  41.     0x1f,0xdd,0xa8,0x33,0x88,0x07,0xc7,0x31,0xb1,0x12,0x10,0x59,0x27,0x80,0xec,0x5f, /*c*/  
  42.     0x60,0x51,0x7f,0xa9,0x19,0xb5,0x4a,0x0d,0x2d,0xe5,0x7a,0x9f,0x93,0xc9,0x9c,0xef, /*d*/  
  43.     0xa0,0xe0,0x3b,0x4d,0xae,0x2a,0xf5,0xb0,0xc8,0xeb,0xbb,0x3c,0x83,0x53,0x99,0x61, /*e*/  
  44.     0x17,0x2b,0x04,0x7e,0xba,0x77,0xd6,0x26,0xe1,0x69,0x14,0x63,0x55,0x21,0x0c,0x7d  /*f*/  
  45. };   
  46.   
  47.   
  48.   
  49. AES::AES(void)  
  50. {  
  51. }  
  52. AES::AES(unsigned char* key)   
  53. {  
  54.     KeyExpansion(key, swapbox);  
  55. }  
  56.   
  57. AES::~AES(void)  
  58. {  
  59. }  
  60.   
  61. /************************************************************************/  
  62. /* create a Encrypt method                                              */  
  63. /* param : data     encrypt data                                        */  
  64. /* param :encryptArrayencryptArray                                   */  
  65. /* param :len encrypt data length                                      */  
  66. /* return : void                                                        */  
  67. /************************************************************************/  
  68.   
  69. void AES::Encrypt(unsigned char* data ,unsigned char * encryptArray,size_t len)  
  70. {  
  71.     memcpy(encryptArray,data,len);  
  72.     Cipher((void *)encryptArray,len);  
  73.   
  74. }  
  75.   
  76. /************************************************************************/  
  77. /* create a Decrypt method                                              */  
  78. /* param : data     decrypt data                                        */  
  79. /* param :decryptArraydecryptArray                                   */  
  80. /* param :len decrypt data length                                      */  
  81. /* return : void                                                        */  
  82. /************************************************************************/  
  83.   
  84. void AES::Decrypt(unsigned char * data,unsigned char * decryptArray,size_t len)  
  85. {     
  86.     memcpy(decryptArray,data,len);  
  87.     InvCipher((void *)decryptArray,len);  
  88. }  
  89.   
  90. /************************************************************************/  
  91. /* create a Cipher  method  only one time  Encrypt                      */  
  92. /* param : input     input encrypt data                                 */  
  93. /* return : unsigned char *                                             */  
  94. /************************************************************************/  
  95.   
  96. unsigned char* AES::Cipher(unsigned char* input)  
  97. {  
  98.   
  99.     unsigned char state[AES_KEY_ROW_NUMBER][AES_KEY_COLUMN_NUMBER];  
  100.     int i,r,c;  
  101.   
  102.     for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  103.     {  
  104.         for(c=0; c<AES_KEY_COLUMN_NUMBER ;c++)  
  105.         {  
  106.             state[r][c] = input[c*AES_KEY_COLUMN_NUMBER+r];  
  107.         }  
  108.     }  
  109.   
  110.     AddRoundKey(state,swapbox[0]);  
  111.   
  112.     for(i=1; i<=AES_ROUND_COUNT; i++)  
  113.     {  
  114.         SubBytes(state);  
  115.         ShiftRows(state);  
  116.         if(i!=AES_ROUND_COUNT)MixColumns(state);  
  117.         AddRoundKey(state,swapbox[i]);  
  118.     }  
  119.   
  120.     for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  121.     {  
  122.         for(c=0; c<AES_KEY_COLUMN_NUMBER ;c++)  
  123.         {  
  124.             input[c*AES_KEY_COLUMN_NUMBER+r] = state[r][c];  
  125.         }  
  126.     }  
  127.     return input;  
  128. }  
  129. /************************************************************************/  
  130. /* create a InvCipher  method  only one time  decrypt                   */  
  131. /* param : input     input decrypt data                                 */  
  132. /* return : unsigned char *                                             */  
  133. /************************************************************************/  
  134. unsigned char* AES::InvCipher(unsigned char* input)  
  135. {  
  136.     unsigned char state[AES_KEY_ROW_NUMBER][AES_KEY_COLUMN_NUMBER];  
  137.     int i,r,c;  
  138.   
  139.     for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  140.     {  
  141.         for(c=0; c<AES_KEY_COLUMN_NUMBER ;c++)  
  142.         {  
  143.             state[r][c] = input[c*AES_KEY_COLUMN_NUMBER+r];  
  144.         }  
  145.     }  
  146.   
  147.     AddRoundKey(state, swapbox[10]);  
  148.     for(i=9; i>=0; i--)  
  149.     {  
  150.         InvShiftRows(state);  
  151.         InvSubBytes(state);  
  152.         AddRoundKey(state, swapbox[i]);  
  153.         if(i)  
  154.         {  
  155.             InvMixColumns(state);  
  156.         }  
  157.     }     
  158.     for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  159.     {  
  160.         for(c=0; c<AES_KEY_COLUMN_NUMBER ;c++)  
  161.         {  
  162.             input[c*AES_KEY_COLUMN_NUMBER+r] = state[r][c];  
  163.         }  
  164.     }  
  165.     return input;  
  166. }  
  167. /************************************************************************/  
  168. /* Create a specified length of data encryption method                  */  
  169. /* param : input     input data encryption                              */  
  170. /* param : length    Input the length of the encrypted data             */  
  171. /* return : unsigned char *                                             */  
  172. /************************************************************************/  
  173. unsigned char* AES::Cipher(void * input, size_t length)  
  174. {  
  175.     unsigned char* in = (unsigned char*) input;  
  176.     size_t i;  
  177.     if(!length)  
  178.     {  
  179.         while(*(in+length++));  
  180.         in = (unsigned char*) input;  
  181.     }  
  182.     for(i=0; i<length; i+=16)  
  183.     {  
  184.         Cipher(in+i);  
  185.     }  
  186.     return (unsigned char*)input;  
  187. }  
  188. /************************************************************************/  
  189. /* Create a specified length of InvCipher method                        */  
  190. /* param : input     input data InvCipher                               */  
  191. /* param : length    Input the length of the InvCipher data             */  
  192. /* return : unsigned char *                                             */  
  193. /************************************************************************/  
  194. unsigned char* AES::InvCipher(void * input, size_t length)  
  195. {  
  196.     unsigned char* in = (unsigned char*) input;  
  197.     size_t i;  
  198.     for(i=0; i<length; i+=16)  
  199.     {  
  200.         InvCipher(in+i);  
  201.     }  
  202.     return (unsigned char*)input;  
  203. }  
  204. /************************************************************************/  
  205. /*Create key method                                                     */  
  206. /* param : key      input data encryption key                           */  
  207. /* param :swapbox  Conversion of key array                             */  
  208. /* return : void                                                        */  
  209. /************************************************************************/  
  210. void AES::KeyExpansion(unsigned char* key, unsigned char swapbox[][4][4])  
  211. {  
  212.     int i,j,r,c;  
  213.     unsigned char rc[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};  
  214.     for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  215.     {  
  216.         for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  217.         {  
  218.             swapbox[0][r][c] = key[r+c*AES_KEY_COLUMN_NUMBER];  
  219.         }  
  220.     }  
  221.     for(i=1; i<=10; i++)  
  222.     {  
  223.         for(j=0; j<AES_KEY_COLUMN_NUMBER; j++)  
  224.         {  
  225.             unsigned char t[AES_KEY_ROW_NUMBER];  
  226.             for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  227.             {  
  228.                 t[r] = j ? swapbox[i][r][j-1] : swapbox[i-1][r][3];  
  229.             }  
  230.             if(j == 0)  
  231.             {  
  232.                 unsigned char temp = t[0];  
  233.                 for(r=0; r<AES_KEY_ROW_NUMBER-1; r++)  
  234.                 {  
  235.                     t[r] = permutebox[t[(r+1)%AES_KEY_ROW_NUMBER]];  
  236.                 }  
  237.                 t[3] = permutebox[temp];  
  238.                 t[0] ^= rc[i-1];  
  239.             }  
  240.             for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  241.             {  
  242.                 swapbox[i][r][j] = swapbox[i-1][r][j] ^ t[r];  
  243.             }  
  244.         }  
  245.     }  
  246. }  
  247.   
  248. /************************************************************************/  
  249. /*Create mixed operation method ranks                                   */  
  250. /* param : a      row  char                                             */  
  251. /* param : b      column  char                                          */  
  252. /* return : unsigned char                                               */  
  253. /************************************************************************/  
  254.   
  255. unsigned char AES::FFmul(unsigned char a, unsigned char b)  
  256. {  
  257.     unsigned char bw[AES_KEY_ROW_NUMBER];  
  258.     unsigned char res=0;  
  259.     int i;  
  260.     bw[0] = b;  
  261.     for(i=1; i<AES_KEY_ROW_NUMBER; i++)  
  262.     {  
  263.         bw[i] = bw[i-1]<<1;  
  264.         if(bw[i-1]&0x80)  
  265.         {  
  266.             bw[i]^=0x1b;  
  267.         }  
  268.     }  
  269.     for(i=0; i<AES_KEY_ROW_NUMBER; i++)  
  270.     {  
  271.         if((a>>i)&0x01)  
  272.         {  
  273.             res ^= bw[i];  
  274.         }  
  275.     }  
  276.     return res;  
  277. }  
  278. /************************************************************************/  
  279. /* Create bytes alternatives                                            */  
  280. /* param :  state[][]  Byte array alternative                           */  
  281. /* return : void                                                        */  
  282. /************************************************************************/  
  283. void AES::SubBytes(unsigned char state[][AES_KEY_COLUMN_NUMBER])  
  284. {  
  285.     int r,c;  
  286.     for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  287.     {  
  288.         for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  289.         {  
  290.             state[r][c] = permutebox[state[r][c]];  
  291.         }  
  292.     }  
  293. }  
  294. /************************************************************************/  
  295. /* Create rows transform method                                         */  
  296. /* param :  state[][]  line array alternative                           */  
  297. /* return : void                                                        */  
  298. /************************************************************************/  
  299. void AES::ShiftRows(unsigned char state[][AES_KEY_COLUMN_NUMBER])  
  300. {  
  301.     unsigned char t[AES_KEY_COLUMN_NUMBER];  
  302.     int r,c;  
  303.     for(r=1; r<AES_KEY_ROW_NUMBER; r++)  
  304.     {  
  305.         for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  306.         {  
  307.             t[c] = state[r][(c+r)%AES_KEY_COLUMN_NUMBER];  
  308.         }  
  309.         for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  310.         {  
  311.             state[r][c] = t[c];  
  312.         }  
  313.     }  
  314. }  
  315. /************************************************************************/  
  316. /* Create columns transform method                                      */  
  317. /* param :  state[][]  columns array alternative                        */  
  318. /* return : void                                                        */  
  319. /************************************************************************/  
  320. void AES::MixColumns(unsigned char state[][AES_KEY_COLUMN_NUMBER])  
  321. {  
  322.     unsigned char t[AES_KEY_ROW_NUMBER];  
  323.     int r,c;  
  324.     for(c=0; c< AES_KEY_COLUMN_NUMBER; c++)  
  325.     {  
  326.         for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  327.         {  
  328.             t[r] = state[r][c];  
  329.         }  
  330.         for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  331.         {  
  332.             state[r][c] = FFmul(0x02, t[r])  
  333.                 ^ FFmul(0x03, t[(r+1)%AES_KEY_COLUMN_NUMBER])  
  334.                 ^ FFmul(0x01, t[(r+2)%AES_KEY_COLUMN_NUMBER])  
  335.                 ^ FFmul(0x01, t[(r+3)%AES_KEY_COLUMN_NUMBER]);  
  336.         }  
  337.     }  
  338. }  
  339.   
  340. /************************************************************************/  
  341. /*Create round keys plus transform method                               */  
  342. /* param :  state[][]  keys plus array alternative                      */  
  343. /* param :  k[][]  temp array alternative                               */  
  344. /* return : void                                                        */  
  345. /************************************************************************/  
  346. void AES::AddRoundKey(unsigned char state[][AES_KEY_COLUMN_NUMBER], unsigned char k[][AES_KEY_COLUMN_NUMBER])  
  347. {  
  348.     int r,c;  
  349.     for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  350.     {  
  351.         for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  352.         {  
  353.             state[r][c] ^= k[r][c];  
  354.         }  
  355.     }  
  356. }  
  357. /************************************************************************/  
  358. /* CreateInvSubBytes alternatives                                      */  
  359. /* param :  state[][]  InvSubBytes array alternative                    */  
  360. /* return : void                                                        */  
  361. /************************************************************************/  
  362. void AES::InvSubBytes(unsigned char state[][AES_KEY_COLUMN_NUMBER])  
  363. {  
  364.     int r,c;  
  365.     for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  366.     {  
  367.         for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  368.         {  
  369.             state[r][c] = inversepermutationbox[state[r][c]];  
  370.         }  
  371.     }  
  372. }  
  373. /************************************************************************/  
  374. /* CreateInvShiftRows transform method                                 */  
  375. /* param :  state[][]  InvShiftRows array alternative                   */  
  376. /* return : void                                                        */  
  377. /************************************************************************/  
  378. void AES::InvShiftRows(unsigned char state[][AES_KEY_COLUMN_NUMBER])  
  379. {  
  380.     unsigned char t[AES_KEY_COLUMN_NUMBER];  
  381.     int r,c;  
  382.     for(r=1; r<AES_KEY_ROW_NUMBER; r++)  
  383.     {  
  384.         for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  385.         {  
  386.             t[c] = state[r][(c-r+AES_KEY_COLUMN_NUMBER)%AES_KEY_COLUMN_NUMBER];  
  387.         }  
  388.         for(c=0; c<AES_KEY_COLUMN_NUMBER; c++)  
  389.         {  
  390.             state[r][c] = t[c];  
  391.         }  
  392.     }  
  393. }  
  394. /************************************************************************/  
  395. /* CreateInvMixColumns transform method                                */  
  396. /* param :  state[][]  InvMixColumns array alternative                  */  
  397. /* return : void                                                        */  
  398. /************************************************************************/  
  399. void AES::InvMixColumns(unsigned char state[][AES_KEY_COLUMN_NUMBER])  
  400. {  
  401.     unsigned char t[AES_KEY_ROW_NUMBER];  
  402.     int r,c;  
  403.     for(c=0; c< AES_KEY_COLUMN_NUMBER; c++)  
  404.     {  
  405.         for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  406.         {  
  407.             t[r] = state[r][c];  
  408.         }  
  409.         for(r=0; r<AES_KEY_ROW_NUMBER; r++)  
  410.         {  
  411.             state[r][c] = FFmul(0x0e, t[r])  
  412.                 ^ FFmul(0x0b, t[(r+1)%AES_KEY_ROW_NUMBER])  
  413.                 ^ FFmul(0x0d, t[(r+2)%AES_KEY_ROW_NUMBER])  
  414.                 ^ FFmul(0x09, t[(r+3)%AES_KEY_ROW_NUMBER]);  
  415.         }  
  416.     }  
  417. }  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值