📄 jcesecuritymodule.java
字号:
* @throws SMException */ private Key decryptFromLMK (SecureDESKey secureDESKey) throws SMException { Key key = null; byte[] keyBytes = secureDESKey.getKeyBytes(); short keyLength = secureDESKey.getKeyLength(); String keyType = secureDESKey.getKeyType(); key = jceHandler.decryptDESKey(keyLength, keyBytes, getLMK(keyType), true); return key; } /** * Calculates the clear PIN Block * @param pin as entered by the card holder on the PIN entry device * @param pinBlockFormat * @param accountNumber (the 12 right-most digits of the account number excluding the check digit) * @return The clear PIN Block * @throws SMException * */ private byte[] calculatePINBlock (String pin, byte pinBlockFormat, String accountNumber) throws SMException { byte[] pinBlock = null; if (pin.length() > MAX_PIN_LENGTH) throw new SMException("Invalid PIN length: " + pin.length()); if (accountNumber.length() != 12) throw new SMException("Invalid Account Number: " + accountNumber + ". The length of the account number must be 12 (the 12 right-most digits of the account number excluding the check digit)"); switch (pinBlockFormat) { case FORMAT00: // same as FORMAT01 case FORMAT01: { // Block 1 String block1 = null; byte[] block1ByteArray; switch (pin.length()) { // pin length then pad with 'F' case 4: block1 = "04" + pin + "FFFFFFFFFF"; break; case 5: block1 = "05" + pin + "FFFFFFFFF"; break; case 6: block1 = "06" + pin + "FFFFFFFF"; break; case 7: block1 = "07" + pin + "FFFFFFF"; break; case 8: block1 = "08" + pin + "FFFFFF"; break; default: throw new SMException("Unsupported PIN Length: " + pin.length()); } block1ByteArray = ISOUtil.hex2byte(block1); // Block 2 String block2; byte[] block2ByteArray = null; block2 = "0000" + accountNumber; block2ByteArray = ISOUtil.hex2byte(block2); // pinBlock pinBlock = ISOUtil.xor(block1ByteArray, block2ByteArray); } ; break; case FORMAT03: { if(pin.length() < 4 || pin.length() > 12) throw new SMException("Unsupported PIN Length: " + pin.length()); pinBlock = ISOUtil.hex2byte ( pin + "FFFFFFFFFFFFFFFF".substring(pin.length(),16) ); } break; default: throw new SMException("Unsupported PIN format: " + pinBlockFormat); } return pinBlock; } /** * Calculates the clear pin (as entered by card holder on the pin entry device) * givin the clear PIN block * @param pinBlock clear PIN Block * @param pinBlockFormat * @param accountNumber * @return the pin * @throws SMException */ private String calculatePIN (byte[] pinBlock, byte pinBlockFormat, String accountNumber) throws SMException { String pin = null; int pinLength; if (accountNumber.length() != 12) throw new SMException("Invalid Account Number: " + accountNumber + ". The length of the account number must be 12 (the 12 right-most digits of the account number excluding the check digit)"); switch (pinBlockFormat) { case FORMAT00: // same as format 01 case FORMAT01: { // Block 2 String block2; block2 = "0000" + accountNumber; byte[] block2ByteArray = ISOUtil.hex2byte(block2); // get Block1 byte[] block1ByteArray = ISOUtil.xor(pinBlock, block2ByteArray); pinLength = Math.abs (block1ByteArray[0]); if (pinLength > MAX_PIN_LENGTH) throw new SMException("PIN Block Error"); // get pin String pinBlockHexString = ISOUtil.hexString(block1ByteArray); pin = pinBlockHexString.substring(2, pinLength + 2); String pad = pinBlockHexString.substring(pinLength + 2); pad = pad.toUpperCase(); int i = pad.length(); while (--i >= 0) if (pad.charAt(i) != 'F') throw new SMException("PIN Block Error"); } break; case FORMAT03: { String block1 = ISOUtil.hexString(pinBlock); int len = block1.indexOf('F'); if(len == -1) len = 12; int i = block1.length(); pin = block1.substring(0, len); while(--i >= len) if(block1.charAt(i) != 'F') throw new SMException("PIN Block Error"); while(--i >= 0) if(pin.charAt(i) >= 'A') throw new SMException("PIN Block Error"); if(pin.length() < 4 || pin.length() > 12) throw new SMException("Unsupported PIN Length: " + pin.length()); } break; default: throw new SMException("Unsupported PIN Block format: " + pinBlockFormat); } return pin; } /** * Initializes the JCE Security Module * @param jceProviderClassName * @param lmkFile Local Master Keys File used by JCE Security Module to store the LMKs * @param lmkRebuild if set to true, the lmkFile gets overwritten with newly generated keys (WARNING: this would render all your previously stored SecureKeys unusable) * @throws SMException */ private void init (String jceProviderClassName, String lmkFile, boolean lmkRebuild) throws SMException { File lmk = new File(lmkFile); try { keyTypeToLMKIndex = new Hashtable(); keyTypeToLMKIndex.put(SMAdapter.TYPE_ZMK, new Integer(0)); keyTypeToLMKIndex.put(SMAdapter.TYPE_ZPK, new Integer(1)); keyTypeToLMKIndex.put(SMAdapter.TYPE_PVK, new Integer(2)); keyTypeToLMKIndex.put(SMAdapter.TYPE_TPK, new Integer(2)); keyTypeToLMKIndex.put(SMAdapter.TYPE_TMK, new Integer(2)); keyTypeToLMKIndex.put(SMAdapter.TYPE_TAK, new Integer(3)); keyTypeToLMKIndex.put(PINLMKIndex, new Integer(4)); keyTypeToLMKIndex.put(SMAdapter.TYPE_CVK, new Integer(5)); keyTypeToLMKIndex.put(SMAdapter.TYPE_ZAK, new Integer(8)); keyTypeToLMKIndex.put(SMAdapter.TYPE_BDK, new Integer(9)); Provider provider = null; LogEvent evt = new LogEvent(this, "jce-provider"); try { if ((jceProviderClassName == null) || (jceProviderClassName.compareTo("") == 0)) { evt.addMessage("No JCE Provider specified. Attempting to load default provider (SunJCE)."); jceProviderClassName = "com.sun.crypto.provider.SunJCE"; } provider = (Provider)Class.forName(jceProviderClassName).newInstance(); Security.addProvider(provider); evt.addMessage("name", provider.getName()); } catch (Exception e) { evt.addMessage(e); throw new SMException("Unable to load jce provider whose class name is: " + jceProviderClassName); } finally { Logger.log(evt); } jceHandler = new JCEHandler(provider); // Load Local Master Keys Properties lmkProps = new Properties(); if (lmkRebuild) { // Creat new LMK file evt = new LogEvent(this, "local-master-keys"); evt.addMessage("Rebuilding new Local Master Keys in file: \"" + lmk.getCanonicalPath() + "\"."); Logger.log(evt); // Generate New random Local Master Keys generateLMK(); // Write the new Local Master Keys to file writeLMK(lmk); evt = new LogEvent(this, "local-master-keys"); evt.addMessage("Local Master Keys built successfully in file: \"" + lmk.getCanonicalPath() + "\"."); Logger.log(evt); } if (!lmk.exists()) { // LMK File does not exist throw new SMException("Error loading Local Master Keys, file: \"" + lmk.getCanonicalPath() + "\" does not exist." + " Please specify a valid LMK file, or rebuild a new one."); } else { // Read LMK from file readLMK(lmk); evt = new LogEvent(this, "local-master-keys"); evt.addMessage("Loaded successfully from file: \"" + lmk.getCanonicalPath() + "\""); Logger.log(evt); } } catch (Exception e) { if (e instanceof SMException) { throw (SMException)e; } else { throw new SMException(e); } } } /** * Generates new LMK keys * @exception SMException */ private void generateLMK () throws SMException { LMK = new SecretKey[0x0f]; try { LMK[0x00] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x01] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x02] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x03] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x04] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x05] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x06] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x07] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x08] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x09] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x0a] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x0b] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x0c] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x0d] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); LMK[0x0e] = (SecretKey)jceHandler.generateDESKey(LMK_KEY_LENGTH); } catch (JCEHandlerException e) { throw new SMException("Can't generate Local Master Keys", e); } } /** * reads (loads) LMK's from lmkFile * @param lmkFile * @exception SMException */ private void readLMK (File lmkFile) throws SMException { LMK = new SecretKey[0x0f]; try { Properties lmkProps = new Properties(); FileInputStream in = new FileInputStream(lmkFile); lmkProps.load(in); in.close(); byte[] lmkData; for (int i = 0x00; i < 0x0f; i++) { lmkData = ISOUtil.hex2byte(lmkProps.getProperty("LMK0x0" + Integer.toHexString(i))); // provider-independent method LMK[i] = new SecretKeySpec(lmkData, JCEHandler.ALG_TRIPLE_DES); } } catch (Exception e) { throw new SMException("Can't read Local Master Keys from file: " + lmkFile, e); } } /** * Writes a newly generated LMK's to lmkFile * @param lmkFile * @exception SMException */ private void writeLMK (File lmkFile) throws SMException { Properties lmkProps = new Properties(); try { for (int i = 0x00; i < 0x0f; i++) { lmkProps.setProperty("LMK0x0" + Integer.toHexString(i), ISOUtil.hexString(LMK[i].getEncoded())); } FileOutputStream out = new FileOutputStream(lmkFile); lmkProps.store(out, "Local Master Keys"); out.close(); } catch (Exception e) { throw new SMException("Can't write Local Master Keys to file: " + lmkFile, e); } } /** * gets the suitable LMK for the key type * @param keyType * @return the LMK secret key for the givin key type * @throws SMException */ private SecretKey getLMK (String keyType) throws SMException { //int lmkIndex = keyType; if (!keyTypeToLMKIndex.containsKey(keyType)) { throw new SMException("Unsupported key type: " + keyType); } int lmkIndex = ((Integer)keyTypeToLMKIndex.get(keyType)).intValue(); SecretKey lmk = null; try { lmk = LMK[lmkIndex]; } catch (Exception e) { throw new SMException("Invalid key code: " + "LMK0x0" + Integer.toHexString(lmkIndex)); } return lmk; } /** * maps a key type to an LMK Index */ private Hashtable keyTypeToLMKIndex; /** * The clear Local Master Keys */ private SecretKey[] LMK; /** * A name for the LMK used to encrypt the PINs */ private static final String PINLMKIndex = "PIN"; /** * The key length (in bits) of the Local Master Keys. * JCESecurityModule uses Triple DES Local Master Keys */ private static final short LMK_KEY_LENGTH = LENGTH_DES3_2KEY; /** * The maximum length of the PIN */ private static final short MAX_PIN_LENGTH = 12; /** * a dummy 64-bit block of zeros used when calculating the check value */ private static final byte[] zeroBlock = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }; private JCEHandler jceHandler;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -