int HDDEV::UnPackResponseStruct(HD8583STRUCT& resp,MESSAGETYPE* msg_type, void* buf,size_t buflen) { short datalen; HDISO8583Msg msg; char * input = (char*)buf; BUF_2_SHORT(datalen,input); if(datalen > buflen - 2) return -1; *msg_type = (MESSAGETYPE)(input[2] & 0xFF); unsigned char zero[2] = {0x00,0x00}; if(msg.Unpack(resp,input+3,datalen-1) > 0) { // 比较 MAC 地址 if(ACE_OS::memcmp(resp->mac,zero,2)) { // 2 byte 长度, 2 byte mac 码 unsigned short i = GenerateCRC16((unsigned char*)input+2,buflen-4); unsigned char tmp[4] = ""; SHORT_2_BUF(i,tmp); /*tmp[0] = (unsigned char)((i & 0xFF00) >> 8); tmp[1] = (unsigned char)(i & 0xFF);*/ tmp[2] = tmp[0]; tmp[0] = tmp[1]; tmp[1] = tmp[2]; for(int i = 0; i < 2; ++i) for(int j = 0; j < 4; ++j) tmp[i] ^= KsgGetGateway()->GetConfig()->_workKey[i+j*2]; return (ACE_OS::memcmp(resp->mac,tmp,2) == 0) ? 0 : -1; } return 0; } return -1; }
size_t HDDEV::PackRequestStruct(HD8583STRUCT& req,MESSAGETYPE msg_type ,void* buf,size_t maxlen,bool with_crc ) { HDISO8583Msg msg; char * output = (char*)buf; char * bitmap = output+3; size_t packlen = msg.Pack(req,output+3,maxlen-3); if(packlen <= 0) return 0; output[2] = (char)msg_type; packlen++; if(with_crc) { bitmap[FIELD_MACOFBASALBITMAP/8] |= 1 << (7 - FIELD_MACOFBASALBITMAP % 8); unsigned short i = GenerateCRC16((unsigned char*)output+2,static_cast<uint16>(packlen)); output[packlen+3] = i % 0x100; output[packlen+2] = i / 0x100; for(i = 0; i < 4; ++i) { output[packlen+2] ^= KsgGetGateway()->GetConfig()->_workKey[i*2]; output[packlen+3] ^= KsgGetGateway()->GetConfig()->_workKey[i*2+1]; } packlen+=2; } short tmp = static_cast<short>(packlen); SHORT_2_BUF(tmp,output); return packlen+2; }
int HDDEV::HDParsePosRecord(BYTE* buf,TRADERECORDSTRUCT* trade) { BUF_2_INT(trade->CardNumber,buf); BUF_2_INT(trade->Balance,buf+4); BUF_2_INT(trade->Amount,buf+8); trade->Year = *(buf+12); trade->Month = *(buf+13); trade->Day = *(buf+14); trade->Hour = *(buf+15); trade->Minute = *(buf+16); trade->Second = *(buf+17); BUF_2_SHORT(trade->TraceOfEW,buf+18); BUF_2_INT(trade->TraceOfPOS,buf+20); BUF_2_INT(trade->OrgTransTrace,buf+24); BUF_2_INT(trade->OperatorID,buf+28); BUF_2_INT(trade->TerminalSN,buf+32); // 终端号 BUF_2_SHORT(trade->AdditionalMoney,buf+36); // 管理费 BUF_2_SHORT(trade->GoodsNumber,buf+38); trade->IndexOfEW = *(buf+40); if(trade->IndexOfEW > 0) trade->IndexOfEW--; trade->RecordType = *(buf+41); trade->ConsumeMode = *(buf+42); memcpy(trade->MAC,buf+43,4); uint16 i = GenerateCRC16(buf,43); unsigned char tmp[4] = ""; SHORT_2_BUF(i,tmp); /*tmp[0] = (unsigned char)((i & 0xFF00) >> 8); tmp[1] = (unsigned char)(i & 0xFF);*/ tmp[2] = tmp[0]; tmp[0] = tmp[1]; tmp[1] = tmp[2]; for(int i = 0; i < 2; ++i) for(int j = 0; j < 4; ++j) tmp[i] ^= KsgGetGateway()->GetConfig()->_workKey[i+j*2]; return (ACE_OS::memcmp(trade->MAC,tmp,2) == 0) ? 0 : -1; /*if( (i & 0xFF) != trade->MAC[1] || ((i & 0xFF00)>>8) != trade->MAC[0]) return -1; return 0; */ }
int __stdcall decrypt_elec_card_pwd(int cut_id,const char seedkey[32],const char mpwd[64],char pwd[8]) { char temp[17],temp1[17],buf[17]; char encrypt_seed[65]; unsigned char radom_seed[4]; keyInstance key_inst; cipherInstance cipher_inst; int i,len; static const int max_pwd_len = 8; memset(&key_inst,0,sizeof key_inst); memset(&cipher_inst,0,sizeof cipher_inst); // 读取随机种子 memcpy(temp,mpwd,8); memset(temp1,0,sizeof temp1); for(i = 0;i < 8;i+=2) { memcpy(temp1,temp+i,2); radom_seed[i/2] = (unsigned char)strtoul(temp1,NULL,16); } // 计算种子密钥 memset(encrypt_seed,0,sizeof encrypt_seed); for(i = 0;i < 32;++i) encrypt_seed[i] = seedkey[i] ^ radom_seed[i%4]; CalcMD5((unsigned char*)encrypt_seed,32,(unsigned char*)temp); memset(encrypt_seed,0,sizeof encrypt_seed); for(i = 0; i < 16 ;++i) sprintf(encrypt_seed+i*2,"%02X",(unsigned char)temp[i]); // 解密 if(makeKey(&key_inst,DIR_DECRYPT,128,(char*)encrypt_seed)==FALSE) { return -1; } if(cipherInit(&cipher_inst,MODE_CBC,NULL)==FALSE) { return -1; } memset(temp1,0,sizeof temp1); memset(temp,0,sizeof temp); for(i = 0;i < 32; i+=2) { memcpy(temp1,mpwd+12+i,2); temp[i/2] = (unsigned char)strtoul(temp1,NULL,16); } memset(temp1,0,sizeof temp1); len = blockDecrypt(&cipher_inst,&key_inst,(BYTE*)temp,16*8,(BYTE*)temp1); for(i=0;i < max_pwd_len;++i) buf[i] = temp1[i] ^ radom_seed[i%4]; // 计算密码 sprintf(temp,"%08X",cut_id); for(i = 0;i < max_pwd_len;++i) temp1[i] = temp1[i] ^ temp[i]; // CRC 校验 uint16 crc = GenerateCRC16((unsigned char*)temp1,max_pwd_len); memset(temp,0,sizeof temp); sprintf(temp,"%04X",crc); if(strncmp(temp,mpwd+8,4)) { return -2; } memcpy(pwd,buf,max_pwd_len); //memcpy(pwd,temp1,max_pwd_len); return 0; }
int __stdcall encrypt_elec_card_pwd(int cut_id,const char seedkey[32],const char pwd[8],char mpwd[64]) { static const int max_pwd_len = 8; keyInstance key_inst; cipherInstance cipher_inst; unsigned char buf[16] = ""; char temp[16] = ""; char temp2[16] = ""; char pwd_str[max_pwd_len*2+1] = ""; unsigned char decrypt_buf[16] = ""; char encrypt_seedkey[64] = ""; unsigned char decrypt_str[64] = ""; time_t radom_seed = time(NULL); int len,i,j,pwd_len; memset(&key_inst,0,sizeof key_inst); memset(&cipher_inst,0,sizeof cipher_inst); for(i = 0;i < max_pwd_len;++i) { switch(pwd[i]) { case ' ': case '\t': case '\r': case '\n': case '\'': case '"': case '%': case '_': return -2; default: break; } } pwd_len = strlen(pwd); if(pwd_len > max_pwd_len) return -3; // 取4位随机种子 srand((unsigned int)radom_seed); for(i = 0;i < 4;++i) buf[i] = (unsigned char)(rand() % 0xFF); // 密码不足8位右补空格 memcpy(pwd_str,pwd,pwd_len); for(i=pwd_len;i < max_pwd_len;++i) pwd_str[pwd_len] = ' '; for(i=0;i < max_pwd_len;++i) pwd_str[i] ^= buf[i%4]; // 加密的密钥 for(i = 0;i < max_pwd_len;++i) pwd_str[max_pwd_len+i] = pwd_str[i] | (!temp[i]); memcpy(pwd_str+max_pwd_len,pwd_str,max_pwd_len); // 计算种子密钥 memset(encrypt_seedkey,0,sizeof encrypt_seedkey); for(i = 0; i < 32 ;++i) encrypt_seedkey[i] = seedkey[i] ^ buf[i%4]; CalcMD5((unsigned char*)encrypt_seedkey,32,(unsigned char*)temp); memset(encrypt_seedkey,0,sizeof encrypt_seedkey); for(i = 0,j = 0;i < 16; ++i) j += sprintf(encrypt_seedkey+j,"%02X",(unsigned char)temp[i]); // 计算CRC sprintf(temp,"%08X",cut_id); memset(temp2,0,sizeof temp2); for(i = 0;i < max_pwd_len;++i) temp2[i] = pwd_str[i] ^ temp[i]; uint16 crc = GenerateCRC16((unsigned char *)temp2,max_pwd_len); sprintf(temp,"%04X",crc); memcpy(buf+4,temp,4); // 进行加密 if(makeKey(&key_inst,DIR_ENCRYPT,128,encrypt_seedkey)==FALSE) { return -1; } if(cipherInit(&cipher_inst,MODE_CBC,NULL)==FALSE) { return -1; } len = blockEncrypt(&cipher_inst,&key_inst,(unsigned char*)pwd_str,16*8,decrypt_str); if(len == 16*8) { // 8 个字符种子 for(i = 0;i < 4; ++i) sprintf(mpwd+i*2,"%02X",(unsigned char)buf[i]); // 4 个字符CRC memcpy(mpwd+8,temp,4); // 8 个字符密码 for(i = 0;i < 16;++i) sprintf(mpwd+12+i*2,"%02X",decrypt_str[i]); //mpwd[28] = '\0'; return 0; } return -1; }
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow) { MSG msg; WINDOWPLACEMENT w; BOOL bQuit = FALSE; InitCommonControls(); hInst = hInstance; // Find location of configuration file ConfigInit(); /* Register our custom classes */ RegisterWindowClasses(); hMain = CreateWindow(szAppName, /* window class name */ szAppName, /* window caption */ WS_OVERLAPPEDWINDOW, /* window style */ 0, 0, 0, 0, /* initially zero size; changed below */ NULL, /* parent window handle */ NULL, /* window menu handle */ hInstance, /* program instance handle */ NULL); /* creation parameters */ if (!hMain) { char buf[256]; DWORD err = GetLastError(); sprintf(buf, "Error - Couldn't Create Client Window : %d", err); MessageBox(NULL, buf, "ERROR!", MB_OK); MainQuit(hMain); exit(1); } if (config.debug) CreateDebugWindow(); if (lpszCmdParam && strlen(lpszCmdParam) > 0) ConfigOverride(lpszCmdParam); w.length = sizeof(WINDOWPLACEMENT); WindowSettingsLoad(&w); SetWindowPlacement(hMain, &w); D3DRenderInit(hMain); ModulesInit(); // Set up data structures for modules /* attempt make a crc16 on the meridian.exe */ GenerateCRC16(); MainInitState(STATE_OFFLINE); UpdateWindow(hMain); while (!bQuit) { MainIdle(); while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (!GetMessage(&msg, NULL, 0, 0)) { bQuit = TRUE; break; } // Forward appropriate messages for tooltips if (state == STATE_GAME) TooltipForwardMessage(&msg); /* Handle modeless dialog messages separately */ if ((hCurrentDlg == NULL || !IsDialogMessage(hCurrentDlg, &msg))) { TranslateMessage(&msg); DispatchMessage(&msg); } } } /* Unregister our custom classes--not good to leave them around */ UnregisterWindowClasses(); return msg.wParam; // Return value of PostQuitMessage }
static uint8 get_next_serial_no(z18_record_t *record) { uint16 ret,crc; uint32 next_ptr; uint8 buffer[64]; uint8 crc_buff[2]; uint8 rec_date[7]; uint8 i,main_error,flag; uint8 param_len = 26; // 先读取主参数表 /* * 记流水流程如下: * 1。 先更新流水号值 * 2. 写卡 * 3. 更新流水状态 * 当第2步失败的时候,如果明确没有写到卡上,那这笔流水就直接覆盖掉, 因此我们直接读备块参数 */ memset(buffer,0,sizeof buffer); memset(crc_buff,0,sizeof crc_buff); main_error = 1; ret = EeSysRead(POS_REC_PTR_ADDR,param_len,buffer); if(Z18_FAILED == ret) { debug_string("read ptr \n"); return KNG_POS_HARDWARE_ERROR; } // 判断crc //debug_hex(buffer+8,25); crc = GenerateCRC16(buffer,param_len-2); //debug_string("crc[%u]",crc); set_2byte_int(crc,crc_buff); //debug_hex(crc_buff,2); if(memcmp(crc_buff,buffer+24,2) == 0) { //debug_string("main sect"); // crc 校验正确 for(i = 0;i < 3;++i) { if(buffer[i] != ~buffer[3+i]) break; if(buffer[6+i] != ~buffer[9+i]) break; } // 保存备参数的内容,以便将来恢复使用 memcpy(g_z18pos.rec_buffer,buffer,sizeof(g_z18pos.rec_buffer)); main_error = 0; // 在这种情况下因为最后一次写卡失败,主参数表已经被恢复,主备参数一致,这样就不需要再写备参数表 if(g_z18pos.rec_status == 0) { //debug_string("sect backup"); // 先备份到备区 ret = EeSysWrite(POS_REC_BAK_PTR_ADDR,param_len,buffer); if(Z18_FAILED == ret) { debug_string("write ptr back\n"); return KNG_POS_HARDWARE_ERROR; } } } if(main_error == 1) { // 读取备块 memset(buffer,0,sizeof buffer); ret = EeSysRead(POS_REC_BAK_PTR_ADDR,param_len,buffer); if(Z18_FAILED == ret) { debug_string("read ptr back\n"); return KNG_POS_HARDWARE_ERROR; } //debug_string("back sect"); memset(crc_buff,0,sizeof crc_buff); crc = GenerateCRC16(buffer,24); set_2byte_int(crc,crc_buff); if(memcmp(crc_buff,buffer+24,2) != 0) { debug_string("back ptr crc\n"); // 备块错误 return KNG_POS_PARAM_ERROR; } // crc 校验正确 for(i = 0;i < 3;++i) { if(buffer[i] != ~buffer[3+i]) { debug_string("bak ptr crc\n"); return KNG_POS_PARAM_ERROR; } if(buffer[6+i] != ~buffer[9+i]) { debug_string("bak ptr crc\n"); return KNG_POS_PARAM_ERROR; } } // 保存备参数的内容,以便将来恢复使用 memcpy(g_z18pos.rec_buffer,buffer,sizeof(g_z18pos.rec_buffer)); } // 写主区 record->serial_no = get_4byte_int(buffer+12); g_z18pos.serial_no = record->serial_no; g_z18pos.rec_wr_ptr = get_3byte_int(buffer); g_z18pos.rec_rd_ptr = get_3byte_int(buffer+6); g_z18pos.rec_ptr_flag = buffer[23]; flag = g_z18pos.rec_ptr_flag; // 如果写记录指针与读记录指针相等,则认为记录已满 if(z18pos_check_rec_full()) { // flash 已经写满,重新开始 debug_string("record full\n"); return KNG_POS_REC_FULL; } if(g_z18pos.rec_rd_ptr == 0x00) { g_z18pos.rec_rd_ptr = POS_RECORD_BEGIN_ADDR; set_3byte_int(POS_RECORD_BEGIN_ADDR,buffer+6); calc_not(buffer+6,3,buffer+9); } next_ptr = g_z18pos.rec_wr_ptr + POS_REC_LEN; if(next_ptr >= POS_RECORD_END_ADDR) { // flash 写到最后 ,需要从头开始 next_ptr = POS_RECORD_BEGIN_ADDR; if(next_ptr <= g_z18pos.rec_rd_ptr ) flag = 0x00; else flag = 0xFF; } //debug_string("get serial no"); // 更新到下一条写记录地址 set_3byte_int(next_ptr,buffer); calc_not(buffer,3,buffer+3); // 累计金额 g_z18pos.total_money = get_4byte_int(buffer+16); memcpy(rec_date,buffer+20,3); /* if(memcmp(g_z18pos.curr_time+1,rec_date,3) >0) { // 更新到下一天 memcpy(buffer+20,g_z18pos.curr_time+1,3); // 写累计金额到前日累计金额 ret = update_pre_total(g_z18pos.total_money); if(ret) { debug_string("update pre money\n"); return ret; } g_z18pos.total_money = record->tx_money; debug_string("money[%lu][%lu]",g_z18pos.total_money,record->tx_money); memcpy(buffer+20,g_z18pos.curr_time+1,3); } else { g_z18pos.total_money += record->tx_money; debug_string("money[%lu][%lu]",g_z18pos.total_money,record->tx_money); } */ g_z18pos.total_money += record->tx_money; memcpy(g_z18pos.last_tx_date,buffer+20,3); // 更新当日累计金额 set_4byte_int(g_z18pos.total_money,buffer+16); // 流水号 set_4byte_int(record->serial_no+1,buffer+12); g_z18pos.serial_no++; g_z18pos.rec_wr_ptr = next_ptr; buffer[23] = flag; // 计算 crc crc = GenerateCRC16(buffer,24); set_2byte_int(crc,buffer+24); //debug_string("wr ptr[%lu]rd[%lu]serial[%lu]\n",g_z18pos.rec_wr_ptr,g_z18pos.rec_rd_ptr,g_z18pos.serial_no); ret = EeSysWrite(POS_REC_PTR_ADDR,param_len,buffer); if(ret == Z18_OK) { g_z18pos.rec_ptr_flag = flag; return 0; } debug_string("update ptr error\n"); return KNG_POS_HARDWARE_ERROR; }
static uint8 record_serial(z18_record_t *record ,uint8 flag,uint8 data *buffer) { uint8 offset,ret; // 根据 flag 的值来控制业务流程 // 1 : 记录新的流水 // 2 : 更新流水状态 // 新记录流水 if(flag==1) { offset = 0; // 版本号 buffer[offset] = record->ver; offset++; // 设备物理 ID memcpy(buffer+offset,g_z18pos.device_id,4); offset+=4; // 流水号 set_4byte_int(record->serial_no,buffer+offset); offset+=4; // 交易卡号 set_3byte_int(record->card_id,buffer+offset); offset +=3; // 入卡金额 set_4byte_int(record->in_balance,buffer+offset); offset+=4; // 交易金额 set_3byte_int(record->tx_money,buffer+offset); offset+=3; // 交易次数 memcpy(buffer+offset,(uint8*)&record->tx_count,2); offset+=2; // 交易时间 //str2bcd(record->tx_datetime,12,buffer+offset); memcpy(buffer+offset,record->tx_datetime,6); offset+=6; // 交易标志 buffer[offset++] = record->tx_mark; // 交易类型 buffer[offset++] = record->tx_type; // 钱包号 buffer[offset++] = record->purse_no; // 前一笔流水 #ifdef SAVE_CARD_REC memcpy(buffer+offset,record->pre_device_id,4); offset+=4; memcpy(buffer+offset,record->pre_tx_time,4); offset+=4; set_4byte_int(record->pre_in_balance,buffer+offset); offset+=4; set_3byte_int(record->pre_tx_money,buffer+offset); offset+=3; buffer[offset++] = record->pre_tx_mark; #else memset(buffer+offset,0x00,16); offset+=16; #endif // 15 byte 保留 offset+=15; // crc offset = 61 record->tx_crc = GenerateCRC16(buffer,offset); set_2byte_int(record->tx_crc,buffer+offset); offset+=2; // 状态 buffer[offset++] = record->tx_status; if(offset != POS_REC_LEN) { debug_string("error serial[%d]\n",(uint16)offset); return KNG_POS_PARAM_ERROR; } record->wr_ptr = g_z18pos.rec_wr_ptr; //debug_string("wr ptr[%ld]",g_z18pos.rec_wr_ptr); ret = z18pos_write_eeprom(g_z18pos.rec_wr_ptr,offset,3,buffer); if(ret) { debug_string("record serial[%lu]\n",g_z18pos.rec_wr_ptr); return ret; } //get_next_wr_ptr(); return 0; } else { // 更新交易标志 buffer[27] = record->tx_mark; // 更新 crc record->tx_crc = GenerateCRC16(buffer,POS_REC_LEN-3); set_2byte_int(record->tx_crc,buffer+61); // 更新 flash ret = z18pos_write_eeprom(record->wr_ptr,POS_REC_LEN,3,buffer); if(ret) { debug_string("upd rec,[%lu]\n",record->wr_ptr); return ret; } return 0; // 更新状态信息 } }