8583组包解包及银联3des签到消费java示例
8583報文示例
8583報文構成
長度 + 報文頭【TPDU + msgHead + msgType(報文/消息類型)】 + 位圖 + 各數據域
銀聯8583簽到報文示例
報文為:
0063600049000060320032050108000020000000C0001600007431323334353637383132333435363738393132333435360011000000000030003753657175656E6365204E6F32343934393130303030303130343138313243413835393239310003313233
在實際傳輸報文中,傳輸的是byte數組,這里用16進制來表示byte數組
其中,各字段的詳細數據如下:
長度:0063
報文頭:
- TPDU:6000490000
- msgHead:603200320501
- msgType(報文/消息類型):0800
- 位圖:0020000000C00016
數據域: 00007431323334353637383132333435363738393132333435360011000000000030003753657175656E6365204E6F32343934393130303030303130343138313243413835393239310003313233
8583手動組包
銀聯簽到報文規范
下圖為銀聯3des簽到報文格式說明:
3des簽到,即我們將一段報文(byte數組)發送給服務端(這里用的是Poster模擬器),然后服務端進行驗證,若驗證通過,會下發工作秘鑰。而發送的這段報文,需要進行8583組包,組包的數據,通常給到的是String類型(也有可能不是),需要將其轉化成byte數組傳給服務端,而各個數據域轉byte數組會有不同規則。
8583報文數據類型
這里數據類型分為三種:BCD、ASCII、BINARY
數據長度的類型也分為三種:定長、LLVAR不定長、LLLVAR不定長
詳細屬性的解釋見(8583各數據域屬性說明https://download.csdn.net/download/weixin_40582843/11169088)
銀聯3des簽到報文組包
數據源
現在開始對銀聯3des簽到報文組包,所用到的字段有(這里只用必須的字段,即上圖所示請求格式中標識為M的字段):
長度:未計算
TPDU:6000490000
msgHead:603200320501
msgType(報文/消息類型):0800(銀聯簽到報文格式中,0800代表簽到請求)
位圖:未計算
各數據域:
- 11域:“000074”
- 41域:“12345678”
- 42域:“123456789123456”
- 60域:“00000000003”
- 62域:
“53657175656E6365204E6F3234393439313030303030313034313831324341383539323931” - 63域:“123”
組包
數據域
-
11域,類型為BCD,屬性為n6,壓縮時用BCD碼表示3個字節的定長域(注:這里的BCD類型,表示出現的‘字符’只會在0-9之間,定長,表示固定長度為6位,即n后的數字6)
- 即“000074”轉為byte數組后,用16進制表示為{0x00,0x00,0x74},為3個字節;
- 查ascii碼表,可以知道“7”用二進制表示為“0011 0111”,“4”用二進制表示為“0011 0100”,這里“74”兩個字符便是2個字節了,去掉前4位,用二進制表示為“0111 0100”,用16進制表示為0x74,即為一個字節;
- “000074”轉化后,便是0x00,0x00,0x74,去掉0x前綴后表示為000074
-
41域,類型為ASCII,屬性為ans8,表示8個字節的定長字符域
- 查ascii碼,可知"12345678"轉為16進制表示為{0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38},剛好8個字節,去掉0x前綴后為,3132333435363738
-
42域,類型為ASCII,屬性為ans15,為15個字節的定長字符域,表示為313233343536373839313233343536
-
60域,類型為BCD,屬性為n…017,格式為LLLVAR,表示長度最大為17個字節的不定長字符域
- ? “00000000003”,長度為11位,用BCD碼表示時,長度需為偶數,可以選擇左靠右補0或右靠左補0的方式(看業務需求),我使用的poster模擬器中,要求此數據域為左靠右補0,補0后數據為“000000000030“,類比11域的轉化,最后的數據用16進制表示為000000000030;
- ? 但此數據域為LLLVAR不定長域,需要在數據前用2個字節表示其長度,這里的長度為未補0之前的長度,即11,(長度為BCD的類型,不夠3個字節時右靠左補0),最終結果為0011;
- ? 即60域最終數據為0011000000000003;
-
62域,類型為BINARY,屬性為b…084,格式為LLLVAR,表示長度最大為84字節的不定長字符域
- ? 一般類型為BINARY時,傳過來的數據都是byte數組了,這個例子中,用16進制表示byte數組為,“53657175656E6365204E6F3234393439313030303030313034313831324341383539323931”,不需要轉換(因為8583報文傳輸的便是byte數組)
- ? 由于是不定長,這里byte數組長度為37,長度壓縮時用BCD碼表示2個字節,轉化后為0037
- ? 即62域最終數據為003753657175656E6365204E6F3234393439313030303030313034313831324341383539323931
-
63域,類型為ASCII,屬性為ans…003,格式為LLLVAR,為最多3個字節的不定長字符域
- ? 最終數據為0003313233
各數據域連起來的結果為:
00007431323334353637383132333435363738393132333435360011000000000030003753657175656E6365204E6F32343934393130303030303130343138313243413835393239310003313233
位圖
位圖的定義:
在所有的報文中都需要主位元表。它決定消息中包含了哪些數據字段。這些位是從左向右解釋的,“1”表示該字段在消息中出現,“0”則表示未出現,第n位指示第n個數據字段。
如果第一位設置為“1”,表示有擴展位元表。
只有當消息中出現第65-128數據字段時,擴展位元表才出現。擴展位元表的描述和主位元表的描述一致。
在此簽到報文中,最多只有64域,故無擴展位元表,且主位元表的第一位應設置為0,其他位,若有該字段,則設置為1,否則設置為0,故11,41,42,60,62,63位需設置為1,其它位設置為0
位元表用二進制表示為100000000000000000000000000000110000000000000000010110
轉為16進制表示為0020000000C00016
報文頭及報文長度
在簽到報文的報文頭中,數據類型都為定長BCD碼,轉換后,將 報文頭【TPDU + msgHead + msgType(報文/消息類型)】 + 位圖 + 各數據域 連接起來,得到的數據用16進制表示為:
600049000060320032050108000020000000C0001600007431323334353637383132333435363738393132333435360011000000000030003753657175656E6365204E6F32343934393130303030303130343138313243413835393239310003313233
可以計算出,此數據的長度為99個字節,而字符“99”用2個字節16進制表示為:0x00,0x63
組包
故,報文最終結果為:
0063600049000060320032050108000020000000C0001600007431323334353637383132333435363738393132333435360011000000000030003753657175656E6365204E6F32343934393130303030303130343138313243413835393239310003313233
銀聯簽到及消費java代碼實例
工具準備
使用poster模擬器進行交易,將模擬器通訊方式設置為tcp
簽到結果
https://github.com/suya1994/Demo8583.git
將此報文發送給poster模擬器后,模擬器會返回相應的報文,返回報文62域中含有工作秘鑰,表示簽到成功;模擬器交易截圖為下圖:
簽到報文工作秘鑰解析
/*** 解析簽到報文第62域*/ public void unpack62Field(){System.out.println("\n-----start unpack62Field------");//將62域的數據提出來,分組int contentLength = fields[62].bytesData.length - 2;byte[] content = new byte[contentLength];System.arraycopy(fields[62].bytesData,2,content,0,contentLength);//工作秘鑰密文byte[] content1 = Arrays.copyOfRange(content,0,16);byte[] content2 = Arrays.copyOfRange(content,20,36);byte[] content3 = Arrays.copyOfRange(content,40,56);//校驗碼byte[] check1 = Arrays.copyOfRange(content,16,20);byte[] check2 = Arrays.copyOfRange(content,36,40);byte[] check3 = Arrays.copyOfRange(content,56,60);System.out.println("check1 = " + Utils.bytes2HexStr(check1));System.out.println("check2 = " + Utils.bytes2HexStr(check2));System.out.println("check3 = " + Utils.bytes2HexStr(check3));//用3des解密第62域,主秘鑰為16個0x11,解密出三個工作秘鑰byte[] key = new byte[]{0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31,0x31};//解密后的工作秘鑰byte[] decrypt1 = EncryptUtil.decryptByDESede(content1,key);byte[] decrypt2 = EncryptUtil.decryptByDESede(content2,key);byte[] decrypt3 = EncryptUtil.decryptByDESede(content3,key);System.out.println("decrypt1 = " + Utils.bytes2HexStr(decrypt1));System.out.println("decrypt2 = " + Utils.bytes2HexStr(decrypt2));System.out.println("decrypt3 = " + Utils.bytes2HexStr(decrypt3));//用工作秘鑰給8字節0x00加密,若結果的前4字節和校驗碼相同,則說明工作秘鑰對byte[] encrypt = new byte[]{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};byte[] decrypt1by3des = EncryptUtil.encryptByDESede(encrypt,decrypt1);byte[] decrypt2by3des = EncryptUtil.encryptByDESede(encrypt,decrypt2);byte[] decrypt3by3des = EncryptUtil.encryptByDESede(encrypt,decrypt3);System.out.println("decrypt1by3des = " + Utils.bytes2HexStr(decrypt1by3des));System.out.println("decrypt2by3des = " + Utils.bytes2HexStr(decrypt2by3des));System.out.println("decrypt3by3des = " + Utils.bytes2HexStr(decrypt3by3des));//前四字節,與校驗碼對比byte[] _decrypt1by3des = Arrays.copyOf(decrypt1by3des,4);byte[] _decrypt2by3des = Arrays.copyOf(decrypt2by3des,4);byte[] _decrypt3by3des = Arrays.copyOf(decrypt3by3des,4);//若相同,則保存三個工作秘鑰if (Arrays.equals(_decrypt1by3des,check1) && Arrays.equals(_decrypt2by3des,check2) && Arrays.equals(_decrypt3by3des,check3)){Pack.key1 = decrypt1;Pack.key2 = decrypt2;Pack.key3 = decrypt3;}System.out.println("-----end unpack62Field------\n"); }文中代碼:https://github.com/suya1994/Demo8583.git
總結
以上是生活随笔為你收集整理的8583组包解包及银联3des签到消费java示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BGP实战拓扑
- 下一篇: 黑客正利用“Black Lives Ma