银行系统的密钥有三种,主密钥/pinkey/Mackey,其中pinkey是用来加密密码的,而mackey是用来校验报文是否有错码,主密钥是用来加密pinkey和mackey的.
其中主密钥加密pinkey和mackey是是用3des来加解密的
代码如下:
/* param: pKey:密钥(十六进制) strPlainAKey:需要加解密的字符串(十六进制) ciperAKey:返回值 iflag:1解密 0加密 */ void getCiper(char* pKey, char* strPlainAKey, char* ciperAKey, int iflag) { unsigned char binPlainAKey[64] = {0}; hex2binary(binPlainAKey, strPlainAKey, strlen(strPlainAKey)); ASCIIStr2BinCharStrBy3DES(pKey,(unsigned char*)binPlainAKey,strlen(strPlainAKey)/2, (unsigned char*)ciperAKey, iflag); } /* param: pKey:密钥(十六进制) inBinary:加解密字符串的字节形式 inLen:加解密字符串的长度 binCharString:返回值 iflag:1解密 0加密 */ void ASCIIStr2BinCharStrBy3DES(char* pKey, unsigned char* inBinary, int inLen, unsigned char* binCharString,int iflag) { unsigned char targetIdBin[DESBINARY_LEN] = {0}; //TargetIdLen=8 // 3DES encription unsigned char key[LEN_OF_KEY]; unsigned char block_key[9]; memset(key, 0, LEN_OF_KEY); hex2binary(key, pKey, strlen(pKey)); DES_key_schedule ks,ks2,ks3; memset(block_key, 0, sizeof(block_key)); memcpy(block_key, key + 0, 8); DES_set_key_unchecked((const_DES_cblock*)block_key, &ks); memcpy(block_key, key + 8, 8); DES_set_key_unchecked((const_DES_cblock*)block_key, &ks2); memcpy(block_key, key + 0, 8); DES_set_key_unchecked((const_DES_cblock*)block_key, &ks3); unsigned char input[8]; memset(input, 0, sizeof(input)); unsigned char encryptedOutBinary[DESBINARY_LEN]; memset(encryptedOutBinary, 0, sizeof(encryptedOutBinary)); for(int i=0; i<inLen/8; i++) { memset(targetIdBin, 0, sizeof(targetIdBin)); memcpy((void*)targetIdBin, (const void*)(inBinary+i*8), 8); DES_ecb3_encrypt((const_DES_cblock*)targetIdBin, (DES_cblock*)encryptedOutBinary, &ks, &ks2, &ks3, iflag); binary2char((char*)binCharString+i*16, encryptedOutBinary, DESBINARY_LEN); } } // // A public function: convert binary string to character string, the character string‘s length = 2 // binary string. // @param charArray: character array. output. // @param binArray: binary array. input. // @param binLen: length of binary array. // void binary2char(char* charArray, const unsigned char* binArray, int binLen) { int i; for(i = 0; i < binLen; i++) { sprintf(charArray + 2*i, "%02X", binArray[i]); } charArray[2*i] = ‘\0‘; } // // A public function: convert hex string to binary string, the hex string‘s length = 2 * binary string. // @param binArray: binary array. output. // @param hexCharArray: character array contains hex string. input. // @param hexLen: length of hex string array. input. // void hex2binary(unsigned char* binArray, const char* hexCharArray, int hexLen) { if (hexLen%2 != 0) { printf("hex2binary(): length of input parameter hexCharArray should be even number!\n"); return; } int i, j; //convert two hex chars to one byte char atom[2 + 1] = "\0"; for (i = 0, j = 0; i < hexLen/2; i++, j+=2) { strncpy(atom, hexCharArray + j, sizeof(atom) - 1); atom[sizeof(atom) - 1] = ‘\0‘; binArray[i] = (unsigned char)strtol(atom, NULL, 16); } }
一般来说,ATM拿到pinkey密文会使用主密钥解密,得到pinkey明文,然后是用帐号+密码生成pinblock明文,然后使用pinkey使用3des加密,然后传给后端
生成pinblock明文的算法为:
char uniteBytes(char a,char b) { char c = (int(a-‘0‘)<<4)+b-‘0‘; return c; } /** * getHPin * 对密码进行转换 * PIN格式 * BYTE 1 PIN的长度 * BYTE 2 – BYTE 3/4/5/6/7 4--12个PIN(每个PIN占4个BIT) * BYTE 4/5/6/7/8 – BYTE 8 FILLER “F” (每个“F“占4个BIT) * @param pin String * @return byte[] */ void getHPin(char* pin, char* encode) { encode[0] = 6; encode[1] = uniteBytes(pin[0], pin[1]); encode[2] = uniteBytes(pin[2], pin[3]); encode[3] = uniteBytes(pin[4], pin[5]); encode[4] = 255; encode[5] = 255; encode[6] = 255; encode[7] = 255; } /** * getHAccno * 对帐号进行转换 * BYTE 1 — BYTE 2 0X0000 * BYTE 3 — BYTE 8 12个主帐号 * 取主帐号的右12位(不包括最右边的校验位),不足12位左补“0X00”。 * @param accno String * @return byte[] */ char* getHAccno(char* accno,char* encode) { int len = strlen(accno); int beginPos = len < 13 ? 0 : len - 13; char arrTemp[13] = {0}; memcpy(arrTemp, accno+beginPos, len-beginPos-1); char arrAccno[12]; for(int i=0; i<12; i++) { arrAccno[i] = (i <= strlen(arrTemp) ? arrTemp[i] : 0); } encode[0] = 0; encode[1] = 0; encode[2] = uniteBytes(arrAccno[0], arrAccno[1]); encode[3] = uniteBytes(arrAccno[2], arrAccno[3]); encode[4] = uniteBytes(arrAccno[4], arrAccno[5]); encode[5] = uniteBytes(arrAccno[6], arrAccno[7]); encode[6] = uniteBytes(arrAccno[8], arrAccno[9]); encode[7] = uniteBytes(arrAccno[10], arrAccno[11]); return encode; } /** * getPinBlock * 标准ANSI X9.8 Format(带主帐号信息)的PIN BLOCK计算 * PIN BLOCK 格式等于 PIN 按位异或 主帐号; * @param pin String * @param accno String * @return byte[] */ void process(char* pin, char* accno,char* pHexRet) { char arrAccno[128]={0}; getHAccno(accno,arrAccno); char arrPin[128]={0}; getHPin(pin, arrPin); unsigned char arrRet[8]={0}; for(int i=0; i<8; i++){ arrRet[i] = (unsigned char)(arrPin[i] ^ arrAccno[i]); } binary2char(pHexRet, arrRet, 8); }
Mac运算:
ATM拿到mackey,通过主密钥解密得到密钥明文,使用一串双方协议好的macdata格式,通过ANSI 9.19得到macblock,随报文发到后端,后端也会做同样的操作,然后比对,得到校验结果
Ansi 9.19的算法如下
void xor(unsigned char *input1,unsigned char *input2,unsigned char *output,int len) { while (len) { *output++=*input1++^*input2++; len--; } } /* *@brief: 根据输入数据计算MAC,初始IV向量默认为"x00x00x00x00x00x00x00x00" *@param: sMacKey 密钥 *@param: pInData 输入数据 *@param: pRetData 计算出来的MAC *@调用自定义xor和des函数 */ void MacArithmetic(char *sMacKey,char *inBinary,char *pRetData) { //MAC算法: //将字符串pInata分为8字节为单位的数据块,不足补x00,分别标号为D1,D2,D3,...,Dn //设置初始向量E0="x00x00x00x00x00x00x00x00" //将E0^D1 —---->E1(E0,D1异或的后结果经使用密钥左8位des加密得到E1) //将E1^D2 ----->E2 //如此类推,知道得出En结束, //使用密钥右8位des解密En得到En0 //使用密钥左8位加密En0得到En1 //En1即是计算出来的MAC unsigned char sUpData[512]; unsigned char sData[20]; unsigned char sXorData[20]; unsigned char sDesData[20]; int i,n,iNum,iInLen; unsigned char key[16]; unsigned char block_key[9]; iInLen=strlen(inBinary); memset(key, 0, sizeof(key)); hex2binary(key, sMacKey, strlen(sMacKey)); DES_key_schedule ks,ks2,ks3; memset(block_key, 0, sizeof(block_key)); memcpy(block_key, key + 0, 8); DES_set_key_unchecked((const_DES_cblock*)block_key, &ks); memcpy(block_key, key + 8, 8); DES_set_key_unchecked((const_DES_cblock*)block_key, &ks2); memcpy(block_key, key + 0, 8); DES_set_key_unchecked((const_DES_cblock*)block_key, &ks3); memset(sUpData,0,sizeof(sUpData)); memset(sData,0,sizeof(sData)); memset(sXorData,0,sizeof(sXorData)); memset(sDesData,0,sizeof(sDesData)); //补全要加密数据成8倍数到sUpData,不足补x00 memcpy(sUpData,inBinary,iInLen); iNum = iInLen%8; if (iNum == 0) n=iInLen/8; else { n=iInLen/8+1; memcpy(sUpData+iInLen,"\0\0\0\0\0\0\0\0",8-iNum); } printf("n=%dnsUpData=[%s]n",n,sUpData); memset(sDesData,0,sizeof(sDesData)); //初始向量赋给sDesData for (i=0;i<n;i++) { memcpy(sData,sUpData+i*8,8); xor(sDesData,sData,sXorData,8); //异或 DES_ecb_encrypt((const_DES_cblock*)sXorData, (DES_cblock*)sDesData, &ks,1); } DES_ecb_encrypt((const_DES_cblock*)sDesData, (DES_cblock*)sXorData, &ks2,0); DES_ecb_encrypt((const_DES_cblock*)sXorData, (DES_cblock*)sDesData, &ks,1); binary2char(pRetData, sDesData, 8); return ; }
银行密钥体系
时间: 2024-10-16 20:25:09