前幾天項目用到sm4加密解密,加密爲十六進制字符串,再將十六進制字符串解密。網上百度了下,sm4是密鑰長度和加密明文加密密文都爲16個字節十六進制數據,網上的sm4 c語言算法很容易搜到,筆者剛開始沒怎麼理解,覺得只能對16字節數據進行加密,而且不管是多少字節的數據加密出來都是16字節的。後來看了下源碼,應該是加密的數據應該是16字節或者16的整數倍個字節的數據,若不夠16倍數字節應該補0x00數據,最後加密出來的數據和輸入數據的長度應該一致,即git
密文長度=明文長度 github
並且密鑰長度一致,是16字節的。c的代碼裏面輸入輸出都是十六進制數據,須要將字符串轉爲char類型數組,而且保證長度是16整數倍算法
+(unsigned char*)hexEnc:(NSString*)strInput{ NSData* data = [strInput dataUsingEncoding:NSUTF8StringEncoding]; NSUInteger length = data.length; NSUInteger plusLength; if(length % 16 == 0){ plusLength = 0; } else{ plusLength = 16 - length % 16; } NSMutableString* new_str = [[NSMutableString alloc] initWithString:strInput]; for (int i =0;i < plusLength;i++) { [new_str appendString:@" "]; } NSUInteger new_length = length+plusLength; Uchar *input = (Uchar*)malloc(sizeof(Uchar)*new_length); Uchar *output = (Uchar*)malloc(sizeof(Uchar)*new_length); Uchar key[16] = KEY; const char *utfChar = [new_str UTF8String]; memset(input, 0, new_length); memcpy(input, utfChar, new_length); sm4_context ctx; unsigned long i; sm4_setkey_enc(&ctx,key); sm4_crypt_ecb(&ctx,1,new_length,input,output); for(i=0;i<new_length;i++) printf("%02x ", output[i]); printf("\n"); unsigned char* c_str = Hex2Str(output,new_length); printf("%s\n", c_str); free(input); free(output); return c_str; }
解密時密文是十六進制字符串,須要將字符串先轉爲int類型數組,再做解密操做,具體代碼
+(unsigned char*)hexDec:(NSString*)strInput{ int inputCharSize = strInput.length/2; Uchar* input = (Uchar*)malloc(sizeof(Uchar)*inputCharSize); Uchar* output = (Uchar*)malloc(sizeof(Uchar)*inputCharSize); for (int i = 0; i<inputCharSize; i++) { NSString* str = [strInput substringWithRange:NSMakeRange(i*2, 2)]; NSString* gw = [str substringWithRange:NSMakeRange(0, 1)] ; NSString* dw = [str substringWithRange:NSMakeRange(1, 1)]; int n_gw = [HexToStr str2Int:gw]; int n_dw = [HexToStr str2Int:dw]; int result = n_gw * 16 + n_dw; input[i] = result; } Uchar key[16] = KEY; sm4_context ctx; sm4_setkey_dec(&ctx,key); sm4_crypt_ecb(&ctx,0,inputCharSize,input,output); int kgPos = 0; for(int i=0;i<inputCharSize;i++){ printf("%02x ", output[i]); if (output[i] == 32) { kgPos = i; output[i] = '\0'; } } printf("\n"); free(input); // free(output); return output; }
demo地址:https://github.com/dinner/sm4數組