001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package  org.jpos.security;
020
021import org.jpos.iso.ISOUtil;
022
023import java.io.PrintStream;
024import java.util.regex.Matcher;
025import java.util.regex.Pattern;
026
027/**
028 * The SecureDESKey class represents: <br>
029 * Single, double or triple length DES keys that are secured by a security module.
030 * This is typically the DES key encrypted under one of the Local Master Keys of the
031 * security module.
032 * <p>
033 * SecureDESKey has an extra property "Key Check Value". It allows assuring that
034 * two SecureDESKeys owned by two different parties map
035 * to the same clear key. This can be a useful manual check for successful key
036 * exchange.
037 * <p>
038 * NOTE: The security of SecureDESKey is totally dependent on the security of
039 * the used security module.
040 *
041 * @author Hani S. Kirollos
042 * @author Robert Demski
043 * @see SMAdapter
044 */
045public class SecureDESKey extends SecureVariantKey {
046
047    private static final long serialVersionUID = -9145281998779008306L;
048
049    /**
050     * Regular expression pattern representing key type string value.
051     */
052    protected static final Pattern KEY_TYPE_PATTERN = Pattern.compile("([^:;]*)([:;])?([^:;])?([^:;])?");
053
054    public SecureDESKey() {
055        super();
056    }
057
058    /**
059     * Constructs an SecureDESKey
060     * @param keyLength e.g. LENGTH_DES, LENGTH_DES3_2KEY, LENGTH_DES3_3KEY
061     * @param keyType
062     * @param variant
063     * @param scheme
064     * @param keyBytes DES Key in the secure proprietary format of your security module
065     * @param keyCheckValue
066     * @see SMAdapter
067     */
068    public SecureDESKey (short keyLength, String keyType, byte variant, KeyScheme scheme, byte[] keyBytes,
069            byte[] keyCheckValue) {
070        setKeyLength(keyLength);
071        setKeyType(keyType);
072        setVariant(variant);
073        setScheme(scheme);
074        setKeyBytes(keyBytes);
075        setKeyCheckValue(keyCheckValue);
076    }
077
078    /**
079     * Constructs an SecureDESKey
080     * @param keyLength e.g. LENGTH_DES, LENGTH_DES3_2KEY, LENGTH_DES3_3KEY
081     * @param keyType
082     * @param keyBytes DES Key in the secure proprietary format of your security module
083     * @param keyCheckValue
084     * @see SMAdapter
085     */
086    public SecureDESKey (short keyLength, String keyType, byte[] keyBytes,
087            byte[] keyCheckValue) {
088        setKeyLength(keyLength);
089        setKeyType(keyType);
090        setKeyBytes(keyBytes);
091        setKeyCheckValue(keyCheckValue);
092        getVariant(); //only for set variant with defaults
093        getScheme();  //only set scheme with defaults
094    }
095
096    /**
097     * Constructs an SecureDESKey
098     * @param keyLength
099     * @param keyType
100     * @param keyHexString secure key represented as HexString instead of byte[]
101     * @param keyCheckValueHexString key check value represented as HexString instead of byte[]
102     */
103    public SecureDESKey (short keyLength, String keyType, String keyHexString,
104            String keyCheckValueHexString) {
105        this(keyLength, keyType, ISOUtil.hex2byte(keyHexString), ISOUtil.hex2byte(keyCheckValueHexString));
106    }
107
108    /**
109     * Constructs an SecureDESKey
110     * @param keyLength
111     * @param keyType
112     * @param variant
113     * @param scheme
114     * @param keyHexString secure key represented as HexString instead of byte[]
115     * @param keyCheckValueHexString key check value represented as HexString instead of byte[]
116     */
117    public SecureDESKey (short keyLength, String keyType, byte variant, KeyScheme scheme, String keyHexString,
118            String keyCheckValueHexString) {
119        this(keyLength, keyType, variant, scheme, ISOUtil.hex2byte(keyHexString), ISOUtil.hex2byte(keyCheckValueHexString));
120    }
121
122    @Override
123    public byte getVariant () {
124        if (variant!=null)
125            return variant;
126        /**
127         * Some variant derivation if it hasn't been explicity stated
128         */
129        variant = 0;
130        Matcher m = KEY_TYPE_PATTERN.matcher(keyType);
131        m.find();
132        if (m.group(3) != null)
133            try {
134                variant = Byte.valueOf(m.group(3));
135            } catch (NumberFormatException ex){
136                throw new NumberFormatException("Value "+m.group(4)+" is not valid key variant");
137            }
138        return variant;
139    }
140
141    @Override
142    public KeyScheme getScheme () {
143        if (scheme!=null)
144            return scheme;
145        /**
146         * Some scheme derivation if it hasn't been explicity stated
147         */
148        switch (keyLength){
149            case SMAdapter.LENGTH_DES:
150                scheme = KeyScheme.Z; break;
151            case SMAdapter.LENGTH_DES3_2KEY:
152                scheme = KeyScheme.X; break;
153            case SMAdapter.LENGTH_DES3_3KEY:
154                scheme = KeyScheme.Y; break;
155        }
156        Matcher m = KEY_TYPE_PATTERN.matcher(keyType);
157        m.find();
158        if (m.group(4) != null)
159            try {
160                scheme = KeyScheme.valueOf(m.group(4));
161            } catch (IllegalArgumentException ex){
162                throw new IllegalArgumentException("Value "+m.group(4)+" is not valid key scheme");
163            }
164        return scheme;
165    }
166
167    /**
168     * dumps SecureDESKey basic information
169     * @param p a PrintStream usually supplied by Logger
170     * @param indent indention string, usually suppiled by Logger
171     * @see org.jpos.util.Loggeable
172     */
173    @Override
174    public void dump (PrintStream p, String indent) {
175        String inner = indent + "  ";
176        p.print(indent + "<secure-des-key");
177        p.print(" length=\"" + getKeyLength() + "\"");
178        p.print(" type=\"" + keyType + "\"");
179        p.print(" variant=\"" + getVariant() + "\"");
180        p.print(" scheme=\"" + this.getScheme() + "\"");
181        if (keyName != null)
182            p.print(" name=\"" + keyName + "\"");
183
184        p.println(">");
185        p.println(inner + "<data>" + ISOUtil.hexString(getKeyBytes()) + "</data>");
186        p.println(inner + "<check-value>" + ISOUtil.hexString(getKeyCheckValue()) + "</check-value>");
187        p.println(indent + "</secure-des-key>");
188    }
189}
190
191
192