D3非接触式读写M1卡几行代码的Java开发

笔者作为一个苦逼即将毕业的大四学生在外打拼已经两个月了,虽然没有费什么大力气被老师推荐到一个小boss公司里面实习,两个月也是颇有感叹。对于小公司,选一个员工像选媳妇儿一样,要“上得厅堂下的厨房”,对老板来说,不管你学过什么,需要写SQL的时候你就得会数据库,需要写html的时候你就得会css,js,开发后台的时候你就得会写servlet,filter,电脑坏了还的会装系统。还得会网络布线调试。博主什么都不精,又什么都会点,反正上刚才列举的东西基本都试了一遍,感慨万千啊。这不,应公司一个移动项目需求,boss需要一个射频卡初始化程序。也不知怎么的就让博主研究研究,我也不好吐槽,不要喊我研究什么,我也没那本事,反正本着boss的需求小小员工就的始终不渝的执行原则,怀着战战兢兢的心就试着写那么几段代码。


入手吧,东西和资料也不懂,就一个D3非接触式读写器,几张M1卡(是射频卡吗,到现在还分不大清,应该有啥区别吧),一个驱动程序,安装完了后还有一个几十k的chm(api)。说干就干呗,也不怕把boss买的机子弄坏,装好驱动后就用读卡器试了试,还是很新鲜的,最少能看到这M1的存储分区吧


M1卡0~15扇区,每区4块(编号记0~63),每块能写16个字符,其中0扇区第0块装商家出厂初始化的一些信息不能擦写,每个扇区的最后一块【(扇区号+1)*4-1】保存密码,其他的数据块都能存储数据。


先不说程序的事,再来说说这M1卡的密码机制吧,这尼玛才叫一个蛋疼,反正到现在我还是一头雾水,对于我这个智商不高的童鞋来说那简直就是比微积分还难过(ps:博主大学唯一挂在的微积分大树上),反正到现在还是一个迷糊蛋,不过反正是能实现boss那不高的要求。这对我来说就可以了,那要是真的深入去学吧,我这人记两天就又忘了,话说又不能当饭吃哈,要是能破解这M1卡的密码那我反手就是100块扔老板脸上走人。(扔100的原因是博主我就是一个穷屌)


基本来说M1卡的密码有两套,分A套密码和B套密码。每套密码各3个密码。M1的数据块是32位,存16个字符(8个中文字符),用16进制表示(这也是一个很蛋疼的地方,转过去转过来的)。前12位(6个字符)和后12位分别存储A套密码和B套密码,中间8位是控制位(这个是精华,虽然我不懂),这个我是一点也没有懂,深入的东西百度吧,不过资料好像不多的样子。总之来说就是中间的控制位控制6个密码的不同权限,哪一个密码分别对那块数据有读或者写或者读写权限,密码也是被隐藏了的哦,小博主开始还在那纠结呢。这个密码机制就跳过把,反正就是不咋个懂的。请深深的百度


现在来说说那几行代码的事儿吧。


基本功能:实现对M1卡的0扇区数据初始化,修改M1密码。根据已知的密码重置M1密码。


就这么基基本本的功能。作为一个只要实现基本功能的程序博主都没有写UI,直接用DOS执行吧(java写UI也是蛋疼)。仔仔细细的把api看了个遍,就那么几个函数,看起来不难样子。


代码构思:

虽然这么一个简单的功能也不能只写一个java类就完事吧,总体的就两个package:工具包和程序运行主类一个包。


把main函数的入口分离出来单独成一个类(入口级)

把实现循环函数功能的类单独分离出来(一级类)

具体实现设备连接,M1卡初始化功能聚合成一个类(二级类)

D3非接触式读写M1卡几行代码的Java开发_第1张图片

小博把代码贴出来,供君批评吐槽-------------------------------------------------------------------------------------------------------------------------------------------------------------



public class StartMain {
	
	public static void main(String args[]){
		//String[] args = {"445566", "8", "WER3", "6789", "2", "defaultkey"};
		if (null == args || args.length < 5) {
			System.out.println("#####参数错误,请确认参数!#####");
			return;
		}else {
			if (args[5].length() != 6) {
				System.out.println("#####参数错误,密码必须是6为字符,请确认参数!#####");
				return ;
			}else {
				InitMCard IMC = null;
				if (args.length == 5) {
					IMC = new InitMCard(args[0], args[1], args[2],
							Integer.parseInt(args[3]), Integer.parseInt(args[4]), null);
				}else {
					IMC = new InitMCard(args[0], args[1], args[2],
							Integer.parseInt(args[3]), Integer.parseInt(args[4]), args[5]);
				}
				IMC.start();
			}
		}
	}
}



public class EmptyKeyMain {
	
