📄 shaibuttoncopr.java
字号:
/*--------------------------------------------------------------------------- * Copyright (C) 1999-2001 Dallas Semiconductor Corporation, All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Dallas Semiconductor * shall not be used except as stated in the Dallas Semiconductor * Branding Policy. *--------------------------------------------------------------------------- */package com.dalsemi.onewire.application.sha;import java.util.*;import java.io.*;import com.dalsemi.onewire.container.OneWireContainer18;import com.dalsemi.onewire.adapter.OneWireIOException;import com.dalsemi.onewire.OneWireException;import com.dalsemi.onewire.utils.IOHelper;import com.dalsemi.onewire.application.file.OWFile;import com.dalsemi.onewire.application.file.OWFileOutputStream;import com.dalsemi.onewire.application.file.OWFileInputStream;import com.dalsemi.onewire.application.file.OWFileNotFoundException;/** * <P>Class for holding instances of SHA iButton Coprocessors involved in SHA * Transactions. The Coprocessor is used for digitally signing transaction * data as well as generating random challenges for users and verifying * their response.</P> * * <p>A DS1963S SHA iButton can be a <code>SHAiButtonCopr</code> or a * <code>SHAiButtonUser</code>. A Coprocessor iButton verifiessignatures * and signs data for User iButtons. A Coprocessor might be located * inside a vending machine, where a person would bring their User iButton. When * the User iButton is pressed to the Blue Dot to perform a transaction, the Coprocessor * would first verify that this button belongs to the system, i.e. that it knows the same * authentication secret (example: a Visa terminal making sure the iButton had a Visa * account installed). Then the Coprocessor would verify the signed data, probably money, * to make sure it was valid. If someone tried to overwrite the money file, even with a * previously valid money file (an attempt to 'restore' a previous amount of money), the * signed file would be invalid because the signature includes the write cycle counter, * which is incremented every time a page is written to. The write cycle counter is * read-only and does not roll over, so the previous amount of money could not be restored * by rolling the write counter. The Coprocessor verifies the money, then signs a new data * file that contains the new amount of money. </p> * * <p>There are two secrets involved with the transaction process. The first secret is * the authentication secret. It is used to validate a User iButton to a system. The Coprocessor * iButton has the system authentication secret installed. On User iButtons, the * system authentication secret is merged with binding data and the unique address * of the User iButton to create a unique device authentication secret. The second secret * is a signing secret. This secret only exists on the Coprocessor iButton, and is used * to sign and verify transaction data (i.e. money). These secrets are inaccessible outside the * iButton. Once they are installed, they cannot be retrieved.</p> * * <p>This class makes use of several performance enhancements for TINI. * For instance, most methods are <code>synchronized</code> to access instance variable * byte arrays rather than creating new byte arrays every time a transaction * is performed. This could hurt performance in multi-threaded * applications, but the usefulness of having several threads contending * to talk to a single iButton is questionable since the methods in * <code>com.dalsemi.onewire.adapter.DSPortAdapter</code> * <code>beginExclusive(boolean)</code> and <code>endExclusive()</code> should be used.</p> * * @see SHATransaction * @see SHAiButtonUser * * @version 1.00 * @author SKH */public class SHAiButtonCopr{ /** * Turns on extra debugging output */ static final boolean DEBUG = false; // *********************************************************************** // Constants for Error codes // *********************************************************************** public static final int NO_ERROR = 0; public static final int WRITE_DATA_PAGE_FAILED = -1; public static final int WRITE_SCRATCHPAD_FAILED = -2; public static final int MATCH_SCRATCHPAD_FAILED = -3; public static final int ERASE_SCRATCHPAD_FAILED = -4; public static final int COPY_SCRATCHPAD_FAILED = -5; public static final int SHA_FUNCTION_FAILED = -6; public static final int BIND_SECRET_FAILED = -7; // *********************************************************************** /** * Last error code raised */ protected int lastError; /** * Reference to the OneWireContainer */ protected OneWireContainer18 ibc = null; /** * Cache of 1-Wire Address */ protected byte[] address = null; /** * Page used for generating user authentication secret. */ protected int authPageNumber = -1; /** * Any auxilliary data stored on this coprocessor */ protected String auxData; /** * 7 bytes of binding data for scratchpad to bind secret installation */ protected byte[] bindCode = new byte [7]; /** * 32 bytes of binding data to bind secret installation */ protected byte[] bindData = new byte [32]; /** * Specifies whether or not this coprocessor is compatible with * the DS1961S. This entails the use of a specifically padded * authentication secret. */ protected boolean DS1961Scompatible = false; /** * Code used to specify encryption type. */ protected int encCode = -1; /** * Filename, including extension, for user's service file */ protected byte[] filename = new byte[5]; /** * 20 byte initial signature, used for signing user account data */ protected byte[] initialSignature = new byte [20]; /** * The Provider name of the coprocessor's service */ protected String providerName; /** * 3 byte challenge, used for signing user account data */ protected byte[] signingChallenge = new byte [3]; /** * Page used for signing user account data. */ protected int signPageNumber = 8; /** * Code used to specify encryption type. */ protected int version = -1; /** * Page used for generating user's validation MAC. */ protected int wspcPageNumber = -1; // *********************************************************************** // Constructors // *********************************************************************** /** * <p>No default construct for user apps. Coprocessors, unlike users, are * immutable classes, so there is no <code>setiButton</code> for User * applications.</p> * * @see #SHAiButtonCopr(OneWireContainer18,String,boolean,int,int,int,int,int,byte,byte[],byte[],byte[],byte[],byte[],byte[],byte[],byte[],byte[]) * @see #SHAiButtonCopr(OneWireContainer18,String) */ protected SHAiButtonCopr() {;} /** * <P>Sets up this coprocessor object based on the provided parameters * and saves all of these parameters as the contents of the file * <code>coprFilename</code> stored on <code>owc</code>. Then, the * system secret and authentication secret are installed on the * coprocessor button.</P> * * <P>For the proper format of the coprocessor data file, see the * document entitled "Implementing Secured D-Identification and E-Payment * Applications using SHA iButtons". For the format of TMEX file * structures, see Application Note 114.</P> * * @param l_owc The DS1963S used as a coprocessor. * @param coprFilename The TMEX filename where coprocessor configuration * data is stored. Usually, "COPR.0". * @param l_formatDevice boolean indicating whether or not the TMEX * filesystem of this device should be formatted before the * coprocessor data file is stored. * @param l_signPageNumber page number used for signing user account data. * (Should be page 8, but page 0 is acceptable if you don't need * the TMEX directory structure) * @param l_authPageNumber page number used for recreating user secret. * @param l_wspcPageNumber page number used for storing user secret and * recreating authentication MAC. * @param l_version version of the service provided by this coprocessor. * @param l_encCode refers to a type of encryption used for user account * data stored on user buttons. * @param l_serviceFileExt the file extension used for the service file. * (An extension of decimal 102 is reserved for Money files). * @param l_serviceFilename the 4-byte name of the user's account data * file. * @param l_providerName the name of the provider of this service * @param l_bindData the binding data used to finalize secret installation * on user buttons. * @param l_bindCode the binding code used to finalize secret installation * on user buttons. * @param l_auxData any auxilliary or miscellaneous data to be stored on * the coprocessor. * @param l_initialSignature the 20-byte initial MAC placed in user account * data before generating actual MAC. * @param l_signingChlg the 3-byte challenge used for signing user * account data. * @param l_signingSecret the system signing secret used by the * service being installed on this coprocessor. * @param l_authSecret the system authentication secret used by the * service being installed on this coprocessor. * * @throws OneWireIOException on a 1-Wire communication error such as * reading an incorrect CRC from a 1-Wire device. This could be * caused by a physical interruption in the 1-Wire Network due to * shorts or a newly arriving 1-Wire device issuing a 'presence pulse'. * @throws OneWireException on a communication or setup error with the 1-Wire * adapter * * @see #SHAiButtonCopr(OneWireContainer18,String) */ public SHAiButtonCopr (OneWireContainer18 l_owc, String coprFilename, boolean l_formatDevice, int l_signPageNumber, int l_authPageNumber, int l_wspcPageNumber, int l_version, int l_encCode, byte l_serviceFileExt, byte[] l_serviceFilename, byte[] l_providerName, byte[] l_bindData, byte[] l_bindCode, byte[] l_auxData, byte[] l_initialSignature, byte[] l_signingChlg, byte[] l_signingSecret, byte[] l_authSecret) throws OneWireException, OneWireIOException { //clear any errors this.lastError = this.NO_ERROR; // Do some bounds checking on our array data. if(l_bindData.length!=32) throw new OneWireException("Invalid Binding Data"); if(l_bindCode.length!=7) throw new OneWireException("Invalid Binding Code"); if(l_signingChlg.length!=3) throw new OneWireException("Invalid Signing Challenge"); if(l_serviceFilename.length<4) throw new OneWireException("Invalid Service Filename"); if(l_signPageNumber!=0 && l_signPageNumber!=8) throw new OneWireException("Invalid Signing Page Number (must be 0 or 8)"); //Check to see if this coprocessor's authentication secret //is appropriately padded to be used with a DS1961S this.DS1961Scompatible = ((l_authSecret.length%47)==0); int secretDiv = l_authSecret.length/47; for(int j=0; j<secretDiv && DS1961Scompatible; j++) { int offset = 47*j; for(int i=32; i<36 && this.DS1961Scompatible; i++) this.DS1961Scompatible = (l_authSecret[i + offset] == (byte)0x0FF); for(int i=44; i<47 && this.DS1961Scompatible; i++) this.DS1961Scompatible = (l_authSecret[i + offset] == (byte)0x0FF); } //get the current month, date, and year Calendar c = Calendar.getInstance(); int month = c.get(c.MONTH) + 1; int date = c.get(c.DATE); int year = c.get(c.YEAR) - 1900; byte yearMSB = (byte)((year >> 8) & 0x0FF); byte yearLSB = (byte)(year & 0x0FF); try { if(l_formatDevice) { //format if necessary OWFile f = new OWFile(l_owc,coprFilename); f.format(); f.close(); } //Create the service file OWFileOutputStream fos = new OWFileOutputStream(l_owc, coprFilename); fos.write(l_serviceFilename,0,4); fos.write(l_serviceFileExt); fos.write(l_signPageNumber); fos.write(l_authPageNumber); fos.write(l_wspcPageNumber); fos.write(l_version); fos.write(month); fos.write(date); fos.write(yearMSB); fos.write(yearLSB); fos.write(l_bindData); fos.write(l_bindCode); fos.write(l_signingChlg); fos.write((byte)l_providerName.length); fos.write((byte)l_initialSignature.length); fos.write((byte)l_auxData.length); fos.write(l_providerName,0,(byte)l_providerName.length); fos.write(l_initialSignature,0,(byte)l_initialSignature.length); fos.write(l_auxData,0,(byte)l_auxData.length); fos.write(l_encCode); fos.write(DS1961Scompatible?0x55:0x00); fos.flush(); fos.close(); } catch(Exception ioe) { ioe.printStackTrace(); throw new OneWireException("Creating Service File failed!"); } //Install the system signing secret, used to sign and validate all user data if(!l_owc.installMasterSecret(l_signPageNumber, l_signingSecret, l_signPageNumber&7)) throw new OneWireException("Could not install signing secret"); //Install the system authentication secret, used to authenticate users if(!l_owc.installMasterSecret(l_authPageNumber, l_authSecret, l_authPageNumber&7)) throw new OneWireException("Could not install authentication secret"); //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ if(DEBUG) { IOHelper.writeLine("------------------------------------"); IOHelper.writeLine("Initialized Coprocessor"); IOHelper.writeLine("address"); IOHelper.writeBytesHex(l_owc.getAddress()); IOHelper.writeLine("signPageNumber: " + l_signPageNumber); IOHelper.writeLine("authPageNumber: " + l_authPageNumber); IOHelper.writeLine("wspcPageNumber: " + l_wspcPageNumber); IOHelper.writeLine("serviceFilename"); IOHelper.writeBytesHex(l_serviceFilename); IOHelper.writeLine("bindData"); IOHelper.writeBytesHex(l_bindData); IOHelper.writeLine("bindCode"); IOHelper.writeBytesHex(l_bindCode); IOHelper.writeLine("initialSignature"); IOHelper.writeBytesHex(l_initialSignature); IOHelper.writeLine("signingChlg"); IOHelper.writeBytesHex(l_signingChlg); IOHelper.writeLine("signingSecret"); IOHelper.writeBytesHex(l_signingSecret); IOHelper.writeLine("authSecret"); IOHelper.writeBytesHex(l_authSecret); IOHelper.writeLine("------------------------------------"); } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ //Call this method because it will read back the file. Ensuring //there were no errors in writing the file in the first place. this.setiButton(l_owc, coprFilename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -