当前位置:   article > 正文

M1卡控制位的解析源码的封装_读取失败可能控制位被写死

读取失败可能控制位被写死

额,最近在做关于M1卡读写的程序开发,由于控制位的问题因此要查询资料解决其解析与打包的问题,恰好在GITHUB上有一个很好的项目,附带上地址:点我看这个神奇的项目 ,我根据这位程序员的思路封装了自己的库(控制位的操作基本都是按位操作,好麻烦的说。我也想参透,乃至自己独立按照M1卡相关文档可以写出,奈何实力不够,被按位操作绕的眼花缭乱的),该有的注释,基本都在这个库里面加了,为了直观明了,我一个个根据文档上的对应的权限来使用了较多的if语句来实现,因此代码有些冗余,为了好理解每一句的作用暂时不修改优化,有需要的可以根据自己的需求定制优化。

好的,话不多说,上代码:
  1. package test;
  2. import java.util.HashMap;
  3. public class AccessBitUitl {
  4. /*
  5. * 控制位长度,4位字节八个十六进制字符
  6. */
  7. public static final int CONTROLBIT_HEX_SIZE = 8;
  8. public static final int CONTROLBIT_BYTE_SIZE = 4;
  9. //可以实例化对象时使用的全局控制位缓存
  10. private byte[] mAcBytes = null;
  11. //静态工具库,default构造方法设为私有较好
  12. private AccessBitUitl() { /*This is don't need*/ }
  13. //有参构造方法,简化对相同控制位解析时方法调用的实现
  14. private AccessBitUitl(byte[] acBytes) { this.mAcBytes = acBytes; }
  15. /*
  16. * 参考文档
  17. * https://blog.csdn.net/liujianhua1989/article/details/72639307
  18. * https://www.cnblogs.com/h2zZhou/p/5250703.html
  19. * https://github.com/ikarus23/MifareClassicTool
  20. */
  21. /*认证后可执行下列操作:
  22. 1、读数据块,读操作支持普通的数据块(0-2)与电子钱包块与尾块(trail)
  23. 2、写数据块,写操作支持普通的数据块(0-2)与电子钱包块与尾块(trail)
  24. 3、减值:减少数据块内的数值,并将结果保存在临时内部数据寄存器中。(仅支持电子钱包块)
  25. 4、加值:增加数据块内的数值,并将结果保存在数据寄存器中。(仅支持电子钱包块)
  26. 5、恢复:将数据块内容移入数据寄存器。(仅支持电子钱包块)
  27. 6、转存:将临时内部数据寄存器的内容写入数值块。 (仅支持电子钱包块)
  28. 枚举操作类型,依次为 -> 读卡 , 写卡 , 增值 , 减值 , 恢复 , 转存
  29. */
  30. public static enum Operation{ READ, WRITE, INCREMENT,DECREMENT, RESTORE, TRANSFER }
  31. //密钥的验证是有KeyA,KeyB的两种不同的选择的,
  32. //当控制位的条件成立时,Key也可当作鉴权值之一
  33. //三个枚举元素分别是 A密钥, B密钥,AB密钥,两者都没
  34. public static enum KeyType{ A , B , AB , NEVER }
  35. //对于一个扇区,能操作的只有两部分,一部分是数据块,一部分是尾部块
  36. public static enum SectorStructure{ DATA , TRAIL }
  37. /*
  38. * 对数据块,能操作的总共有“三部分”,
  39. * Block1和Block2和Block3,不同容量的卡块数量不同,
  40. * 但是对于MIFARE CLASSIC CARD的兼容性来说,能操作的,就是“三部分”
  41. */
  42. public static enum DataBlockStructure{ BLOCK0 , BLOCK1 , BLOCK2 , BLOCK3 }
  43. //对于特殊的块3,是有三部分的分割读写区域
  44. //其中分别是KeyA的读写,还有KeyB的读写, 还有控制位的读写
  45. //因此我们要根据要操作的区域对控制位进行解析鉴权
  46. public static enum TrailStructure{ KEYA , KEYB , CONTROLBIT }
  47. //对于控制位,是有C1 , C2, C3的编号
  48. public static enum ControlBitNum{ C1 , C2 , C3 }
  49. /*块具有相对于区的独立性,16扇区各自拥有独立的鉴权方式,
  50. *块鉴权在控制位的约束下,对于密码的权限是依赖控制位的实现
  51. *依据控制位的约束,密钥对于块进行上述操作是必须要条件成立
  52. *每个数据块和尾块的读写条件均由3个bit定义,
  53. *并以非取反和取反形式保存在各个区的尾块中。
  54. **尾部块由C13 C23 C33三个控制位来控制,由于不是数据块,因此仅支持读写操作
  55. *数据块2由C12 C22 C32三个控制位控制,由于是数据块,因此支持读写增值减值操作
  56. *数据块1由C11 C21 C31三个控制位控制,由于是数据块,因此支持读写增值减值操作
  57. *数据块0由C10 C20 C30三个控制位控制,由于是数据块,因此支持读写增值减值操作
  58. */
  59. /* 警告,若控制位错误,将导致扇区锁死 */
  60. /*
  61. * 尾部块操作权限解析方法
  62. * 根据传入的控制字节对操作进行解析,返回对应的ENUM对象
  63. * @param c1 控制字节1
  64. * @param c2 控制字节2
  65. * @param c3 控制字节3
  66. * @param opera 将要进行的操作
  67. * @param whereToOpera 将要操作尾部块那一部分
  68. */
  69. public static KeyType trailOperation(byte c1, byte c2, byte c3,
  70. Operation opera, TrailStructure whereToOpera) {
  71. //判断传入的操作类型是否正确,如果不正确则直接返回NEVER
  72. //特别警告!!!在尾部块,操作仅限于支持读操作与写操作
  73. if(opera != Operation.READ && opera != Operation.WRITE) return KeyType.NEVER;
  74. //为了简化鉴权过程,先执行把操作为读的鉴权
  75. if(opera == Operation.READ) {
  76. //在尾部块的操作为在KeyA部分上进行的时候的鉴权
  77. if(whereToOpera == TrailStructure.KEYA) {
  78. //当控制位为000时KeyA部分禁止读
  79. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.NEVER;
  80. //当控制位为001时KeyA部分禁止读
  81. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  82. //当控制位为010时KeyA部分禁止读
  83. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  84. //当控制位为011时KeyA部分禁止读
  85. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  86. //当控制位为100时KeyA部分禁止读
  87. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.NEVER;
  88. //当控制位为101时KeyA部分禁止读
  89. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  90. //当控制位为110时KeyA部分禁止读
  91. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  92. //当控制位为111时KeyA部分禁止读
  93. if(c1 == 1 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  94. }
  95. //在尾部块的操作为在控制位部分上进行的时候的鉴权
  96. if(whereToOpera == TrailStructure.CONTROLBIT) {
  97. //当控制位为000时控制位部分允许验证密钥A后读
  98. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.A;
  99. //当控制位为001时控制位部分允许验证密钥A后读
  100. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.A;
  101. //当控制位为010时控制位部分允许验证密钥A后读
  102. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.A;
  103. //当控制位为011时控制位部分允许验证密钥A|B后读
  104. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.AB;
  105. //当控制位为100时控制位部分允许验证密钥A|B后读
  106. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.AB;
  107. //当控制位为101时控制位部分允许验证密钥A|B后读
  108. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.AB;
  109. //当控制位为110时控制位部分允许验证密钥A|B后读
  110. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.AB;
  111. //当控制位为111时控制位部分允许验证密钥A|B后读
  112. if(c1 == 1 && c2 == 1 && c3 == 1) return KeyType.AB;
  113. }
  114. //在尾部块的操作为在KeyB部分上进行的时候的鉴权
  115. if(whereToOpera == TrailStructure.KEYB) {
  116. //当控制位为000时KeyB部分允许验证密钥A后读
  117. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.A;
  118. //当控制位为001时KeyB部分允许验证密钥A后读
  119. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.A;
  120. //当控制位为010时KeyB部分允许验证密钥A后读
  121. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.A;
  122. //当控制位为011时KeyB部分禁止读
  123. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  124. //当控制位为100时KeyB部分禁止读
  125. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.NEVER;
  126. //当控制位为101时KeyB部分禁止读
  127. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  128. //当控制位为110时KeyB部分禁止读
  129. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  130. //当控制位为111时KeyB部分禁止读
  131. if(c1 == 1 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  132. }
  133. }
  134. //然后再执行操作为写的鉴权
  135. if(opera == Operation.WRITE) {
  136. //在尾部块的操作为在KeyA部分上进行的时候的鉴权
  137. if(whereToOpera == TrailStructure.KEYA) {
  138. //当控制位为000时KeyA部分允许验证密钥A后写
  139. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.A;
  140. //当控制位为001时KeyA部分允许验证密钥A后写
  141. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.A;
  142. //当控制位为010时KeyA部分禁止写
  143. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  144. //当控制位为011时KeyA部分允许验证密钥B后写
  145. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.B;
  146. //当控制位为100时KeyA部分允许验证密钥B后写
  147. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.B;
  148. //当控制位为101时KeyA部分禁止写
  149. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  150. //当控制位为110时KeyA部分禁止写
  151. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  152. //当控制位为111时KeyA部分禁止写
  153. if(c1 == 1 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  154. }
  155. //在尾部块的操作为在控制位部分上进行的时候的鉴权
  156. if(whereToOpera == TrailStructure.CONTROLBIT) {
  157. //当控制位为000时控制位部分允许验证密钥B后写
  158. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.B;
  159. //当控制位为001时控制位部分允许验证密钥A后写
  160. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.A;
  161. //当控制位为010时控制位部分禁止写
  162. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  163. //当控制位为011时控制位部分允许验证密钥B后写
  164. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.B;
  165. //当控制位为100时控制位部分禁止写
  166. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.NEVER;
  167. //当控制位为101时控制位部分允许验证密钥B后写
  168. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.B;
  169. //当控制位为110时控制位部分禁止写
  170. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  171. //当控制位为111时控制位部分禁止写
  172. if(c1 == 1 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  173. }
  174. //在尾部块的操作为在KeyB部分上进行的时候的鉴权
  175. if(whereToOpera == TrailStructure.KEYB) {
  176. //当控制位为000时KeyB部分允许验证密钥A后写
  177. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.A;
  178. //当控制位为001时KeyB部分允许验证密钥A后写
  179. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.A;
  180. //当控制位为010时KeyB部分禁止写
  181. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  182. //当控制位为011时KeyB部分允许验证密钥B后写
  183. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.B;
  184. //当控制位为100时KeyB部分允许验证密钥B后写
  185. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.B;
  186. //当控制位为101时KeyB部分禁止写
  187. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  188. //当控制位为110时KeyB部分禁止写
  189. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  190. //当控制位为111时KeyB部分禁止写
  191. if(c1 == 1 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  192. }
  193. }
  194. //在条件都不成立时返回NEVER
  195. return KeyType.NEVER;
  196. }
  197. /*
  198. * 数据块操作权限解析方法
  199. * 根据传入的控制字节对操作进行解析,返回对应的ENUM对象
  200. * @param c1 控制字节1
  201. * @param c2 控制字节2
  202. * @param c3 控制字节3
  203. * @param opera 将要对数据块进行的操作
  204. */
  205. public static KeyType generalOperation(byte c1, byte c2, byte c3, Operation opera) {
  206. //1、进行数据块读操作的鉴权
  207. if(opera == Operation.READ) {
  208. //在控制位为000时允许密钥AB后读
  209. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.AB;
  210. //在控制位为010时允许密钥AB后读
  211. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.AB;
  212. //在控制位为100时允许密钥AB后读
  213. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.AB;
  214. //在控制位为110时允许密钥AB后读
  215. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.AB;
  216. //在控制位为001时允许密钥AB后读
  217. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.AB;
  218. //在控制位为011时允许密钥B后读
  219. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.B;
  220. //在控制位为101时允许密钥B后读
  221. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.B;
  222. //在控制位为111时禁止读
  223. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  224. }
  225. //1、进行数据块写操作的鉴权
  226. if(opera == Operation.WRITE) {
  227. //在控制位为000时允许密钥AB后写
  228. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.AB;
  229. //在控制位为010时允许密钥B后写
  230. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.B;
  231. //在控制位为100时允许密钥B后写
  232. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.B;
  233. //在控制位为110时允许密钥B后写
  234. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.B;
  235. //在控制位为001时禁止读
  236. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  237. //在控制位为011时允许密钥B后写
  238. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.B;
  239. //在控制位为101时禁止写
  240. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  241. //在控制位为111时禁止写
  242. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  243. }
  244. //3、进行数据块增值操作的鉴权
  245. if(opera == Operation.INCREMENT) {
  246. //在控制位为000时允许密钥AB后增值
  247. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.AB;
  248. //在控制位为010时允许密钥B后增值
  249. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  250. //在控制位为100时允许密钥B后增值
  251. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.NEVER;
  252. //在控制位为110时允许密钥B后增值
  253. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.B;
  254. //在控制位为001时禁止增值
  255. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  256. //在控制位为011时允许密钥B后增值
  257. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  258. //在控制位为101时禁止增值
  259. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  260. //在控制位为111时禁止增值
  261. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  262. }
  263. //4、进行数据块减值操作的鉴权
  264. //5、进行数据块恢复操作的鉴权
  265. //6、进行数据块转存操作的鉴权
  266. if(opera == Operation.DECREMENT ||
  267. opera == Operation.RESTORE ||
  268. opera == Operation.TRANSFER) {
  269. //在控制位为000时允许密钥AB后减值转存恢复
  270. if(c1 == 0 && c2 == 0 && c3 == 0) return KeyType.AB;
  271. //在控制位为010时允许密钥B后减值转存恢复
  272. if(c1 == 0 && c2 == 1 && c3 == 0) return KeyType.NEVER;
  273. //在控制位为100时允许密钥B后减值转存恢复
  274. if(c1 == 1 && c2 == 0 && c3 == 0) return KeyType.NEVER;
  275. //在控制位为110时允许密钥AB后减值转存恢复
  276. if(c1 == 1 && c2 == 1 && c3 == 0) return KeyType.AB;
  277. //在控制位为001时允许密钥AB后减值转存恢复
  278. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.AB;
  279. //在控制位为011时禁止减值转存恢复
  280. if(c1 == 0 && c2 == 1 && c3 == 1) return KeyType.NEVER;
  281. //在控制位为101时禁止减值转存恢复
  282. if(c1 == 1 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  283. //在控制位为111时禁止减值转存恢复
  284. if(c1 == 0 && c2 == 0 && c3 == 1) return KeyType.NEVER;
  285. }
  286. //在条件都不成立时返回NEVER
  287. return KeyType.NEVER;
  288. }
  289. /*
  290. * 密钥B可读性判断方法
  291. * 返回TRUE则keyB可读并可用于存储数据的访问控制条件
  292. * 尾块和key A被预定义为传输配置状态。
  293. * 因为在传输配置状态下key B可读,
  294. * (KeyB可读的情况下)新卡必须用keyA认证。
  295. * @param c1 控制字节1
  296. * @param c2 控制字节2
  297. * @param c3 控制字节3
  298. */
  299. public static boolean isKeyBReadable(byte c1, byte c2, byte c3) {
  300. return c1 == 0
  301. //在控制位为000时密钥B可读
  302. && (c2 == 0 && c3 == 0)
  303. //在控制位为010时密钥B可读
  304. || (c2 == 1 && c3 == 0)
  305. //在控制位为001时密钥B可读
  306. || (c2 == 0 && c3 == 1);
  307. }
  308. /*
  309. * 传输配置状态检测方法
  310. * @param c1 控制字节1
  311. * @param c2 控制字节2
  312. * @param c3 控制字节3
  313. * @param block 要操作的区域
  314. */
  315. public static boolean isTranspotConfiguration(byte c1, byte c2, byte c3,
  316. SectorStructure block) {
  317. if(c1 == 0 && c2 == 0) {
  318. //操作数据块的情况下如果控制位为000则为传输配置状态
  319. if(block == SectorStructure.DATA && c3 == 0) return true;
  320. //操作尾部块的情况下如果控制位为001则为传输配置状态
  321. if(block == SectorStructure.TRAIL && c3 == 1) return true;
  322. }
  323. return false;
  324. }
  325. /*
  326. * 解析控制字节的方法
  327. * @param controlBit 长度为4byte的控制位
  328. * @param block 枚举对象,用于判断要解析的块的控制位的鉴权
  329. * 返回对应的区块的控制权限_对应的byte
  330. */
  331. public static HashMap<ControlBitNum,Byte> unpackAccessInfo(byte[] controlBit, DataBlockStructure block) {
  332. //控制位长度查错
  333. if(controlBit.length != CONTROLBIT_BYTE_SIZE) {
  334. throw new RuntimeException("The ControlBit length is error!!!");
  335. }
  336. //存结果的图表
  337. HashMap<ControlBitNum,Byte> result = new HashMap<>();
  338. //建立一个矩阵数组,存控制位换算结果
  339. //三个控制位,四个块
  340. byte[][] acMatrix = new byte[3][4];
  341. //验证控制位的可行性
  342. if ( (byte)((controlBit[1]>>>4)&0x0F) ==
  343. (byte)((controlBit[0]^0xFF)&0x0F) &&
  344. (byte)(controlBit[2]&0x0F) ==
  345. (byte)(((controlBit[0]^0xFF)>>>4)&0x0F) &&
  346. (byte)((controlBit[2]>>>4)&0x0F) ==
  347. (byte)((controlBit[1]^0xFF)&0x0F)) {
  348. // C1, Block 0-3
  349. for (int i = 0; i < 4; i++) {
  350. acMatrix[0][i] = (byte)((controlBit[1]>>>4+i)&0x01);
  351. }
  352. // C2, Block 0-3
  353. for (int i = 0; i < 4; i++) {
  354. acMatrix[1][i] = (byte)((controlBit[2]>>>i)&0x01);
  355. }
  356. // C3, Block 0-3
  357. for (int i = 0; i < 4; i++) {
  358. acMatrix[2][i] = (byte)((controlBit[2]>>>4+i)&0x01);
  359. }
  360. }
  361. if(block == DataBlockStructure.BLOCK0) {
  362. result.put(ControlBitNum.C1, acMatrix[0][0]);
  363. result.put(ControlBitNum.C2, acMatrix[1][0]);
  364. result.put(ControlBitNum.C3, acMatrix[2][0]);
  365. return result;
  366. }
  367. if(block == DataBlockStructure.BLOCK1) {
  368. result.put(ControlBitNum.C1, acMatrix[0][1]);
  369. result.put(ControlBitNum.C2, acMatrix[1][1]);
  370. result.put(ControlBitNum.C3, acMatrix[2][1]);
  371. return result;
  372. }
  373. if(block == DataBlockStructure.BLOCK2) {
  374. result.put(ControlBitNum.C1, acMatrix[0][2]);
  375. result.put(ControlBitNum.C2, acMatrix[1][2]);
  376. result.put(ControlBitNum.C3, acMatrix[2][2]);
  377. return result;
  378. }
  379. if(block == DataBlockStructure.BLOCK3) {
  380. result.put(ControlBitNum.C1, acMatrix[0][3]);
  381. result.put(ControlBitNum.C2, acMatrix[1][3]);
  382. result.put(ControlBitNum.C3, acMatrix[2][3]);
  383. return result;
  384. }
  385. return null;
  386. }
  387. /*
  388. * 打包控制字节的方法
  389. * @param controlBit 全部控制位的实现,当有四个对象,每个对象里有用C1 , C2 , C3
  390. * 三个键值对,对应四个块的三个控制位
  391. * 返回全部区块的控制权限_对应的byte(三个,不包括预留字节)
  392. */
  393. public static byte[] packAccessInfo(HashMap<DataBlockStructure,HashMap<ControlBitNum,Byte>> controlBit) {
  394. //建立一个矩阵数组,存控制位换算结果
  395. //三个控制位,四个块,从图表中取出来填充到矩阵数组中
  396. byte[][] acMatrix = new byte[3][4];
  397. //外层迭代
  398. for(int i = 0; i < 3; ++i) {
  399. //内层迭代
  400. for(int j = 0; j < 4; ++j) {
  401. acMatrix[i][j] =
  402. //取出对应扇区的控制比特位封包
  403. controlBit.get(DataBlockStructure.values()[j])
  404. //取出封包中的比特位打包进矩阵中
  405. .get(ControlBitNum.values()[i]);
  406. }
  407. }
  408. //开始将比特矩阵数组转化为字节数组
  409. if (acMatrix != null && acMatrix.length == 3) {
  410. for (int i = 0; i < 3; i++) {
  411. if (acMatrix[i].length != 4)
  412. // Error.
  413. return null;
  414. }
  415. } else {
  416. // Error.
  417. return null;
  418. }
  419. byte[] acBytes = new byte[3];
  420. // Byte 6, Bit 0-3.
  421. acBytes[0] = (byte)((acMatrix[0][0]^0xFF)&0x01);
  422. acBytes[0] |= (byte)(((acMatrix[0][1]^0xFF)<<1)&0x02);
  423. acBytes[0] |= (byte)(((acMatrix[0][2]^0xFF)<<2)&0x04);
  424. acBytes[0] |= (byte)(((acMatrix[0][3]^0xFF)<<3)&0x08);
  425. // Byte 6, Bit 4-7.
  426. acBytes[0] |= (byte)(((acMatrix[1][0]^0xFF)<<4)&0x10);
  427. acBytes[0] |= (byte)(((acMatrix[1][1]^0xFF)<<5)&0x20);
  428. acBytes[0] |= (byte)(((acMatrix[1][2]^0xFF)<<6)&0x40);
  429. acBytes[0] |= (byte)(((acMatrix[1][3]^0xFF)<<7)&0x80);
  430. // Byte 7, Bit 0-3.
  431. acBytes[1] = (byte)((acMatrix[2][0]^0xFF)&0x01);
  432. acBytes[1] |= (byte)(((acMatrix[2][1]^0xFF)<<1)&0x02);
  433. acBytes[1] |= (byte)(((acMatrix[2][2]^0xFF)<<2)&0x04);
  434. acBytes[1] |= (byte)(((acMatrix[2][3]^0xFF)<<3)&0x08);
  435. // Byte 7, Bit 4-7.
  436. acBytes[1] |= (byte)((acMatrix[0][0]<<4)&0x10);
  437. acBytes[1] |= (byte)((acMatrix[0][1]<<5)&0x20);
  438. acBytes[1] |= (byte)((acMatrix[0][2]<<6)&0x40);
  439. acBytes[1] |= (byte)((acMatrix[0][3]<<7)&0x80);
  440. // Byte 8, Bit 0-3.
  441. acBytes[2] = (byte)(acMatrix[1][0]&0x01);
  442. acBytes[2] |= (byte)((acMatrix[1][1]<<1)&0x02);
  443. acBytes[2] |= (byte)((acMatrix[1][2]<<2)&0x04);
  444. acBytes[2] |= (byte)((acMatrix[1][3]<<3)&0x08);
  445. // Byte 8, Bit 4-7.
  446. acBytes[2] |= (byte)((acMatrix[2][0]<<4)&0x10);
  447. acBytes[2] |= (byte)((acMatrix[2][1]<<5)&0x20);
  448. acBytes[2] |= (byte)((acMatrix[2][2]<<6)&0x40);
  449. acBytes[2] |= (byte)((acMatrix[2][3]<<7)&0x80);
  450. return acBytes;
  451. }
  452. /**
  453. * Convert the Access Condition bytes to a matrix containing the
  454. * resolved C1, C2 and C3 for each block.
  455. * @param acBytes 控制位字节数组
  456. * @return 返回由3字节的控制位解析出来的控制位(bit)矩阵
  457. * null will be returned.
  458. */
  459. public static byte[][] acBytesToACMatrix(byte acBytes[]) {
  460. // ACs correct?
  461. // C1 (Byte 7, 4-7) == ~C1 (Byte 6, 0-3) and
  462. // C2 (Byte 8, 0-3) == ~C2 (Byte 6, 4-7) and
  463. // C3 (Byte 8, 4-7) == ~C3 (Byte 7, 0-3)
  464. byte[][] acMatrix = new byte[3][4];
  465. if (acBytes.length > 2 &&
  466. (byte)((acBytes[1]>>>4)&0x0F) ==
  467. (byte)((acBytes[0]^0xFF)&0x0F) &&
  468. (byte)(acBytes[2]&0x0F) ==
  469. (byte)(((acBytes[0]^0xFF)>>>4)&0x0F) &&
  470. (byte)((acBytes[2]>>>4)&0x0F) ==
  471. (byte)((acBytes[1]^0xFF)&0x0F)) {
  472. // C1, Block 0-3
  473. for (int i = 0; i < 4; i++) {
  474. acMatrix[0][i] = (byte)((acBytes[1]>>>4+i)&0x01);
  475. }
  476. // C2, Block 0-3
  477. for (int i = 0; i < 4; i++) {
  478. acMatrix[1][i] = (byte)((acBytes[2]>>>i)&0x01);
  479. }
  480. // C3, Block 0-3
  481. for (int i = 0; i < 4; i++) {
  482. acMatrix[2][i] = (byte)((acBytes[2]>>>4+i)&0x01);
  483. }
  484. return acMatrix;
  485. }
  486. return null;
  487. }
  488. /**
  489. * 把矩阵控制位(比特类型的矩阵数组)转换为3字节的控制位
  490. * @param acMatrix bit类型的控制位矩阵数组
  491. * @return 返回3字节的字节数组
  492. */
  493. public static byte[] acMatrixToACBytes(byte acMatrix[][]) {
  494. if (acMatrix != null && acMatrix.length == 3) {
  495. for (int i = 0; i < 3; i++) {
  496. if (acMatrix[i].length != 4)
  497. // Error.
  498. return null;
  499. }
  500. } else {
  501. // Error.
  502. return null;
  503. }
  504. byte[] acBytes = new byte[3];
  505. // Byte 6, Bit 0-3.
  506. acBytes[0] = (byte)((acMatrix[0][0]^0xFF)&0x01);
  507. acBytes[0] |= (byte)(((acMatrix[0][1]^0xFF)<<1)&0x02);
  508. acBytes[0] |= (byte)(((acMatrix[0][2]^0xFF)<<2)&0x04);
  509. acBytes[0] |= (byte)(((acMatrix[0][3]^0xFF)<<3)&0x08);
  510. // Byte 6, Bit 4-7.
  511. acBytes[0] |= (byte)(((acMatrix[1][0]^0xFF)<<4)&0x10);
  512. acBytes[0] |= (byte)(((acMatrix[1][1]^0xFF)<<5)&0x20);
  513. acBytes[0] |= (byte)(((acMatrix[1][2]^0xFF)<<6)&0x40);
  514. acBytes[0] |= (byte)(((acMatrix[1][3]^0xFF)<<7)&0x80);
  515. // Byte 7, Bit 0-3.
  516. acBytes[1] = (byte)((acMatrix[2][0]^0xFF)&0x01);
  517. acBytes[1] |= (byte)(((acMatrix[2][1]^0xFF)<<1)&0x02);
  518. acBytes[1] |= (byte)(((acMatrix[2][2]^0xFF)<<2)&0x04);
  519. acBytes[1] |= (byte)(((acMatrix[2][3]^0xFF)<<3)&0x08);
  520. // Byte 7, Bit 4-7.
  521. acBytes[1] |= (byte)((acMatrix[0][0]<<4)&0x10);
  522. acBytes[1] |= (byte)((acMatrix[0][1]<<5)&0x20);
  523. acBytes[1] |= (byte)((acMatrix[0][2]<<6)&0x40);
  524. acBytes[1] |= (byte)((acMatrix[0][3]<<7)&0x80);
  525. // Byte 8, Bit 0-3.
  526. acBytes[2] = (byte)(acMatrix[1][0]&0x01);
  527. acBytes[2] |= (byte)((acMatrix[1][1]<<1)&0x02);
  528. acBytes[2] |= (byte)((acMatrix[1][2]<<2)&0x04);
  529. acBytes[2] |= (byte)((acMatrix[1][3]<<3)&0x08);
  530. // Byte 8, Bit 4-7.
  531. acBytes[2] |= (byte)((acMatrix[2][0]<<4)&0x10);
  532. acBytes[2] |= (byte)((acMatrix[2][1]<<5)&0x20);
  533. acBytes[2] |= (byte)((acMatrix[2][2]<<6)&0x40);
  534. acBytes[2] |= (byte)((acMatrix[2][3]<<7)&0x80);
  535. return acBytes;
  536. }
  537. /*
  538. * 根据一个控制位来进行所有的操作时使用的对象
  539. * @param acBytes 控制位字节,四字节的控制位字节数组
  540. * @return 返回this
  541. */
  542. public static AccessBitUitl operaOneAc(byte[] acBytes) {
  543. return new AccessBitUitl(acBytes);
  544. }
  545. /*
  546. * 重载unpackAccessInfo,简化调用
  547. */
  548. public HashMap<ControlBitNum,Byte> unpackAccessInfo(DataBlockStructure block){
  549. return unpackAccessInfo(mAcBytes,block);
  550. }
  551. /*
  552. * 重载unpackAccessInfo,简化调用
  553. */
  554. public HashMap<DataBlockStructure,HashMap<ControlBitNum,Byte>> unpackAccessInfo(){
  555. DataBlockStructure[] blocks = { DataBlockStructure.BLOCK0 ,
  556. DataBlockStructure.BLOCK1 ,
  557. DataBlockStructure.BLOCK2 ,
  558. DataBlockStructure.BLOCK3 };
  559. HashMap<DataBlockStructure,HashMap<ControlBitNum,Byte>> result = new HashMap<DataBlockStructure,HashMap<ControlBitNum,Byte>>();
  560. for(int i = 0; i < 4; ++i) {
  561. result.put(blocks[i] , unpackAccessInfo(blocks[i]));
  562. }
  563. return result;
  564. }
  565. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/985050
推荐阅读
相关标签
  

闽ICP备14008679号