	public static void main(String args[]){
		//String[] args = {"ABCDEF"};
		if (null == args || args.length < 1) {
			System.out.println("#####参数错误,请确认参数!#####");
			return;
		}else {
			InitMCard IMC = null;
			IMC = new InitMCard(args[0]);
			IMC.startEmpty();
		}
	}
}




public class InitMCard {
	
	private static final short sectorNo = 0;
	private static final short[] blockNos = {1};
	
	private String areaCode = null;
	private String type = null;
	private String batchNo = null;
	private int seqStartNo;
	private int seqCount;
	private String initKey = "529656";

	public InitMCard(){}
	
	public InitMCard(String initKey){
		if (null != initKey) {
			this.initKey = initKey;
		}
	}
	
	public InitMCard(String areaCode, String type, String bathNo, int seqStartNo, int seqCount, String initKey) {
		if (null == areaCode || null == type || null == bathNo
				|| areaCode.equals("") || type.equals("") || bathNo.equals("") || seqCount <= 0 || areaCode.length() != 6
				|| type.length() != 1 || bathNo.length() != 4 || seqStartNo <= 0 || seqStartNo>99999) {
			System.out.println("参数输入错误,请重新输入参数!");
			return ;
		}
		this.areaCode = areaCode;
		this.type = type;
		this.batchNo = bathNo;
		this.seqStartNo = seqStartNo;
		this.seqCount = seqCount;
		if (null != initKey) {
			this.initKey = initKey;
		}
	}
	
	/**
	 * 开始初始化方法
	 */
	public void start() {
		if (null == this.areaCode) {
			System.out.println("the end");
			return;
		}
		String[] infos = new String[2];
		int startNo = this.seqStartNo;
		do {
			getData(infos);
			InitData.writeData(sectorNo, blockNos, infos, this.initKey);
			
			this.seqStartNo = startNo + InitData.initCount;
			delay();
		} while (InitData.initCount < this.seqCount);
		System.out.println("the end");
	}

	/**
	 * 清空密码
	 */
	public void startEmpty() {
		do {
			InitData.emptyKey(this.initKey);
			
			delay();
		} while (true);
	}
	
	/**
	 * 延迟程序
	 */
	public void delay() {
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取数据
	 * @param infos
	 */
	public void getData(String[] infos){
		String UID = this.areaCode + this.type + this.batchNo;
		String startNoS = Integer.toString(this.seqStartNo);
		if (startNoS.length() < 5) {
			String s = "";
			for (int i = 0; i < 5-startNoS.length(); i++) {
				s += "0";
			}
			startNoS = s+startNoS;
		}
		if (startNoS.length() > 5) {
			startNoS = startNoS.substring(startNoS.length() - 5, startNoS.length());
		}
		infos[0] = UID + startNoS;
	}
}



public class InitData {
	
	public static int initCount = 0;
	private static final int port = 100;
	private static final int baud = 9600;
	private static final JavaRD800 rd = new JavaRD800();
	private static final short _SearchCardModle = 0;
	private static final short _KeyAuthModle = 0;
	public static char[] defaultKey = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
	private static char[] emptyKey = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x80, 0x69 , 0xFF, 0xFF, 0xFF, 0xFF,0xFF,0xFF};
	
	
	/**
	 * 写入数据
	 * @param sectorNo
	 * @param blockNos
	 * @param infos
	 * @param key
	 */
	public static void writeData (short sectorNo, short[] blockNos, String[] infos, String key){
		int status = 0, icdev = 0;
		int cardID[] = new int[1];
		char[] readBuff = new char[16];
		String card = null;
		//获取设备
		icdev = rd.dc_init(port, baud);
		if (icdev <= 0) {
			System.out.println("######设备绑定端口失败!######");
			return;
		}
		//寻卡
		status = rd.dc_card(icdev, _SearchCardModle, cardID);
		if (status != 0) {
			rd.dc_exit(icdev);
			return;
		} else {
			card = Tool.cardIdInt2String(cardID[0]);
			if (card == null) {
				System.out.println("######M1卡ID获取失败######");
				return ;
			}
			System.out.println("-----------设备ID:"+card);
			status = KeyAuthentication(icdev, sectorNo);
			if (status != 0) {
				System.out.println("######验证密码错误!######");
				rd.dc_beep(icdev, (short) 250);
				rd.dc_exit(icdev);
				return ;
			}
			//获取转换设备ID
			status = rd.dc_read(icdev, (short)0, readBuff);
			if (status != 0) {
				System.out.println("######读取设备ID失败######");
				rd.dc_beep(icdev, (short) 250);
				rd.dc_exit(icdev);
				return ;
			}
			//循环写数据
			for (int i = 0; i < blockNos.length; i++) {
				status = rd.dc_write(icdev, blockNos[i], Tool.stringTochars(infos[i]));
				if (status != 0) {
					rd.dc_beep(icdev, (short) 250);
					System.out.println("######写入第 "+blockNos[i]+"块  错误!######");
					continue;
				}
			}
			if (status != 0) {
				rd.dc_beep(icdev, (short) 250);
				rd.dc_exit(icdev);
				return ;
			}
			
			status = rd.dc_write(icdev, (short)((sectorNo+1)*4-1), Tool.keyStringToChars(key));
			if (status != 0) {
				System.out.println("######初始化密码失败!######");
				rd.dc_exit(icdev);
				return ;
			}
			System.out.println("-----------初始化密码 :" + key);
			
			Tool.saveToLocalFlie(card, infos[0], key);
			Tool.saveToDBURL(card, infos[0], key);
			rd.dc_beep(icdev, (short) 20);
			System.out.println("-------------------------初始化成功");
			initCount++;
		}
		// 关闭设备
		status = rd.dc_exit(icdev);
		if (status != 0) {
			rd.dc_beep(icdev, (short) 250);
			System.out.println("######关闭端口失败!######");
			rd.dc_exit(icdev);
			icdev = 0;
			return;
		}
	}
	
	/**
	 * 密码验证
	 * @param icdev
	 * @param sectorNo
	 * @return
	 */
	private static int KeyAuthentication(int icdev, short sectorNo){

		int t = rd.dc_load_key(icdev, _KeyAuthModle, sectorNo, defaultKey);
		if (t != 0) {
			return t;
		}
		return rd.dc_authentication(icdev, _KeyAuthModle, sectorNo);
	}


	public static void emptyKey(String key){
		InitData.defaultKey = Tool.keyStringToChars(key);
		int status = 0, icdev = 0;
		int cardID[] = new int[1];
		String card = null;
		//获取设备
		icdev = rd.dc_init(port, baud);
		if (icdev <= 0) {
			System.out.println("######设备绑定端口失败!######");
			return;
		}
		//寻卡
		status = rd.dc_card(icdev, _SearchCardModle, cardID);
		if (status != 0) {
			rd.dc_exit(icdev);
			return;
		} else {
			card = Tool.cardIdInt2String(cardID[0]);
			if (card == null) {
				System.out.println("######M1卡ID获取失败######");
				return ;
			}
			System.out.println("-----------设备ID:"+card);
			status = KeyAuthentication(icdev, (short)0);
			if (status != 0) {
				System.out.println("######原始验证密码错误!######");
				rd.dc_beep(icdev, (short) 250);
				rd.dc_exit(icdev);
				return ;
			}
			
			status = rd.dc_write(icdev, (short)3, emptyKey);
			if (status != 0) {
				System.out.println("######重置密码失败!######");
				rd.dc_exit(icdev);
				return ;
			}
			
			rd.dc_beep(icdev, (short) 20);
			System.out.println("-----------已经重置为原始密码 ");
		}
		// 关闭设备
		status = rd.dc_exit(icdev);
		if (status != 0) {
			rd.dc_beep(icdev, (short) 250);
			System.out.println("######关闭端口失败!######");
			rd.dc_exit(icdev);
			icdev = 0;
			return;
		}
	}
}


工具类

public class Tool {
	
	/**
	 * 转换字符串成字符数组
	 * @param source
	 * @return
	 */
	public static char[] stringTochars(String source){
		if (null == source || source.length() == 0) {
			return new char[16];
		}
		byte[] tpBytes = null;
		char[] chars = new char[16];
		try {
			tpBytes = source.getBytes("GBK");
		} catch (UnsupportedEncodingException e) {
			System.out.println("编码失败!");
		}
		for (int i = 0; i < 16; i++) {
			if (i < tpBytes.length) {
				chars[i] = (char)tpBytes[i];
			}else {
				chars[i] = 0x00;
			}
		}
		return chars;
	}
	
	/**
	 * 转换字节数组成字符串
	 * @param source
	 * @return
	 */
	public static String charsToString(char[] source){
		if (null == source || source.length == 0) {
			return null;
		}
		byte[] tpBytes = new byte[16];
		char[] chars = source;
		String ts = "";
		for (int i = 0; i < chars.length; i++) {
			tpBytes[i] = (byte)chars[i];
		}
		try {
			ts = new String(tpBytes, "GBK");
		} catch (UnsupportedEncodingException e) {
			System.out.println("解码失败");
			return new String(tpBytes);
		}
		return ts;
	}
	
	
	/**
	 * 解析卡号
	 * @param source
	 * @return
	 */
	public static String cardIdInt2String(int intCardId){
		String hexCarId = Integer.toHexString(intCardId);
		int t = hexCarId.length();
		if (t % 2 != 0) {
			return null;
		}
		String cardId = "";
		for (; t > 0; t =t-2) {
			cardId += hexCarId.substring(t - 2, t);
		}
		return cardId.toUpperCase();
	}
	
	
	/**
	 * 将密码转换成char[]
	 * @param key
	 * @return
	 */
	public static char[] keyStringToChars(String key){
		char[] defaultKey = {'5', '2', '9', '6', '5', '6', 0xFF, 0x07, 0x80, 0x69 , 0xFF, 0xFF, 0xFF, 0xFF,0xFF,0xFF};
		if (null == key || key.length() < 6) {
			return defaultKey;
		}
		char[] keychar = key.toCharArray();
		for (int i = 0; i < keychar.length; i++) {
			defaultKey[i] = keychar[i];
		}
		return defaultKey;
	}
	
