📄 jcesecuritymodule.java
字号:
/* * jPOS Project [http://jpos.org] * Copyright (C) 2000-2008 Alejandro P. Revilla * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */package org.jpos.security.jceadapter;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.security.Key;import java.security.Provider;import java.security.Security;import java.util.Hashtable;import java.util.Properties;import javax.crypto.SecretKey;import javax.crypto.spec.SecretKeySpec;import org.jpos.core.Configuration;import org.jpos.core.ConfigurationException;import org.jpos.iso.ISOUtil;import org.jpos.security.BaseSMAdapter;import org.jpos.security.EncryptedPIN;import org.jpos.security.SMAdapter;import org.jpos.security.SMException;import org.jpos.security.SecureDESKey;import org.jpos.util.LogEvent;import org.jpos.util.Logger;import org.jpos.util.SimpleMsg;/** * <p> * JCESecurityModule is an implementation of a security module in software. * It doesn't require any hardware device to work.<br> * JCESecurityModule also implements the SMAdapter, so you can view it: either * as a self contained security module adapter that doesn't need a security module * or a security module that plugs directly to jpos, so doesn't need * a separate adapter.<br> * It relies on Java(tm) Cryptography Extension (JCE), hence its name.<br> * JCESecurityModule relies on the JCEHandler class to do the low level JCE work. * </p> * <p> * WARNING: This version of JCESecurityModule is meant for testing purposes and * NOT for life operation, since the Local Master Keys are stored in CLEAR on * the system's disk. Comming versions of JCESecurity Module will rely on * java.security.KeyStore for a better protection of the Local Master Keys. * </p> * @author Hani Samuel Kirollos * @version $Revision: 2594 $ $Date: 2008-01-22 14:41:31 -0200 (Tue, 22 Jan 2008) $ */public class JCESecurityModule extends BaseSMAdapter { /** * Creates an uninitialized JCE Security Module, you need to setConfiguration to initialize it */ public JCESecurityModule () { super(); } /** * @param lmkFile Local Master Keys filename of the JCE Security Module * @throws SMException */ public JCESecurityModule (String lmkFile) throws SMException { init(null, lmkFile, false); } public JCESecurityModule (String lmkFile, String jceProviderClassName) throws SMException { init(jceProviderClassName, lmkFile, false); } public JCESecurityModule (Configuration cfg, Logger logger, String realm) throws ConfigurationException { setLogger(logger, realm); setConfiguration(cfg); } /** * Configures a JCESecurityModule * @param cfg The following properties are read:<br> * lmk: Local Master Keys file (The only required parameter)<br> * jce: JCE Provider Class Name, if not provided, it defaults to: com.sun.crypto.provider.SunJCE<br> * rebuildlmk: (true/false), rebuilds the Local Master Keys file with new keys (WARNING: old keys will be erased)<br> * @throws ConfigurationException */ public void setConfiguration (Configuration cfg) throws ConfigurationException { this.cfg = cfg; try { init(cfg.get("provider"), cfg.get("lmk"), cfg.getBoolean("rebuildlmk")); } catch (SMException e) { throw new ConfigurationException(e); } } public SecureDESKey generateKeyImpl (short keyLength, String keyType) throws SMException { SecureDESKey generatedSecureKey = null; Key generatedClearKey = jceHandler.generateDESKey(keyLength); generatedSecureKey = encryptToLMK(keyLength, keyType, generatedClearKey); return generatedSecureKey; } public SecureDESKey importKeyImpl (short keyLength, String keyType, byte[] encryptedKey, SecureDESKey kek, boolean checkParity) throws SMException { SecureDESKey importedKey = null; // decrypt encrypted key Key clearKEY = jceHandler.decryptDESKey(keyLength, encryptedKey, decryptFromLMK(kek), checkParity); // Encrypt Key under LMK importedKey = encryptToLMK(keyLength, keyType, clearKEY); return importedKey; } public byte[] exportKeyImpl (SecureDESKey key, SecureDESKey kek) throws SMException { byte[] exportedKey = null; // get key in clear Key clearKey = decryptFromLMK(key); // Encrypt key under kek exportedKey = jceHandler.encryptDESKey(key.getKeyLength(), clearKey, decryptFromLMK(kek)); return exportedKey; } public EncryptedPIN encryptPINImpl (String pin, String accountNumber) throws SMException { EncryptedPIN encryptedPIN = null; byte[] clearPINBlock = calculatePINBlock(pin, FORMAT00, accountNumber); // Encrypt byte[] translatedPINBlock = jceHandler.encryptData(clearPINBlock, getLMK(PINLMKIndex)); encryptedPIN = new EncryptedPIN(translatedPINBlock, FORMAT00, accountNumber); return encryptedPIN; } public String decryptPINImpl (EncryptedPIN pinUnderLmk) throws SMException { String pin = null; byte[] clearPINBlock = jceHandler.decryptData(pinUnderLmk.getPINBlock(), getLMK(PINLMKIndex)); pin = calculatePIN(clearPINBlock, pinUnderLmk.getPINBlockFormat(), pinUnderLmk.getAccountNumber()); return pin; } public EncryptedPIN importPINImpl (EncryptedPIN pinUnderKd1, SecureDESKey kd1) throws SMException { EncryptedPIN pinUnderLmk = null; // read inputs String accountNumber = pinUnderKd1.getAccountNumber(); // Use FORMAT00 for encrypting PIN under LMK byte destinationPINBlockFormat = FORMAT00; // get clear PIN byte[] clearPINBlock = jceHandler.decryptData(pinUnderKd1.getPINBlock(), decryptFromLMK(kd1)); // extract clear pin (as entered by card holder) String pin = calculatePIN(clearPINBlock, pinUnderKd1.getPINBlockFormat(), accountNumber); // Format PIN Block using proprietary FORMAT00 to be encrypetd under LMK clearPINBlock = calculatePINBlock(pin, destinationPINBlockFormat, accountNumber); // encrypt PIN byte[] translatedPINBlock = jceHandler.encryptData(clearPINBlock, getLMK(PINLMKIndex)); pinUnderLmk = new EncryptedPIN(translatedPINBlock, destinationPINBlockFormat, accountNumber); return pinUnderLmk; } public EncryptedPIN exportPINImpl (EncryptedPIN pinUnderLmk, SecureDESKey kd2, byte destinationPINBlockFormat) throws SMException { EncryptedPIN exportedPIN = null; String accountNumber = pinUnderLmk.getAccountNumber(); // process // get clear PIN byte[] clearPINBlock = jceHandler.decryptData(pinUnderLmk.getPINBlock(), getLMK(PINLMKIndex)); // extract clear pin String pin = calculatePIN(clearPINBlock, pinUnderLmk.getPINBlockFormat(), accountNumber); clearPINBlock = calculatePINBlock(pin, destinationPINBlockFormat, accountNumber); // encrypt PIN byte[] translatedPINBlock = jceHandler.encryptData(clearPINBlock, decryptFromLMK(kd2)); exportedPIN = new EncryptedPIN(translatedPINBlock, destinationPINBlockFormat, accountNumber); return exportedPIN; } public EncryptedPIN translatePINImpl (EncryptedPIN pinUnderKd1, SecureDESKey kd1, SecureDESKey kd2, byte destinationPINBlockFormat) throws SMException { EncryptedPIN translatedPIN = null; String accountNumber = pinUnderKd1.getAccountNumber(); // get clear PIN byte[] clearPINBlock = jceHandler.decryptData(pinUnderKd1.getPINBlock(), decryptFromLMK(kd1)); String pin = calculatePIN(clearPINBlock, pinUnderKd1.getPINBlockFormat(), accountNumber); // Reformat PIN Block clearPINBlock = calculatePINBlock(pin, destinationPINBlockFormat, accountNumber); // encrypt PIN byte[] translatedPINBlock = jceHandler.encryptData(clearPINBlock, decryptFromLMK(kd2)); translatedPIN = new EncryptedPIN(translatedPINBlock, destinationPINBlockFormat, accountNumber); return translatedPIN; } /** * Generates a random clear key component.<br> * Used by Console, that's why it is package protected. * @param keyLength * @return clear key componenet * @throws SMException */ String generateClearKeyComponent (short keyLength) throws SMException { String clearKeyComponenetHexString; SimpleMsg[] cmdParameters = { new SimpleMsg("parameter", "Key Length", keyLength) }; LogEvent evt = new LogEvent(this, "s-m-operation"); evt.addMessage(new SimpleMsg("command", "Generate Clear Key Component", cmdParameters)); try { Key clearKey = jceHandler.generateDESKey(keyLength); byte[] clearKeyData = jceHandler.extractDESKeyMaterial(keyLength, clearKey); clearKeyComponenetHexString = ISOUtil.hexString(clearKeyData); evt.addMessage(new SimpleMsg("result", "Generated Clear Key Componenet", clearKeyComponenetHexString)); } catch (JCEHandlerException e) { evt.addMessage(e); throw e; } finally { Logger.log(evt); } return clearKeyComponenetHexString; } /** * Generates key check value.<br> * Though not confidential, it is used only by Console, * that's why it is package protected. * @param keyLength * @param keyType * @param KEYunderLMKHexString * @return SecureDESKey object with its check value set * @throws SMException */ SecureDESKey generateKeyCheckValue (short keyLength, String keyType, String KEYunderLMKHexString) throws SMException { SecureDESKey secureDESKey = null; byte[] keyCheckValue; SimpleMsg[] cmdParameters = { new SimpleMsg("parameter", "Key Length", keyLength), new SimpleMsg("parameter", "Key Type", keyType), new SimpleMsg("parameter", "Key under LMK", KEYunderLMKHexString), }; LogEvent evt = new LogEvent(this, "s-m-operation"); evt.addMessage(new SimpleMsg("command", "Generate Key Check Value", cmdParameters)); try { secureDESKey = new SecureDESKey(keyLength, keyType, KEYunderLMKHexString, ""); keyCheckValue = calculateKeyCheckValue(decryptFromLMK(secureDESKey)); secureDESKey.setKeyCheckValue(keyCheckValue); evt.addMessage(new SimpleMsg("result", "Key with Check Value", secureDESKey)); } catch (JCEHandlerException e) { evt.addMessage(e); throw e; } finally { Logger.log(evt); } return secureDESKey; } /** * Forms a key from 3 clear components and returns it encrypted under its corresponding LMK * The corresponding LMK is determined from the keyType * @param keyLength e.g. LENGTH_DES, LENGTH_DES3_2, LENGTH_DES3_3, .. * @param keyType possible values are those defined in the SecurityModule inteface. e.g., ZMK, TMK,... * @param clearComponent1HexString HexString containing the first component * @param clearComponent2HexString HexString containing the second component * @param clearComponent3HexString HexString containing the second component * @return forms an SecureDESKey from two clear components * @throws SMException */ SecureDESKey formKEYfromThreeClearComponents (short keyLength, String keyType, String clearComponent1HexString, String clearComponent2HexString, String clearComponent3HexString) throws SMException { SecureDESKey secureDESKey; SimpleMsg[] cmdParameters = { new SimpleMsg("parameter", "Key Length", keyLength), new SimpleMsg("parameter", "Key Type", keyType), new SimpleMsg("parameter", "Clear Componenent 1", clearComponent1HexString), new SimpleMsg("parameter", "Clear Componenent 2", clearComponent2HexString), new SimpleMsg("parameter", "Clear Componenent 3", clearComponent3HexString) }; LogEvent evt = new LogEvent(this, "s-m-operation"); evt.addMessage(new SimpleMsg("command", "Form Key from Three Clear Components", cmdParameters)); try { byte[] clearComponent1 = ISOUtil.hex2byte(clearComponent1HexString); byte[] clearComponent2 = ISOUtil.hex2byte(clearComponent2HexString); byte[] clearComponent3 = ISOUtil.hex2byte(clearComponent3HexString); byte[] clearKeyBytes = ISOUtil.xor(ISOUtil.xor(clearComponent1, clearComponent2), clearComponent3); Key clearKey = null; clearKey = jceHandler.formDESKey(keyLength, clearKeyBytes); secureDESKey = encryptToLMK(keyLength, keyType, clearKey); evt.addMessage(new SimpleMsg("result", "Formed Key", secureDESKey)); } catch (JCEHandlerException e) { evt.addMessage(e); throw e; } finally { Logger.log(evt); } return secureDESKey; } /** * Calculates a key check value over a clear key * @param key * @return the key check value * @exception SMException */ byte[] calculateKeyCheckValue (Key key) throws SMException { byte[] encryptedZeroBlock = jceHandler.encryptData(zeroBlock, key); byte[] keyCheckValue = ISOUtil.trim(encryptedZeroBlock, 3); return keyCheckValue; } /** * Encrypts a clear DES Key under LMK to form a SecureKey * @param keyLength * @param keyType * @param clearDESKey * @return secureDESKey * @throws SMException */ private SecureDESKey encryptToLMK (short keyLength, String keyType, Key clearDESKey) throws SMException { SecureDESKey secureDESKey = null; byte[] encryptedKeyDataArray = jceHandler.encryptDESKey(keyLength, clearDESKey, getLMK(keyType)); secureDESKey = new SecureDESKey(keyLength, keyType, encryptedKeyDataArray, calculateKeyCheckValue(clearDESKey)); return secureDESKey; } /** * Decrypts a secure DES key from encryption under LMK * @param secureDESKey (Key under LMK) * @return clear key
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -