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 java.io.Serializable;
022import java.util.Collections;
023import java.util.LinkedHashMap;
024import java.util.Map;
025import java.util.Objects;
026import org.jpos.iso.ISOUtil;
027
028/**
029 * Defines the primary usage of the key contained in the key block.
030 * <p>
031 * Each value repesents bytes 5-6 of the keyblock header.
032 */
033public class KeyUsage implements Serializable {
034
035    private static final long serialVersionUID = -5504819939017756749L;
036
037    protected static final Map<String, KeyUsage> TR31MAP =  new LinkedHashMap<>();
038
039    /**
040     * TR-31 BDK Base Derivation Key.
041     */
042    public final static KeyUsage BDK       = create("B0", "BDK - Base Derivation Key");
043
044    /**
045     * TR-31 DUKPT Initial Key (IKEY aka IPEK).
046     */
047    public final static KeyUsage IKEY      = create("B1", "IKEY - DUKPT Initial Key");
048
049    /**
050     * TR-31 CVK Card Verification Key.
051     */
052    public final static KeyUsage CVK       = create("C0", "CVK - Card Verification Key");
053
054    /**
055     * TR-31 Data Encryption Key.
056     */
057    public final static KeyUsage ENC       = create("D0", "Data Encryption Key");
058
059    /**
060     * TR-31 Initialization Value.
061     * <p>
062     * Used for protect eg. Initalization Vector or Decimalization Table.
063     */
064    public final static KeyUsage INIT      = create("I0", "Initialization Value");
065
066    /**
067     * TR-31 Generic Key Encryption / Wrapping Key.
068     */
069    public final static KeyUsage KEK       = create("K0", "Key Encryption / Wrapping Key");
070
071    /**
072     * TR-31 Key Block Protection Key.
073     */
074    public final static KeyUsage KEKWRAP   = create("K1", "Key Block Protection Key");
075
076    /**
077     * TR-31 ISO 16609 MAC algorithm 1 Key <i>(using 3-DES)</i>.
078     */
079    public final static KeyUsage ISOMAC0   = create("M0", "ISO 16609 MAC algorithm 1 Key");
080
081    /**
082     * TR-31 ISO 9797-1 MAC algorithm 1 Key.
083     */
084    public final static KeyUsage ISOMAC1   = create("M1", "ISO 9797-1 MAC algorithm 1 Key");
085
086    /**
087     * TR-31 ISO 9797-1 MAC algorithm 2 Key.
088     */
089    public final static KeyUsage ISOMAC2   = create("M2", "ISO 9797-1 MAC algorithm 2 Key");
090
091    /**
092     * TR-31 ISO 9797-1 MAC algorithm 3 Key.
093     */
094    public final static KeyUsage ISOMAC3   = create("M3", "ISO 9797-1 MAC algorithm 3 Key");
095
096    /**
097     * TR-31 ISO 9797-1 MAC algorithm 4 Key.
098     */
099    public final static KeyUsage ISOMAC4   = create("M4", "ISO 9797-1 MAC algorithm 4 Key");
100
101    /**
102     * TR-31 ISO 9797-1 MAC algorithm 5 Key.
103     */
104    public final static KeyUsage ISOMAC5   = create("M5", "ISO 9797-1 MAC algorithm 5 Key");
105
106    /**
107     * TR-31 Generic PIN Encription Key.
108     */
109    public final static KeyUsage PINENC    = create("P0", "PIN encryption key");
110
111    /**
112     * TR-31 Generic PIN Verification Key.
113     */
114    public final static KeyUsage PINVER    = create("V0", "PIN verification key or other algorithm");
115
116    /**
117     * TR-31 PIN Verification Key (IBM 3624 algorithm).
118     */
119    public final static KeyUsage PINV3624  = create("V1", "PIN verification key, IBM 3624 algorithm");
120
121    /**
122     * TR-31 PIN Verification Key (Visa PVV algorithm).
123     */
124    public final static KeyUsage VISAPVV   = create("V2", "PIN verification key, VISA PVV algorithm");
125
126    /**
127     * TR-31 Application Cryptograms Key.
128     */
129    public final static KeyUsage EMVACMK   = create("E0", "EMV/Chip card Master Key, MKAC - Application Cryptogram");
130
131    /**
132     * TR-31 Secure Messaging for Confidentiality Key.
133     */
134    public final static KeyUsage EMVSCMK   = create("E1", "EMV/Chip card Master Key, MKSMC - Secure Messaging for Confidentiality");
135
136    /**
137     * TR-31 Secure Messaging for Integrity.
138     */
139    public final static KeyUsage EMVSIMK   = create("E2", "EMV/Chip card Master Key, MKSMI - Secure Messaging for Integrity");
140
141    /**
142     * TR-31 Data Authentication Code Key.
143     */
144    public final static KeyUsage EMVDAMK   = create("E3", "EMV/Chip card Master Key, MKDAC - Data Authentication Code");
145
146    /**
147     * TR-31 Dynamic Numbers Key.
148     */
149    public final static KeyUsage EMVDNMK   = create("E4", "EMV/Chip card Master Key, MKDN - Dynamic Numbers");
150
151    /**
152     * TR-31 Card Personalization Key.
153     */
154    public final static KeyUsage EMVCPMK   = create("E5", "EMV/Chip card Master Key, Card Personalization");
155
156    /**
157     * TR-31 Chip card Master Key.
158     */
159    public final static KeyUsage EMVOTMK   = create("E6", "EMV/Chip card Master Key, Other");
160
161    /**
162     * TR-31 Master Personalization Key.
163     */
164    public final static KeyUsage EMVMPMK   = create("E7", "EMV/Master Personalization Key");
165
166
167    private final String code;
168    private final String name;
169
170    /**
171     * Internal constructor.
172     * <p>
173     * The constructor is protected to guarantee only one instance of the key
174     * usage in the entire JVM. This makes it possible to use the operator
175     * {@code ==} or {@code !=} as it does for enums.
176     *
177     * @param code the key usage code
178     * @param name the usage name
179     */
180    protected KeyUsage(String code, String name) {
181        Objects.requireNonNull(code, "The code of key usage is required");
182        Objects.requireNonNull(name, "The name of key usage is required");
183        if (code.length() != 2)  //The length of the code must be 2
184            throw new IllegalArgumentException("The length of the key block Key Usage code must be 2");
185
186        this.code = code;
187        this.name = name;
188    }
189
190    private static KeyUsage create(String code, String name) {
191        KeyUsage ku = new KeyUsage(code, name);
192        if (ISOUtil.isNumeric(code, 10))
193            throw new IllegalArgumentException(
194                "The TR-31 Key Usage code can not consist of digits only"
195            );
196        if (TR31MAP.containsKey(ku.getCode()))
197            throw new IllegalArgumentException(
198                "The TR-31 Key Usage code can by registered only once"
199            );
200        TR31MAP.put(ku.getCode(), ku);
201        return ku;
202    }
203
204    /**
205     * Get key usage code.
206     *
207     * @return two characters which represents key usage code
208     */
209    public String getCode() {
210        return code;
211    }
212
213    /**
214     * Get key usage name.
215     *
216     * @return the key usage name
217     */
218    public String getName() {
219        return name;
220    }
221
222    @Override
223    public String toString() {
224        return String.format("KeyUsage[code: %s, name: %s]", code, name);
225    }
226
227    /**
228     * Returns the enum constant of this type with the specified {@code code}.
229     *
230     * @param code
231     * @return the enum constant with the specified processing code or
232     *         {@code null} if unknown.
233     */
234    public static KeyUsage valueOfByCode(String code) {
235        return TR31MAP.get(code);
236    }
237
238    public static Map<String, KeyUsage> entries() {
239        return Collections.unmodifiableMap(TR31MAP);
240    }
241
242}