	/**
	 * 保存到本地文件
	 * @param cardID
	 * @param UID
	 * @param key
	 * @return
	 */
	public static boolean saveToLocalFlie(String cardID, String UID, String key){
		if (null == cardID || null == UID || null == key) {
			return false;
		}
		String outString = "\'"+cardID +"\',\'"+UID +"\',\'"+key +"\'\r\n";
		String path = System.getProperty("user.dir")+"\\CardInfo\\";
		String fileName = new SimpleDateFormat("YYYYMMdd").format(new Date())+".txt";
		File file = new File(path);
		if (!file.isDirectory()) {
			file.mkdirs();
		}
		file = new File(path+fileName);
		FileOutputStream fos = null;
		OutputStreamWriter osw = null;
		try {
			if (!file.exists()) {
				file.createNewFile();
			}
			fos = new FileOutputStream(file,true);
			osw = new OutputStreamWriter(fos, "utf-8");
			osw.write(outString, 0, outString.length());
			if (osw != null) {
				osw.close();
			}
			if (fos != null) {
				fos.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
			osw=null;
			fos=null;
			file=null;
			return false;
		}
		osw=null;
		fos=null;
		file=null;
		return true;
	}
	
	/**
	 * 保存到数据库
	 * @param cardID
	 * @param UID
	 * @param key
	 * @return
	 */
	public static boolean saveToDBURL(String cardId, String UID, String key){
		String url = "http://192.168.0.5/jwapp/pub/hntinit/Query/saveCardInfo.srdbexec?cardId="+cardId+"&key="+key+"&UID="+UID;
		PURL purl = new PURL();
		String rt = purl.get(url);
		if (rt == null) {
			return false;
		}
		return true;
	}	
	
	/**
	 * 重文件中根据cardId获取key
	 * @param filePath
	 * @param cardId
	 * @return
	 */
	public static char[] getKeyFromLocal(String filePath, String cardId){
		if (null == filePath || filePath.equals("")) {
			return null;
		}
		char[] keyChar = null;
		File file = new File(filePath);
		if (!file.exists() || !file.isFile()) {
			return null;
		}

		String line = "";
		FileInputStream fis = null;
		BufferedReader bfr = null;
		try {
			fis = new FileInputStream(file);
			bfr = new BufferedReader(new InputStreamReader(fis));
			while ((line = bfr.readLine()) != null) {
				if (line.indexOf(cardId) > 0) {
					keyChar = (line.split(" ")[2]).toCharArray();
				}
			}
		} catch (Exception e) {
		} finally {
			try {
				if (fis != null) {
					fis.close();
				}
				if (bfr != null) {
					bfr.close();
				}
			} catch (Exception e2) {
			}
		}
		return keyChar;
	}
	
	/**
	 * 从远程根据cardId获取密码
	 * @param cardId
	 * @return
	 */
	public static char[] getKeyFromUrl(String cardId){
		String url = "http://192.168.0.5/srdbexec?cardId="+cardId;
		PURL purl = new PURL();
		String rt = purl.get(url);
		
		if (rt == null || rt.substring(rt.indexOf(""), rt.indexOf("")).equals("0")) {
			return null;
		}
		/*从rt中拆分*/
		String keystr = rt.substring(rt.indexOf(""), rt.indexOf(""));
		return keystr.toCharArray();
	}	
	
}



public class PURL {

	public String get(String urlstr) {
		BufferedReader br = null;

		URL url = null;
		StringBuffer ret = new StringBuffer();
		try {
			url = new URL(urlstr);
		} catch (MalformedURLException e) {
			return null;
		}
		if (null != url) {
			try {
				br = new BufferedReader(new InputStreamReader(url.openStream(),
						"UTF-8"));
			} catch (IOException e) {
				return null;
			}
			int s;
			if (null != br) {
				try {
					while ((s = br.read()) != -1) {
						ret.append((char) s);
					}

				} catch (IOException e) {
					return null;
				}
			}
			if (null != br) {
				try {
					br.close();
				} catch (IOException e) {
					return null;
				}
			}
		}
		br = null;
		url = null;
		return ret.toString();
	}

}




你可能感兴趣的:(IT技术)